【问题标题】:How to shift image horizontally to create loop effect?如何水平移动图像以创建循环效果?
【发布时间】:2019-05-22 18:28:31
【问题描述】:

如何水平移动 NSImage,使移动的像素出现在另一侧,使其看起来像一个循环? 目前我正在使用drawInRect。是否有任何 CIFilter 或更智能的方法可以做到这一点?

- (CIImage *)image:(NSImage *)image shiftedBy:(CGFloat)shiftAmount
{

    NSUInteger width = image.size.width;
    NSUInteger height = image.size.height;
    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                  pixelsWide:width
                                                  pixelsHigh:height
                                               bitsPerSample:8
                                             samplesPerPixel:4
                                                    hasAlpha:YES
                                                    isPlanar:NO
                                              colorSpaceName:NSDeviceRGBColorSpace
                                                 bytesPerRow:0
                                                bitsPerPixel:0];
    [rep setSize:NSMakeSize(width, height)];
    [NSGraphicsContext saveGraphicsState];
    NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep];
    [NSGraphicsContext setCurrentContext:context];


    CGRect rect0 = CGRectMake(0, 0, width, height);
    CGRect leftSourceRect, rightSourceRect;
    CGRectDivide(rect0, &leftSourceRect, &rightSourceRect, shiftAmount, CGRectMinXEdge);
    CGRect rightDestinationRect = CGRectOffset(leftSourceRect, width - rightSourceRect.origin.x, 0);
    CGRect leftDestinationRect = rightSourceRect;
    leftDestinationRect.origin.x = 0;

    [image drawInRect:leftDestinationRect fromRect:rightSourceRect operation:NSCompositingOperationSourceOver fraction:1.0];
    [image drawInRect:rightDestinationRect fromRect:leftSourceRect operation:NSCompositingOperationSourceOver fraction:1.0];

    [NSGraphicsContext restoreGraphicsState];
    return [[CIImage alloc] initWithBitmapImageRep:rep];
}

【问题讨论】:

  • 看起来您可以使用CIAffineTile 来做到这一点。
  • 我只会使用图像的两个副本和两个图像视图,然后滑动它们,并进行剪辑。
  • @matt 谢谢。我已经将它用于屏幕绘图(CALayers)。只是在保存到磁盘时寻找“更智能”。

标签: cocoa nsimage cifilter


【解决方案1】:

我使用 CIFilter 进行了尝试,但是性能下降了 3-4 倍。但是,代码更具可读性。

- (CIImage *)image:(NSImage *)image shiftXBy:(CGFloat)shiftX YBy:(CGFloat)shiftY
{
    //avoid calling TIFFRepresentation here cause the performance hit is even bigger
    CIImage *ciImage = [[CIImage alloc] initWithData:[image TIFFRepresentation]];
    CGAffineTransform xform = CGAffineTransformIdentity;
    NSValue *xformObj = [NSValue valueWithBytes:&xform objCType:@encode(CGAffineTransform)];
    ciImage = [ciImage imageByApplyingFilter:@"CIAffineTile"
                         withInputParameters:@{kCIInputTransformKey : xformObj} ];
    ciImage = [ciImage imageByCroppingToRect:CGRectMake(shiftX, shiftY, image.size.width, image.size.height)];
    return ciImage;
}

【讨论】:

  • CIFilter 很快。渲染到 NSImage 很慢。
【解决方案2】:

为了获得最佳性能,您需要使用 CALayer。这是基本概念:

  • 您的NSView 子类应将wantsLayerlayerUsesCoreImageFilters 设置为true
  • 将您的图像分配给NSView.layercontent 属性(或添加新的子图层)。
  • 创建CIAffineTile 过滤器并将其添加到图层中。

现在您可以更改过滤器的值,而无需重新加载或重绘图像。这一切都将是硬件加速的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    相关资源
    最近更新 更多