在两个轴上翻转NSImage

mso*_*ohn 6 macos cocoa core-image nsimage

我正在尝试翻转使用NSImageBitmapRep表示创建的NSImage.经过一些挖掘(翻转Quicktime预览和捕获以及镜像CIImage/NSImage)后,我通过CIImage尝试了两种方法,并对这两个因子应用了-1的缩放变换.

首先使用CIImage imageByApplyingTransform:

    NSBitmapImageRep *imgRep = ...
    CGImageRef cgi = [imgRep CGImage];
    CIImage *cii = [CIImage imageWithCGImage:cgi];
    CGAffineTransform at = CGAffineTransformTranslate(CGAffineTransformMakeScale(-1, -1), 0, 0);
    NSCIImageRep *ciiRep = [NSCIImageRep imageRepWithCIImage:[cii imageByApplyingTransform:at]];

    NSImage *img = [[[NSImage alloc] init] autorelease];
    [img addRepresentation:ciiRep];
    [self.ivImage setImage:img];
Run Code Online (Sandbox Code Playgroud)

然后使用CIAffineTransform过滤器:

    NSBitmapImageRep *imgRep = ...
    CGImageRef cgi = [imgRep CGImage];
    CIImage *cii = [CIImage imageWithCGImage:cgi];
    CIFilter *f = [CIFilter filterWithName:@"CIAffineTransform"];
    NSAffineTransform *t = [NSAffineTransform transform];
    [t scaleXBy:1.0 yBy:1.0];
    //[t translateXBy:width yBy:0];
    [f setValue:t forKey:@"inputTransform"];
    [f setValue:cii forKey:@"inputImage"];
    CIImage *cii2 = [f valueForKey:@"outputImage"];
    NSCIImageRep *ciiRep = [NSCIImageRep imageRepWithCIImage:cii2];

    NSImage *img = [[[NSImage alloc] init] autorelease];
    [img addRepresentation:ciiRep];
    [self.ivImage setImage:img];
Run Code Online (Sandbox Code Playgroud)

两种方式都会产生空白图像.我也尝试翻译图像,以防因为-1次缩放而出现在屏幕外,但无济于事.如果我使用正值进行缩放,我可以看到正确应用了变换.

self.ivImage是一个NSImageView.我想要一个翻转的实际NSImage,因此不应该将转换应用于NSImageView.

这是32位,Lion上的Xcode 4.3.2.

Ken*_*ses 9

你应该NSImage用一个大小来初始化你.

通过翻译展示您的尝试,因为这是正确的方式.通常,首先进行翻译然后进行缩放最容易.您的代码片段似乎有翻译尝试的残余痕迹,但它们并不正确.您在一个案例和宽度中翻译0,0,在另一个案例和宽度中翻译0.此外,在您的第二个代码段中,您缩放1,1(正),因此不会翻转.

此外,简单地将焦点锁定在适当大小的新图像上,设置变换并绘制图像代表可能更简单.避免使用所有这些东西CIImage.

NSBitmapImageRep *imgRep = ...
NSImage* img = [[[NSImage alloc] initWithSize:NSMakeSize(imgRep.pixelsWide, imgRep.pixelsHigh)] autorelease];
[img lockFocus];
NSAffineTransform* t = [NSAffineTransform transform];
[t translateXBy:imgRep.pixelsWide yBy:imgRep.pixelsHigh];
[t scaleXBy:-1 yBy:-1];
[t concat];
[imgRep drawInRect:NSMakeRect(0, 0, imgRep.pixelsWide, imgRep.pixelsHigh)];
[img unlockFocus];
Run Code Online (Sandbox Code Playgroud)


Ale*_*ngo 6

无论如何,我认为一个好主意应该是发布一个完整的功能.这是我基于Ken帖子的解决方案

- (NSImage *)flipImage:(NSImage *)image
{
    NSImage *existingImage = image;
    NSSize existingSize = [existingImage size];
    NSSize newSize = NSMakeSize(existingSize.width, existingSize.height);
    NSImage *flipedImage = [[[NSImage alloc] initWithSize:newSize] autorelease];

    [flipedImage lockFocus];
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];

    NSAffineTransform *t = [NSAffineTransform transform];
    [t translateXBy:existingSize.width yBy:existingSize.height];
    [t scaleXBy:-1 yBy:-1];
    [t concat];

    [existingImage drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositeSourceOver fraction:1.0];

    [flipedImage unlockFocus];

    return flipedImage;
}
Run Code Online (Sandbox Code Playgroud)


Tam*_*gel 6

Swift 的扩展,基于Alejandro Lugeno 的解决方案

extension NSImage {
    func flipped(flipHorizontally: Bool = false, flipVertically: Bool = false) -> NSImage {
        let flippedImage = NSImage(size: size)

        flippedImage.lockFocus()

        NSGraphicsContext.current?.imageInterpolation = .high

        let transform = NSAffineTransform()
        transform.translateX(by: flipHorizontally ? size.width : 0, yBy: flipVertically ? size.height : 0)
        transform.scaleX(by: flipHorizontally ? -1 : 1, yBy: flipVertically ? -1 : 1)
        transform.concat()

        draw(at: .zero, from: NSRect(origin: .zero, size: size), operation: .sourceOver, fraction: 1)

        flippedImage.unlockFocus()

        return flippedImage
    }
}
Run Code Online (Sandbox Code Playgroud)