更新UIImage方向metaData?
基本任务:更新与UIImage关联的元数据的EXIF方向属性。 我的问题是,我不知道方向属性在所有EXIF信息中的位置。
Convoluted背景:我正在改变由imagePickerController:didFinishPickingMediaWithInfo:
返回的图像的方向imagePickerController:didFinishPickingMediaWithInfo:
所以我想我也需要更新writeImageToSavedPhotosAlbum:(CGImageRef)imageRef metadata:(NSDictionary *)metadata
之前保存图像writeImageToSavedPhotosAlbum:(CGImageRef)imageRef metadata:(NSDictionary *)metadata
。
换句话说,除非我改变它,元数据将包含旧的/初始的方向,因此是错误的。 我改变方向的原因是因为当我运行Core Image
脸检测程序时,它会让我绊倒。 使用前置摄像头在纵向模式下使用iPhone(设备)拍摄照片,方向为UIImageOrientationRight
(3)。 如果我重写图像的方向是UIImageOrientationUp
(0),我会得到很好的人脸检测结果。 作为参考,重写图像的例程如下。
整个相机方向的东西,我觉得很混乱,我似乎正在挖掘自己更深入到一个代码洞与所有这一切。 我看过post( 这里 , 这里和这里 。根据这个职位( https://stackoverflow.com/a/3781192/840992 ):
“相机实际上是风景本地的,所以当你拍摄照片的时候,当你拍摄照片时,你可以上下拍照,也可以在拍照时拍照(取决于你如何拿着照相机)。”
这是完全混淆的 如果以上是真的,我想我应该得到的UIImageOrientationLeftMirrored
或UIImageOrientationRightMirrored
与前置摄像头的方向。 而这一切都不能解释为什么CIDetector
失败的select器返回的处女形象。
我正在接近这个屁股倒退,但我似乎无法得到导向…
-(UIImage *)normalizedImage:(UIImage *) thisImage { if (thisImage.imageOrientation == UIImageOrientationUp) return thisImage; UIGraphicsBeginImageContextWithOptions(thisImage.size, NO, thisImage.scale); [thisImage drawInRect:(CGRect){0, 0, thisImage.size}]; UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return normalizedImage; }
看看我的答案在这里:
强制UIImagePickerController以纵向/维度iOS拍照
和github上的相关项目 (你不需要运行该项目,只需看看自述)。
它更关心的是阅读而不是写元数据 – 但是它包含了一些关于苹果的imageOrientation和相应的定位“Exif”元数据的笔记。
这也许值得一读
捕获的照片在iOS 6.0或iPhone上传期间自动旋转
播放中有两种不同的常量编号约定来指示图像的方向。
- 在TIFF / IPTC图像元数据标签中使用的kCGImagePropertyOrientation常量
- UIImage imageOrientation属性使用的UIImageOrientation常量。
iPhone本机摄像头方向是左侧风景(右侧是主屏幕button)。 原生像素尺寸总是反映这一点,旋转标志用于正确定位与显示方向的图像。
Apple UIImage.imageOrientation TIFF/IPTC kCGImagePropertyOrientation iPhone native UIImageOrientationUp = 0 = Landscape left = 1 rotate 180deg UIImageOrientationDown = 1 = Landscape right = 3 rotate 90CCW UIImageOrientationLeft = 2 = Portrait down = 8 rotate 90CW UIImageOrientationRight = 3 = Portrait up = 6
UIImageOrientation
4-7映射到kCGImagePropertyOrientation
– 这些是镜像对应。
UIImage从底层kCGImagePropertyOrientation标志派生它的imagerOrientation属性 – 这就是为什么它是一个只读属性。 这意味着只要你得到正确的元数据标志,imageOrientation将正确地遵循。 但是,如果您正在阅读数字以应用转换,则需要注意您正在查看的数字。
从我的世界中收集到的一些细微之处在于:
背景: Core Image
脸检测失败,它似乎与使用featuresInImage:options:和使用UIImage.imageOrientation属性作为参数有关。 如果图像被调整为不旋转而没有镜像,则检测工作正常,但直接从相机检测图像传递失败。
那么… UIImage.imageOrientation
是不同于图像的实际方向。
换一种说法…
UIImage* tmpImage = [self.imageInfo objectForKey:UIImagePickerControllerOriginalImage]; printf("tmpImage.imageOrientation: %d\n", tmpImage.imageOrientation);
报告值为3或UIImageOrientationRight
而使用由UIImagePickerControllerDelegate方法返回的元数据…
NSMutableDictionary* metaData = [[tmpInfo objectForKey:@"UIImagePickerControllerMediaMetadata"] mutableCopy]; printf(" metaData orientation %d\n", [[metaData objectForKey:@"Orientation"] integerValue]);
报告值为6或UIImageOrientationLeftMirrored
。
我想现在看来很明显, UIImage.imageOrientation
是一个显示方向 , 似乎由源图像方向和设备旋转确定。 (我可能在这里是错误的)由于显示方向不同于实际的图像数据,使用它将导致CIDetector
失败。 啊。
我相信所有这一切都为液体GUI等提供了非常好的和重要的目的,但是对于我来说太多了,因为所有的CIDetector
坐标都会在原始的图像方向上使CALayer绘图生病。 所以,这里的后代是如何改变元数据的Orientation
属性和其中包含的图像。 这个元数据然后可以用来保存图像到cameraRoll。
解
// NORMALIZE IMAGE UIImage* tmpImage = [self normalizedImage:[self.imageInfo objectForKey:UIImagePickerControllerOriginalImage]]; NSMutableDictionary * tmpInfo =[self.imageInfo mutableCopy]; NSMutableDictionary* metaData = [[tmpInfo objectForKey:@"UIImagePickerControllerMediaMetadata"] mutableCopy]; [metaData setObject:[NSNumber numberWithInt:0] forKey:@"Orientation"]; [tmpInfo setObject:tmpImage forKey:@"UIImagePickerControllerOriginalImage"]; [tmpInfo setObject:metaData forKey:@"UIImagePickerControllerMediaMetadata"]; self.imageInfo = tmpInfo;