我有一个UIView,我试图使用[CALayer renderInContext:]渲染到UIImage中。但是,我发现结果图像是垂直翻转的。由于坐标系不同,我有点期待这一点。然而,我尝试用仿射变换将上下文恢复正常 - 但它没有任何效果:
CGAffineTransform flipVertical = CGAffineTransformMake(
1, 0, 0, -1, 0, imageContextHeight
);
CGContextConcatCTM(imageContext, flipVertical);
CGImageRef cgImage = CGBitmapContextCreateImage(imageContext);
UIImage* uiImage = [[UIImage imageWithCGImage:cgImage] retain];
CGImageRelease(cgImage);
我做错了什么?
答案 0 :(得分:32)
以下是我根据这个答案编写的一些代码,以防它对任何人都有帮助:
#import <QuartzCore/QuartzCore.h>
...
+ (UIImage *) flipImageVertically:(UIImage *)originalImage {
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:originalImage];
UIGraphicsBeginImageContext(tempImageView.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform flipVertical = CGAffineTransformMake(
1, 0, 0, -1, 0, tempImageView.frame.size.height
);
CGContextConcatCTM(context, flipVertical);
[tempImageView.layer renderInContext:context];
UIImage *flipedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[tempImageView release];
return flipedImage;
}
答案 1 :(得分:29)
CTM影响未来的绘图;你正在捕捉已经画出的东西。你需要在绘制之前连接转换,而不是在之后。
答案 2 :(得分:6)
这是与上面相同的代码(benvolioT的答案),但在SWIFT 4.0中
import QuartzCore
...
func flipImageVertically(originalImage:UIImage) -> UIImage{
let tempImageView:UIImageView = UIImageView(image: originalImage)
UIGraphicsBeginImageContext(tempImageView.frame.size)
let context:CGContext = UIGraphicsGetCurrentContext()!
let flipVertical: CGAffineTransform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: tempImageView.frame.size.height)
context.concatenate(flipVertical)
tempImageView.layer.render(in: context)
let flippedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return flippedImage
}
这是SWIFT中更好的方法:
func flipImageVertically(originalImage:UIImage) -> UIImage {
let image:UIImage = UIImage(CGImage: originalImage.CGImage, scale: 1.0, orientation: UIImageOrientation.RightMirrored)!
return image
}
答案 3 :(得分:1)
我在swift中使用此代码:
UIGraphicsBeginImageContextWithOptions(myImageView.image!.size, false, 1.0)
var context = UIGraphicsGetCurrentContext()
//move and invert canvas by scaling
CGContextTranslateCTM(context, myImageView.image!.size.width, 0)
CGContextScaleCTM(context, -1, 1)
myImageView.image!.drawInRect(CGRect(x: 0, y: 0, width: myImageView.image!.size.width, height: myImageView.image!.size.height))
// move back and reinvert
CGContextScaleCTM(context, 1, 1)
CGContextTranslateCTM(context, -myImageView.image!.size.width, 0)
let flippedImg = UIGraphicsGetImageFromCurrentImageContext()
myImageView.image = flippedImg
UIGraphicsEndImageContext()
答案 4 :(得分:1)
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: originalImage.size.height)
ctx.concatenate(flipVertical)
答案 5 :(得分:1)
在Swift 4中使用此功能:
func drawImage(image: UIImage) -> UIImage {
// Setup our context
let opaque = false
let scale: CGFloat = 0 // 0 means we use scale factor of the device’s main screen.
UIGraphicsBeginImageContextWithOptions(image.size, opaque, scale)
let context = UIGraphicsGetCurrentContext()!
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: image.size.height)
context.concatenate(flipVertical) // flip by y
// draw your another figures
//...
// Drawing complete, set context to image and finish
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
答案 6 :(得分:1)
Swift 5扩展程序:
import CoreGraphics
extension CGContext {
/// Transforms the user coordinate system in a context
/// such that the y-axis is flipped.
func flipYAxis() {
concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty:
CGFloat(height)/abs(userSpaceToDeviceSpaceTransform.d)))
}
}
答案 7 :(得分:1)
快速版本获得 y 翻转仿射矩阵:
let t1 = CGAffineTransform(scaleX: 1, y: -1)
let t = t1.translatedBy(x: 0, y: height)
// or in one step
let t = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: height)