有谁知道为什么CGContextDrawImage
会把我的形象颠倒过来?我从我的应用程序加载图像:
UIImage *image = [UIImage imageNamed:@"testImage.png"];
然后简单地要求核心图形将其绘制到我的上下文中:
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
它呈现在正确的位置和尺寸,但图像是颠倒的.我一定错过了一些非常明显的东西吗?
代替
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
使用
[image drawInRect:CGRectMake(0, 0, 145, 15)];
在您的开始/结束CGcontext
方法的中间.
这将以正确的方向将图像绘制到当前图像上下文中 - 我很确定这与UIImage
保持方向知识有关,而CGContextDrawImage
方法在不了解方向的情况下获取基础原始图像数据.
请注意,您将在许多方面遇到此问题,但一个具体示例是处理地址簿用户图像.
即使应用了我提到的所有内容,我仍然会对图像进行戏剧化.最后,我刚刚使用Gimp创建了所有图像的"翻转垂直"版本.现在我不需要使用任何变换.希望这不会导致进一步的问题.
有谁知道为什么CGContextDrawImage会颠倒我的图像?我从我的应用程序加载图像:
Quartz2d使用不同的坐标系,原点位于左下角.因此,当Quartz绘制100*100图像的像素x [5],y [10]时,该像素将被绘制在左下角而不是左上角.从而导致'翻转'图像.
x坐标系统匹配,因此您需要翻转y坐标.
CGContextTranslateCTM(context, 0, image.size.height);
这意味着我们已经在x轴上将图像转换为0个单位,并在y轴上转换图像高度.然而,仅此一点就意味着我们的图像仍然是颠倒的,只是在我们希望绘制的地方下方绘制"image.size.height".
Quartz2D编程指南建议使用ScaleCTM并传递负值以翻转图像.您可以使用以下代码执行此操作 -
CGContextScaleCTM(context, 1.0, -1.0);
在CGContextDrawImage
通话之前将两者结合起来,您应该正确绘制图像.
UIImage *image = [UIImage imageNamed:@"testImage.png"]; CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height); CGContextTranslateCTM(context, 0, image.size.height); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, imageRect, image.CGImage);
如果您的imageRect坐标与图像的坐标不匹配,请小心,因为您可能会得到意想不到的结果.
要转换回坐标:
CGContextScaleCTM(context, 1.0, -1.0); CGContextTranslateCTM(context, 0, -imageRect.size.height);
两个世界中最好的,使用UIImage drawAtPoint:
或drawInRect:
仍然指定您的自定义上下文:
UIGraphicsPushContext(context); [image drawAtPoint:CGPointZero]; // UIImage will handle all especial cases! UIGraphicsPopContext();
你也避免修改您的上下文CGContextTranslateCTM
或CGContextScaleCTM
其中第二个答案呢.
相关的Quartz2D文档:https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4
翻转默认坐标系
在UIKit绘图中翻转会修改背景CALayer,以将具有LLO坐标系的绘图环境与UIKit的默认坐标系对齐.如果您只使用UIKit方法和绘图功能,则不需要翻转CTM.但是,如果将Core Graphics或Image I/O函数调用与UIKit调用混合使用,则可能需要翻转CTM.
具体来说,如果您通过直接调用Core Graphics函数绘制图像或PDF文档,则该对象将在视图的上下文中呈现为倒置.您必须翻转CTM才能正确显示图像和页面.
要将绘制到Core Graphics上下文的对象翻转以便在UIKit视图中显示时它正确显示,您必须分两步修改CTM.将原点转换为绘图区域的左上角,然后应用缩放平移,将y坐标修改为-1.执行此操作的代码类似于以下内容:
CGContextSaveGState(graphicsContext); CGContextTranslateCTM(graphicsContext, 0.0, imageHeight); CGContextScaleCTM(graphicsContext, 1.0, -1.0); CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight)); CGContextRestoreGState(graphicsContext);
如果有人对在上下文中自定义rect中绘制图像的简单解决方案感兴趣:
func drawImage(image: UIImage, inRect rect: CGRect, context: CGContext!) { //flip coords let ty: CGFloat = (rect.origin.y + rect.size.height) CGContextTranslateCTM(context, 0, ty) CGContextScaleCTM(context, 1.0, -1.0) //draw image let rect__y_zero = CGRect(origin: CGPoint(x: rect.origin.x, y:0), size: rect.size) CGContextDrawImage(context, rect__y_zero, image.CGImage) //flip back CGContextScaleCTM(context, 1.0, -1.0) CGContextTranslateCTM(context, 0, -ty) }
将缩放图像以填充矩形.
我不确定UIImage
,但这种行为通常发生在翻转坐标时.大多数OS X坐标系的原点都在左下角,如Postscript和PDF.但CGImage
坐标系的起源位于左上角.
可能的解决方案可能涉及isFlipped
属性或scaleYBy:-1
仿射变换.