ios 旋转图像上下文 (CGContextRotateCTM) 使其变为空白。为什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5983090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:53:48  来源:igfitidea点击:

Rotating an image context (CGContextRotateCTM) causing it to become blank. Why?

iphoneobjective-cioscore-graphics

提问by Gurpartap Singh

#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;
}

Could something else be wrong? Out of ideas.

会不会有其他问题?没有想法。

回答by nielsbot

The problem is your context is being rotated around (0,0) which is the top left corner. If you rotate 90 degrees around the top left corner, all your drawing will occur out of the bounds of the context. You need a 2-step transform to move the origin of the context to it's middle, and THEN rotate. Also you need to draw your image centered around the moved/rotated origin, like this:

问题是您的上下文正在围绕左上角的 (0,0) 旋转。如果围绕左上角旋转 90 度,则所有绘图都将超出上下文的边界。您需要一个 2 步变换将上下文的原点移动到它的中间,然后旋转。您还需要以移动/旋转的原点为中心绘制图像,如下所示:

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

HTH

回答by lbsweek

I try followed code, it works, get from http://www.catamount.com/blog/1015/uiimage-extensions-for-cutting-scaling-and-rotating-uiimages/

我尝试遵循代码,它有效,来自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;
}

回答by Farhad Malekpour

If you don't want to change all the origins and sizes, move the center, rotate and change the center to corner again like this:

如果您不想更改所有原点和大小,请移动中心,旋转并将中心再次更改为角,如下所示:

CGContextTranslateCTM( context, 0.5f * size.width, 0.5f * size.height ) ; CGContextRotateCTM( context, radians( 90 ) ) ; CGContextTranslateCTM( context, -0.5f * size.width, -0.5f * size.height ) ;

CGContextTranslateCTM( context, 0.5f * size.width, 0.5f * size.height ) ; CGContextRotateCTM( context, radians( 90 ) ) ; CGContextTranslateCTM( context, -0.5f * size.width, -0.5f * size.height ) ;

Then draw normally like this:

然后像这样正常绘制:

[image drawInRect:CGRectMake(0, 0, size.width, size.height)];

[image drawInRect:CGRectMake(0, 0, size.width, size.height)];

回答by anoop4real

I liked the solution by @lbsweek but I was bit worried about alloc ing UIView just for transform, instead I tried the below

我喜欢@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;
}

回答by Timo

Expanding on Nielsbot's answer, I created the following snippet. Note that this should preferably be made a function rather than a code snippet, to prevent 'copy/paste programming'. I didn't get to that yet, so feel free to adapt it.

扩展 Nielsbot 的回答,我创建了以下代码段。请注意,最好将其设为函数而不是代码片段,以防止“复制/粘贴编程”。我还没有做到这一点,所以请随意调整它。

Code snippet:

代码片段:

// <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>

Also, I welcome a better way to reset the CGContext to its previous state.

另外,我欢迎使用更好的方法将 CGContext 重置为其以前的状态。