旋转图像并将图像保存为 Rotated 状态

Posted

技术标签:

【中文标题】旋转图像并将图像保存为 Rotated 状态【英文标题】:Rotate image and save the image with the Rotated state 【发布时间】:2011-07-07 08:45:54 【问题描述】:

我想用 UIslider 控件旋转图像。

我已经用下面的函数做到了

- (void)rotateImage:(UIImageView *)图像持续时间:(NSTimeInterval)持续时间 曲线:(int)曲线度:(CGFloat)度 //设置动画 [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:duration]; [UIView setAnimationCurve:curve]; [UIView setAnimationBeginsFromCurrentState:YES]; // The transform matrix CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees)); image.transform = transform; // Commit the changes [UIView commitAnimations];

通过使用此功能,它将完美运行 但问题是我无法保存旋转的图像参考。 我必须使用旋转后的图像进行进一步处理。

那么如何保存旋转位置的图像呢?

请帮我解决这个问题

谢谢

【问题讨论】:

【参考方案1】:

我找到了我的问题的解决方案

使用下面的这个方法

- (UIImage*)upsideDownBunny:(CGFloat)radians withImage:(UIImage*)testImage 
    __block CGImageRef cgImg;
    __block CGSize imgSize;
    __block UIImageOrientation orientation;
    dispatch_block_t createStartImgBlock = ^(void) 
        // UIImages should only be accessed from the main thread

        UIImage *img =testImage
        imgSize = [img size]; // this size will be pre rotated
        orientation = [img imageOrientation];
        cgImg = CGImageRetain([img CGImage]); // this data is not rotated
    ;
    if([NSThread isMainThread]) 
        createStartImgBlock();
     else 
        dispatch_sync(dispatch_get_main_queue(), createStartImgBlock);
    
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    // in ios4+ you can let the context allocate memory by passing NULL
    CGContextRef context = CGBitmapContextCreate( NULL,
                                                 imgSize.width,
                                                 imgSize.height,
                                                 8,
                                                 imgSize.width * 4,
                                                 colorspace,
                                                 kCGImageAlphaPremultipliedLast);
    // rotate so the image respects the original UIImage's orientation
    switch (orientation) 
        case UIImageOrientationDown:
            CGContextTranslateCTM(context, imgSize.width, imgSize.height);
            CGContextRotateCTM(context, -radians);
            break;
        case UIImageOrientationLeft:
            CGContextTranslateCTM(context, 0.0, imgSize.height);
            CGContextRotateCTM(context, 3.0 * -radians / 2.0);
            break;
        case UIImageOrientationRight:
            CGContextTranslateCTM(context,imgSize.width, 0.0);
            CGContextRotateCTM(context, -radians / 2.0);
            break;
        default:
            // there are mirrored modes possible
            // but they aren't generated by the iPhone's camera
            break;
    
    // rotate the image upside down

    CGContextTranslateCTM(context, +(imgSize.width * 0.5f), +(imgSize.height * 0.5f));
    CGContextRotateCTM(context, -radians);
    //CGContextDrawImage( context, CGRectMake(0.0, 0.0, imgSize.width, imgSize.height), cgImg );
    CGContextDrawImage(context, (CGRect).origin.x = -imgSize.width* 0.5f , .origin.y = -imgSize.width* 0.5f , .size.width = imgSize.width, .size.height = imgSize.width, cgImg);
    // grab the new rotated image
    CGContextFlush(context);
    CGImageRef newCgImg = CGBitmapContextCreateImage(context);
    __block UIImage *newImage;
    dispatch_block_t createRotatedImgBlock = ^(void) 
        // UIImages should only be accessed from the main thread
        newImage = [UIImage imageWithCGImage:newCgImg];
    ;
    if([NSThread isMainThread]) 
        createRotatedImgBlock();
     else 
        dispatch_sync(dispatch_get_main_queue(), createRotatedImgBlock);
    
    CGColorSpaceRelease(colorspace);
    CGImageRelease(newCgImg);
    CGContextRelease(context);
    return newImage;

调用这个方法
 UIImage  *rotated2 = [self upsideDownBunny:rotation];

其中旋转为 0 到 360 之间的滑块值。

现在我们可以保存旋转后的状态了。

【讨论】:

【参考方案2】:

我尝试了上面的代码,它可以工作,但仅适用于 SQUARE 图像,这是另一个可行的解决方案,它将重新绘制图像并保持正确的宽度/高度:

