gpt4 book ai didi

ios - 如何将从 CGImageRef 创建的 UIImage 对象转换为原始数据并再次转换回来

转载 作者:可可西里 更新时间:2023-11-01 04:57:14 27 4
gpt4 key购买 nike

假设您从一个 UIImage 开始,您希望裁剪它。最常见的方法是使用 CGImageCreateWithImageInRect 获取 CGImageRef 并从中创建一个新图像,如下所示:

CGRect cropRect = CGRectMake(x*width, y*height, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];

现在假设您稍后需要将此 UIImage 转换为 NSData 对象。例如,如果您希望使用 NSKeyedArchiver 将图像存储在磁盘上,就会发生这种情况。或者您可以通过显式执行以下操作来获取 NSData 对象:

NSData *imageData = UIImagePNGRepresentation(croppedImage);

我这样做了,后来我尝试通过以下方式重建一个新的 UIImage 对象:

UIImage *image = [UIImage imageWithData:imageData];

我为一系列 48 张图片做了这个。他们中的大多数都很好,但在每 4 张图像之后,接下来的 2 张图像被损坏,每张图像的顶部和底部交换。如果我取出转换为 NSData 并再次返回,它工作正常。如果我使用 NSKeyedArchiver 将图像数组写入磁盘(我猜它在其编码例程中调用类似 UIImagePNGRepresentation 的东西),我也会遇到完全相同的问题。我的理论是这一定与我如何从 CGImageRefs 构建图像有关。

解决这个问题的方法是什么?我似乎无法弄清楚如何将 CGImageRefs 放入 NSData 对象中,我更喜欢一种能够正确构建 UIImage 的解决方案,以便它可以被序列化。

编辑:

有些人要求实际运行的代码,所以我在这里添加它

    UIImage *image = self.animationObject.image;
for (int y=0; y<[self.animationInfoObject.numInY intValue]; y++) {
for (int x=0; x<[self.animationInfoObject.numInX intValue]; x++) {
CGRect cropRect = CGRectMake(x*width, y*height, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
NSData *imageData = UIImageJPEGRepresentation(croppedImage, 1.0);
[self addImageToArray:imageData];
CFRelease(imageRef);
}
}

self.animationObject.image 中的图像是一个图像网格,每个方向都有 numInX 和 numInY 个图像。我从 2D 网格中裁剪出每个单独的图像并保存它们。

稍后,我将图像放在 ImageView 中以使其具有动画效果。这是代码:

        NSMutableArray *animationArray = [[NSMutableArray alloc] init];
for (int frame=0; frame<[[photoObject frameArray] count]; frame++) {
NSData *imageData =[[photoObject imageArray] objectAtIndex:[[[photoObject frameArray] objectAtIndex:frame] integerValue]-1];
UIImage *image = [UIImage imageWithData:imageData];
[animationArray addObject:image];
}

这在 iPhone 6 上一切正常,但在 iPhone 5 上不起作用。这似乎也只有在图像网格很长时才会出现问题。例如,在我使用 self.animationObject.image 的示例中,numInY 为 3,numInX 为 2,图像的总大小为 1536x3072(每个迷你图像为 768x1024)。它是底部的两个图像,它们的顶部和底部翻转了。

最佳答案

您的问题是由于图像方向引起的。
每个 UIImage 都包含一个 -imageOrientation 属性,当您请求 CGImage 时,该属性定义了渲染到屏幕后应应用于 UIImage 的方向 你丢失了那个信息。
如果您从所提供的元数据字典中的相机获取图像,则还有 EXIF 方向,因此它取决于您的数据来自何处。
在我的博客上,我写了一个 article关于这一点以及如果图像来自相机,如何正确处理它们。
一个快速的解决方案是读取 CGImage 属性并根据 -imageOrientation 属性应用转换。你可以找到不同的方法,herehere

此片段摘自 here , 归功于 awolf

- (UIImage *)croppedImageInRect:(CGRect)rect
{
double (^rad)(double) = ^(double deg) {
return deg / 180.0 * M_PI;
};

CGAffineTransform rectTransform;
switch (self.imageOrientation) {
case UIImageOrientationLeft:
rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -self.size.height);
break;
case UIImageOrientationRight:
rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -self.size.width, 0);
break;
case UIImageOrientationDown:
rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -self.size.width, -self.size.height);
break;
default:
rectTransform = CGAffineTransformIdentity;
};
rectTransform = CGAffineTransformScale(rectTransform, self.scale, self.scale);

CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], CGRectApplyAffineTransform(rect, rectTransform));
UIImage *result = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
CGImageRelease(imageRef);

return result;
}

关于ios - 如何将从 CGImageRef 创建的 UIImage 对象转换为原始数据并再次转换回来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29441298/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com