如何制作从UIImagePickerController返回的UIImage的精确副本?(How do I make an exact copy of a UIImage returned from a UIImagePickerController?)

165 IT屋

I have divergent needs for the image returned from the iPhone camera. My app scales the image down for upload and display and, recently, I added the ability to save the image to the Photos app.

At first I was assigning the returned value to two separate variables, but it turned out that they were sharing the same object, so I was getting two scaled-down images instead of having one at full scale.

After figuring out that you can't do UIImage *copyImage = [myImage copy];, I made a copy using imageWithCGImage, per below. Unfortunately, this doesn't work because the copy (here croppedImage) ends up rotated 90º from the original.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{   
    // Resize, crop, and correct orientation issues
    self.originalImage = [info valueForKey:@"UIImagePickerControllerOriginalImage"];
    UIImageWriteToSavedPhotosAlbum(originalImage, nil, nil, nil);
    UIImage *smallImage = [UIImage imageWithCGImage:[originalImage CGImage]]; // UIImage doesn't conform to NSCopy

    // This method is from a category on UIImage based on this discussion:
    // http://discussions.apple.com/message.jspa?messageID=7276709
    // It doesn't rotate smallImage, though: while imageWithCGImage returns
    // a rotated CGImage, the UIImageOrientation remains at UIImageOrientationUp!
    UIImage *fixedImage = [smallImage scaleAndRotateImageFromImagePickerWithLongestSide:480];
    ...
}

Is there a way to copy the UIImagePickerControllerOriginalImage image without modifying it in the process?

解决方案

Copy backing data and rotate it

This question asks a common question about UIImage in a slightly different way. Essentially, you have two related problems - deep copying and rotation. A UIImage is just a container and has an orientation property that is used for display. A UIImage can contain its backing data as a CGImage or CIImage, but most often as a CGImage. The CGImage is a struct of information that includes a pointer to the underlying data and if you read the docs, copying the struct does not copy the data. So...

Deep copying

As I'll get to in the next paragraph deep copying the data will leave the image rotated because the image is rotated in the underlying data.

UIImage *newImage = [UIImage imageWithData:UIImagePNGRepresentation(oldImage)];

This will copy the data but will require setting the orientation property before handing it to something like UIImageView for proper display.

Another way to deep copy would be to draw into the context and grab the result. Assume a zebra.

UIGraphicsBeginImageContext(zebra!.size)
zebra!.drawInRect(CGRectMake(0, 0, zebra!.size.width, zebra!.size.height))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

Deep copy and Rotation

Rotating a CGImage has been already been answered. It also happens that this rotated image is a new CGImage that can be used to create a UIImage.

我对iPhone相机返回的图像有不同的需求。我的应用程序缩小图像以便上传和显示,最近,我添加了将图像保存到照片应用程序的功能。



首先我分配了返回的值两个单独的变量,但事实证明他们共享相同的对象,所以我得到两个缩小的图像,而不是一个满刻度的。



之后搞清楚你不能做 UIImage * copyImage = [myImage copy]; ,我使用 imageWithCGImage 制作了一份副本,如下所示。不幸的是,这不起作用,因为副本(此处为 croppedImage )最终从原始位置旋转90º。



   - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
//调整大小,裁剪和纠正方向问题
self.originalImage = [info valueForKey:@ UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(originalImage,nil,nil,nil);
UIImage * smallImage = [UIImage imageWithCGImage:[originalImage CGImage]]; // UIImage不符合NSCopy

//此方法基于此讨论来自UIImage上的类别:
// http://discussions.apple.com/message。 jspa?messageID = 7276709
//它不会旋转smallImage,但是:当imageWithCGImage返回
//旋转的CGImage时,UIImageOrientation仍保留在UIImageOrientationUp!
UIImage * fixedImage = [smallImage scaleAndRotateImageFromImagePickerWithLongestSide:480];
...
}


有没有办法复制UIImagePickerControllerOriginalImage图像没有在过程中修改它?


解决方案

复制支持数据并将其旋转



这个问题以一种略有不同的方式询问关于 UIImage 的常见问题。基本上,您有两个相关的问题 - 深度复制和旋转。 UIImage 只是一个容器,并且具有用于显示的orientation属性。 UIImage 可以将其支持数据包含为 CGImage 或 CIImage ,但最常见的是 CGImage 。 CGImage 是一个包含指向底层数据的指针的信息结构,如果您阅读了文档,则复制结构不会复制数据。所以...



深度复制



我将在下一段中深入复制数据将使图像旋转,因为图像在基础数据中旋转。



  UIImage * newImage = [UIImage imageWithData:UIImagePNGRepresentation(oldImage) )]; 


这将复制数据,但需要先设置orientation属性,然后再将其设置为 UIImageView 正确显示。



深度复制的另一种方法是绘制上下文并获取结果。假设斑马。



  UIGraphicsBeginImageContext(zebra!.size)
zebra!.drawInRect(CGRectMake(0,0, zebra!.size.width,zebra!.size.height))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()


深层复制和轮换



旋转 CGImage 已经得到解答。此旋转图像也是一个新的 CGImage ,可用于创建 UIImage 。


本文地址:IT屋 » 如何制作从UIImagePickerController返回的UIImage的精确副本?