0

如何水平移动 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];
}
4

2 回答 2

0

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

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

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

于 2018-12-25T12:38:18.870 回答
0

我用 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;
}
于 2018-12-23T16:49:33.103 回答