如何将方向数据写入UIImage iOS SDK

4
我遇到了一个问题,我从imagePicker(相机而非图库)中获取了一个UIImage,但是当我使用[UIImageJPEGRepresentation writeToFile: atomically:]将其写入文件时,会失去方向数据(所有图像都处于横向状态),我使用了一些图像转换代码,但每个图像需要1.5-2秒的时间,我的问题是如何不丢失方向?也许我可以将其写入EXIF数据中? 谢谢您的帮助。
编辑: 感谢Jonathan Cichon,现在我得到了UIImagePickerControllerMediaMetadata中的图像方向(Orientation = 6),但是如何将其存储到jpg文件中?(我再次使用[UIImageJPEGRepresentation writeToFile: atomically:] proc保存文件)
2个回答

4
请查看此帖子,以获取关于如何存储EXIF数据的信息。如果我没记错的话,你可以直接使用UIImagePickerControllerMediaMetadata。至少,你可以在这个字典中找到所有必要的方向信息来创建你的EXIF数据。
请参考链接中的最佳答案,并将第一行替换为


NSData * jpeg = UIImageJPEGRepresentation(yourImage, 1);

是的,这是正确的,我得到了Orientation = 6,但是如何将其添加到使用[UIImageJPEGRepresentation writeToFile: atomically:]保存的文件中呢? - itworksinua
最简单的方法是在保存文件之前添加EFIX容器,请查看我的编辑。 - Jonathan Cichon
好的,现在我可以在两种情况下编写和读取exif,并且得到相同的值,假设它是6,但是在我的UIImageView中,它以横向模式而不是纵向模式显示。UIImageView读取EXIF,所以也许我需要将其存储在其他键中(现在它在“方向”上)? - itworksinua
尝试使用 kCGImagePropertyTIFFDictionarykCGImagePropertyTIFFOrientation 键。 - Jonathan Cichon
抱歉,那是我的错误,现在一切都正常运作了。注:kCGImagePropertyTIFFDictionary是“方向”的常量,因此相同。注2:UIImageView在方向上工作正常,我使用的MWPhotoBrowser在方向上不太好。总之,我使用Orientation键保存图像,它在UIImageView上显示正确。感谢您的帮助。 - itworksinua
谢谢!根据您的建议,我已经通过使用UIImageJPEGRepresentation/UIImagePNGRepresentation解决了方向问题,并且还用CGImageDestinationAddImageFromSource替换了CGImageDestinationAddImage。 - Nianliang

3

好的,我在谷歌上简单搜索找到了以下内容,来自这个链接:

UIImage *scaleAndRotateImage(UIImage *image)
{
    int kMaxResolution = 320; // Or whatever

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);

    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = bounds.size.width / ratio;
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }

    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

    }

    UIGraphicsBeginImageContext(bounds.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

请仔细阅读,我使用了这种方法,但速度太慢了。 - itworksinua
我认为有一个错误,因为EXIF = 8应该是UIImageOrientationLeft而不是UIImageOrientationRight。 - zeus
需要检查一下,因为这篇文章很旧,可能在写作时条件是适当的,但现在可能有一些条件发生了变化。如果需要,我会检查并更新答案。 - The iOSDev

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