从旋转的UIImageView创建UIImage

15

我有一个UIImageView控件,其中包含一张图片。在显示之前,通过将UIImageView的transform属性设置为CGAffineTransformMakeRotation(angle),其中angle为弧度角度,来旋转图像。

我希望能够创建另一个UIImage,它与我在视图中看到的旋转版本相对应。

通过旋转图像上下文,我已经接近成功,我得到了一个旋转后的图像:

- (UIImage *) rotatedImageFromImageView: (UIImageView *) imageView
{
    UIImage *rotatedImage;

    // Get image width, height of the bounding rectangle
    CGRect boundingRect = [self getBoundingRectAfterRotation: imageView.bounds byAngle:angle];

    // Create a graphics context the size of the bounding rectangle
    UIGraphicsBeginImageContext(boundingRect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Rotate and translate the context
    CGAffineTransform ourTransform = CGAffineTransformIdentity;
    ourTransform = CGAffineTransformConcat(ourTransform, CGAffineTransformMakeRotation(angle));

    CGContextConcatCTM(context, ourTransform);

    // Draw the image into the context
    CGContextDrawImage(context, CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage);

    // Get an image from the context
    rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];

    // Clean up
    UIGraphicsEndImageContext();
    return rotatedImage;
 }

然而,图像并没有围绕其中心旋转。我已经尝试了所有可能的变换组合来使它围绕中心旋转,但是无济于事。我是否漏掉了什么技巧?由于我旋转的是上下文而不是图像,所以这是否可能?

现在很渴望让它工作,任何帮助将不胜感激。

Dave

编辑:我已被要求多次提供我的boundingRect代码,因此在此处提供:

- (CGRect) getBoundingRectAfterRotation: (CGRect) rectangle byAngle: (CGFloat) angleOfRotation {
    // Calculate the width and height of the bounding rectangle using basic trig
    CGFloat newWidth = rectangle.size.width * fabs(cosf(angleOfRotation)) + rectangle.size.height * fabs(sinf(angleOfRotation));
    CGFloat newHeight = rectangle.size.height * fabs(cosf(angleOfRotation)) + rectangle.size.width * fabs(sinf(angleOfRotation));

    // Calculate the position of the origin
    CGFloat newX = rectangle.origin.x + ((rectangle.size.width - newWidth) / 2);
    CGFloat newY = rectangle.origin.y + ((rectangle.size.height - newHeight) / 2);

    // Return the rectangle
    return CGRectMake(newX, newY, newWidth, newHeight);
}

这应该可以解决<br/>https://dev59.com/i3M_5IYBdhLWcg3wlEPO - zapping
这个 getBoundingRectAfterRotation 函数是什么? - bmdhacks
嗨@bmdhacks,getBoundingRectAfterRotation是我创建的一个方法,因此您在任何Cocoa-Touch类中都找不到它。它接受矩形和角度作为参数,并返回一个新的CGRect,如果原始矩形按给定角度旋转,则该矩形将包围它。 - Magic Bullet Dave
嗨@bmdhacks,由于广大用户的需求,我在原问题的编辑中添加了该方法。 - Magic Bullet Dave
1个回答

22

好的 - 最终我似乎做到了。有关正确性的任何评论都会很有用...需要一个翻译、旋转、缩放和偏移量,从绘图矩形位置开始才能使它工作。代码在这里:

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, boundingRect.size.width/2, boundingRect.size.height/2);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformScale(transform, 1.0, -1.0);

CGContextConcatCTM(context, transform);

// Draw the image into the context
CGContextDrawImage(context, CGRectMake(-imageView.image.size.width/2, -imageView.image.size.height/2, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage);

// Get an image from the context
rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];

1
为什么需要 transform = CGAffineTransformScale(transform, 1.0, -1.0); - Hlung
3
CoreGraphics 使用的坐标系原点在左下角,UIKit 对象使用的是以左上角为原点的坐标系,并且沿着屏幕向下移动时,y 轴递增。这个转换会翻转 y 轴,以确保图像被正确绘制。 - Magic Bullet Dave
1
谢谢!我一直在尝试用平移、旋转和缩放来绘制图像,但一直很苦恼。我尝试使用UIImage的drawInRect:并将上下文进行平移,但它始终围绕左上角(0,0)旋转。您的解决方案是唯一有效的!:) - Hlung
嗨,这段代码无法处理方向与UIImageOrientationUp不同的照片,你有什么解决方案吗? - Pion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接