- (UIImage *) rotatedImage:(UIImage *)imageRotation and:(CGFloat) rotation

// Calculate Destination Size
CGAffineTransform t = CGAffineTransformMakeRotation(rotation);
CGRect sizeRect = (CGRect) .size = imageRotation.size;
CGRect destRect = CGRectApplyAffineTransform(sizeRect, t);
CGSize destinationSize = destRect.size;

// Draw image
UIGraphicsBeginImageContext(destinationSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, destinationSize.width / 2.0f, destinationSize.height / 2.0f);
CGContextRotateCTM(context, rotation);
[imageRotation drawInRect:CGRectMake(-imageRotation.size.width / 2.0f, -imageRotation.size.height / 2.0f, imageRotation.size.width, imageRotation.size.height)];

// Save image
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;

这里的旋转参数是以弧度给出的。您可以通过将其添加到您的函数上方(或直接在您的 .m 文件中)来执行转换

#define M_PI   3.14159265358979323846264338327950288   /* pi */
#define DEGREES_TO_RADIANS(angle) (angle / 180.0 * M_PI)

最后,我用动画来称呼它:

  [UIView animateWithDuration:0.5f delay:0 options:UIViewAnimationCurveEaseIn animations:^
    //Only used for the ANIMATION of the uiimage
    imageView.transform = CGAffineTransformRotate(editorPad.transform, DEGREES_TO_RADIANS(90));
completion:^(BOOL finished) 
    // Workaround : Need to set previous transformation back or the next step will turn the image more
    imageView.transform = CGAffineTransformRotate(imageView.transform, DEGREES_TO_RADIANS(-90));
    imageView.image = [self imageView.image and:DEGREES_TO_RADIANS(90)];
];

我希望这也能有所帮助!

干杯。

【讨论】:

【参考方案3】:

进一步处理的一种方法是按顺序应用更多转换,例如:

CGAffineTransform transform = CGAffineTransformScale(previousTransform, newScale, newScale);

在这种情况下,您将对旋转的图像应用缩放。

如果您需要保存这些信息以便以后能够重做转换,您可以简单地存储旋转角度、缩放因子(在我的示例中),然后再次构建转换。

您还可以考虑将您的 CGAffineTransform 存储在您的类或其他机制的 ivar 中。

编辑:

如果保存是指保存到文件,则可以使用以下代码将视图转换为图像:

NSData *data;
NSBitmapImageRep *rep;
rep = [self bitmapImageRepForCachingDisplayInRect:[self frame]];
[self cacheDisplayInRect:[self frame] toBitmapImageRep:rep];
data = [rep TIFFRepresentation];

然后将 NSData 保存到文件中

对于 PNG:

 UIGraphicsBeginImageContext(self.bounds.size);
 [self.layer renderInContext:UIGraphicsGetCurrentContext()];
 UIImage* image1 = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
 NSData *imageData = UIImagePNGRepresentation(image1);
 [imageData writeToFile:filePath atomically:YES];

【讨论】:

我在旋转图像时没有问题,但问题是我必须保存旋转后的图像。那我该怎么做呢? 将图片保存在旋转位置。 我必须将旋转后的图像保存在 .png 文件中。【参考方案4】:

您可以将旋转后的图像渲染成另一张图像:

UIGraphicsBeginImageContext(aCGRectToHoldYourImage);
CALayer* layer = myRotatedImageView.layer;

[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

然后从中获取 PNG 数据并将其保存到文件中

NSData* myPNGData = [viewImage UIImagePNGRepresentation];
[myPNGData writeToFile:@"aFileName.png" atomically:YES];

附带条件,我在 *** 中输入了这个,而不是编译器 :-)

【讨论】:

【参考方案5】:

保存你的 UIImageView 的转换值,并在下次你想使用这个 UIImageView 甚至另一个 UIImageView 时应用这个转换值。

【讨论】:

以上是关于旋转图像并将图像保存为 Rotated 状态的主要内容,如果未能解决你的问题,请参考以下文章

如何旋转base64图像并将其保存为角度2或以上?

在python中旋转图像:外推背景颜色

如何使用 Pygame 围绕其中心旋转图像?

使用旋转矩形提取图像 ROI

使用PIL在python中旋转并将expand参数设置为true时指定图像填充颜色

旋转 persp3d 绘图并将图像另存为 png