我正在尝试翻转使用NSImageBitmapRep表示创建的NSImage。经过一些挖掘(Flipping Quicktime preview & capture和Mirroring 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];
然后使用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];
两种方式都会产生空白图像。我也尝试翻译图像,以防因为-1次缩放而出现在屏幕外,但无济于事。如果我使用正值进行缩放,我可以看到正确应用了变换。
self.ivImage是一个NSImageView。我想要一个翻转的实际NSImage,因此不应该将转换应用于NSImageView。
这是32位,Lion上的Xcode 4.3.2。
答案 0 :(得分:8)
您应该使用大小初始化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];
答案 1 :(得分:5)
无论如何,我认为一个好主意应该是发布一个完整的功能。这是我基于Ken post的解决方案
- (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;
}
答案 2 :(得分:3)
垂直翻转
- (NSImage *)flipImageVertically:(NSImage *)inputImage {
NSImage *tmpImage;
NSAffineTransform *transform = [NSAffineTransform transform];
NSSize dimensions = [inputImage size];
NSAffineTransformStruct flip = {1.0, 0.0, 0.0, -1.0, 0.0,
dimensions.height};
tmpImage = [[NSImage alloc] initWithSize:dimensions];
[tmpImage lockFocus];
[transform setTransformStruct:flip];
[transform concat];
[inputImage drawAtPoint:NSMakePoint(0,0)
fromRect:NSMakeRect(0,0, dimensions.width, dimensions.height)
operation:NSCompositeCopy fraction:1.0];
[tmpImage unlockFocus];
return [tmpImage autorelease];
}
用于水平翻转
+ (NSImage *)flipImageHorizontally:(NSImage *)inputImage {
NSImage *tmpImage;
NSAffineTransform *transform = [NSAffineTransform transform];
NSSize dimensions = [inputImage size];
NSAffineTransformStruct flip = {-1.0, 0.0, 0.0, 1.0,
dimensions.width, 0.0 };
tmpImage = [[NSImage alloc] initWithSize:dimensions];
[tmpImage lockFocus];
[transform setTransformStruct:flip];
[transform concat];
[inputImage drawAtPoint:NSMakePoint(0,0)
fromRect:NSMakeRect(0,0, dimensions.width, dimensions.height)
operation:NSCompositeCopy fraction:1.0];
[tmpImage unlockFocus];
return [tmpImage autorelease];
}
答案 3 :(得分:0)
基于the solution of Alejandro Lugeno的Swift扩展:
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
}
}