旋转图像上下文 (CGContextRotateCTM) 使其变为空白。为啥?
Posted
技术标签:
【中文标题】旋转图像上下文 (CGContextRotateCTM) 使其变为空白。为啥?【英文标题】:Rotating an image context (CGContextRotateCTM) causing it to become blank. Why?旋转图像上下文 (CGContextRotateCTM) 使其变为空白。为什么? 【发布时间】:2011-05-12 19:05:06 【问题描述】:#define radians(degrees) (degrees * M_PI/180)
UIImage *rotate(UIImage *image)
CGSize size = image.size;;
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// If this is commented out, image is returned as it is.
CGContextRotateCTM (context, radians(90));
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
会不会有其他问题?没有想法。
【问题讨论】:
在catamount.com/blog/1015/…查看 Hardy Macia 的简单而令人敬畏的代码,谢谢 Hardy Macia! 【参考方案1】:问题是您的上下文正在围绕左上角的 (0,0) 旋转。如果您围绕左上角旋转 90 度,您的所有绘图都将出现在上下文范围之外。您需要一个两步变换来将上下文的原点移动到它的中间,然后旋转。您还需要以移动/旋转的原点为中心绘制图像,如下所示:
CGContextTranslateCTM( context, 0.5f * size.width, 0.5f * size.height ) ;
CGContextRotateCTM( context, radians( 90 ) ) ;
[ image drawInRect:(CGRect) -size.width * 0.5f, -size.height * 0.5f , size ] ;
HTH
【讨论】:
对,就是图片旋转的轴。但是该代码没有帮助。无论如何,弄清楚了正确的。将尽快发布作为答案。 +1 的答案。非常感谢! hm.. 是旋转然后翻译?我有时会混淆顺序。 谢谢!这对我有用。我通过恢复上下文来扩展这一点,这是我能找到的唯一方法。让我把它贴在一个新的答案中。 Timo——您可以通过调用CGContextSaveGState()
来保存变换矩阵,然后在完成后调用 CGContextRestoreGState()
。【参考方案2】:
我尝试遵循代码,它有效,来自http://www.catamount.com/blog/1015/uiimage-extensions-for-cutting-scaling-and-rotating-uiimages/
+ (UIImage *)rotateImage:(UIImage*)src byRadian:(CGFloat)radian
// calculate the size of the rotated view's containing box for our drawing space
//UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0, src.size.width, src.size.height)];
//CGAffineTransform t = CGAffineTransformMakeRotation(radian);
//rotatedViewBox.transform = t;
//CGSize rotatedSize = rotatedViewBox.frame.size;
CGRect rect = CGRectApplyAffineTransform(CGRectMake(0,0, src.size.width, src.size.height), CGAffineTransformMakeRotation(radian));
CGSize rotatedSize = rect.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, radian);
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-src.size.width / 2, -src.size.height / 2, src.size.width, src.size.height), [src CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
【讨论】:
创建一个新视图只是为了获取旋转矩形的边界有点疯狂。您可以简单地将这里的前 4 行代码替换为:CGSize rotatedSize = CGSizeMake(src.size.height, src.size.width);
。
@CraigMcMahon 你是对的。因为我的意思是展示 CTM 功能,所以使用最简单但有效的方法来获取绑定,在使用您的代码时应该是完美的。
@CraigMcMahon 正确的用法应该是这样的:CGSize rotatedSize = CGRectApplyAffineTransform(CGRectMake(0,0, src.size.width, src.size.height), CGAffineTransformMakeRotation(radian));
【参考方案3】:
如果您不想更改所有原点和大小,请像这样移动中心、旋转并再次将中心更改为角:
CGContextTranslateCTM( context, 0.5f * size.width, 0.5f * size.height ) ;
CGContextRotateCTM( context, radians( 90 ) ) ;
CGContextTranslateCTM( context, -0.5f * size.width, -0.5f * size.height ) ;
然后像这样正常绘制:
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
【讨论】:
如果您能通过一些插图达到预期的效果,我将不胜感激。特别是,这是否需要,因为旋转发生在上下文的中心?【参考方案4】:扩展 Nielsbot 的答案,我创建了以下 sn-p。请注意,最好将其设为函数而不是代码 sn-p,以防止“复制/粘贴编程”。我还没有做到这一点,所以请随意调整。
代码sn-p:
// <Draw in frame with orientation>
UIImage* imageToDrawRotated = <#image#>;
float rotationAngle = <#angle#>;
CGRect drawFrame = CGRectMake(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat width#>, <#CGFloat height#>);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), floor(drawFrame.origin.x + drawFrame.size.width/2), floor(drawFrame.origin.y + drawFrame.size.height/2));
CGContextRotateCTM(UIGraphicsGetCurrentContext(), rotationAngle);
[imageToDrawRotated drawInRect:CGRectMake(-floor(drawFrame.size.width/2), -floor(drawFrame.size.height/2), drawFrame.size.width, drawFrame.size.height)];
CGContextRotateCTM(UIGraphicsGetCurrentContext(), -rotationAngle);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -floor(drawFrame.origin.x + drawFrame.size.width/2), -floor(drawFrame.origin.y + drawFrame.size.height/2));
// </Draw in frame with orientation>
另外,我欢迎使用更好的方法将 CGContext 重置为之前的状态。
【讨论】:
更好的方法?您可以只使用 CGContextSaveGState/CGContextRestoreGState【参考方案5】:我喜欢@lbsweek 的解决方案,但我有点担心分配 UIView 只是为了进行转换,而是尝试了以下方法
- (UIImage *)rotateImage:(UIImage *)sourceImage byDegrees:(float)degrees
CGFloat radian = degrees * (M_PI/ 180);
CGRect contextRect = CGRectMake(0, 0, sourceImage.size.width, sourceImage.size.height);
float newSide = MAX([sourceImage size].width, [sourceImage size].height);
CGSize newSize = CGSizeMake(newSide, newSide);
UIGraphicsBeginImageContext(newSize);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGPoint contextCenter = CGPointMake(CGRectGetMidX(contextRect), CGRectGetMidY(contextRect));
CGContextTranslateCTM(ctx, contextCenter.x, contextCenter.y);
CGContextRotateCTM(ctx, radian);
CGContextTranslateCTM(ctx, -contextCenter.x, -contextCenter.y);
[sourceImage drawInRect:contextRect];
UIImage* rotatedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return rotatedImage;
【讨论】:
以上是关于旋转图像上下文 (CGContextRotateCTM) 使其变为空白。为啥?的主要内容,如果未能解决你的问题,请参考以下文章