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

时间:2011-05-12 19:05:06

标签: iphone objective-c ios core-graphics

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

还有别的错吗?出于想法。

5 个答案:

答案 0 :(得分:52)

问题是你的上下文正在左右角(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 :(得分:11)

我尝试按照代码运行,从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;
}

答案 2 :(得分:9)

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

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)];

答案 3 :(得分:1)

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

代码段:

// <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重置为之前的状态。

答案 4 :(得分:1)

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