保存UIImage时,加载它时出现了错误的方向

42

我正在使用以下代码保存和加载从相册或通过相机拍摄的图像:

//saving an image
- (void)saveImage:(UIImage*)image:(NSString*)imageName {
    NSData *imageData = UIImagePNGRepresentation(image); //convert image into .png format.
    NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
    NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory
    NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]]; //add our image to the path
    [fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; //finally save the path (image)
    NSLog(@"image saved");
}

//loading an image
- (UIImage*)loadImage:(NSString*)imageName {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]];
    return [UIImage imageWithContentsOfFile:fullPath];
}

这是我将选择的图像显示在UIImageView中的方式:

imgView.image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

然而,当我选择一张图片并将其设置为在我的 UIImageView 中显示时,它是正常的,但当我加载该图片时,它经常会显示错误的方向。有什么想法吗?是否有人遇到过这种情况或知道如何解决?

谢谢。

编辑:

所以似乎,如果您加载一个竖直翻转的照片,则以那个方向加载,如果您拍摄了一个横向左侧的照片,则以该方向加载。有什么办法绕过这个问题吗?无论它们以任何方向加载,它们总是返回UIImageOrientationUp。


只需查看UIImage文档中的UIImageOrientationUp。您可以设置UIImage对象的imageOrientation属性。 - Praveen-K
我该如何应用这个方向呢?我已经看过了,似乎只适用于比较,旋转必须手动完成。 - Josh Kahane
你可以像这样解决这个问题:修复图像方向 - Javen.Yang
5个回答

64

问题的根本原因是PNG格式没有图像方向信息,而JPEG格式有。因此,解决这个问题最简单的方法是使用UIImageJPEGRepresentation()将您的文件保存为JPEG格式。


这解决了我的问题,即我的保存的图像未以正确方向返回 - 特别是从相机拍摄的图像。使用JPEG替代方案的唯一缺点是透明度不会保留,对吗? - micnguyen
还需要注意的是,使用JPEG格式会导致图像质量损失。 - Gang Fang
因此,像这样旋转它是必要的。 - DawnSong

31

我曾经遇到过类似的问题,下面是我的解决方法。

当我们保存图像时,需要同时保存其方向信息

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:[myImage imageOrientation] forKey:@"kImageOrientation"];
[imageOrientation release];

当我们加载图片时,需要读取其方向信息并将其应用于图片

UIImage *tempImage = [[UIImage alloc] initWithContentsOfFile:fullPath];
UIImage *orientedImage= [[UIImage alloc] initWithCGImage: tempImage.CGImage scale:1.0 orientation:imageOrientation];
[tempImage release];

orientedImage 是我们需要的内容。

谢谢。


即使UIImage已经被转换为NSData并再次转换回来,这仍然有效吗? - zakdances
谢谢,我已经为奇怪的旋转问题苦恼了6个小时,当我终于找到这个答案时感到非常高兴。 - Rick van der Linde
1
这解决了我的问题,但只有当我开始使用ALAsset方向属性而不是UIImage方向属性时才有效。 - Scott Allen
在保存到磁盘前进行旋转,类似于这样 - DawnSong

3
检查您加载的图像的EXIF信息,应该有一个方向标签。使用该值将图像旋转到正确的方向。
这个网站可以让您开始。

http://www.impulseadventure.com/photo/exif-orientation.html

当您打开照片时,用于查看照片的应用程序必须内置此功能,这就是为什么您会看到正确的方向。


1
啊,非常有趣,不过我该如何获取那个Exif方向数据呢? - Josh Kahane

0
尝试保存图像方向,然后在加载该图像时检查是否为正确方向,如果不是,则使用CGAffineTransform或其他方法旋转图像。

0

您可以使用Image I/O根据原始图像的方向将PNG图像保存到文件(或NSMutableData)。在下面的示例中,我将PNG图像保存到path指定的文件中。

- (BOOL)savePngFile:(UIImage *)image toPath:(NSString *)path {
    NSData *data = UIImagePNGRepresentation(image);
    int exifOrientation = [UIImage cc_iOSOrientationToExifOrientation:image.imageOrientation];
    NSDictionary *metadata = @{(__bridge id)kCGImagePropertyOrientation:@(exifOrientation)};
    NSURL *url = [NSURL fileURLWithPath:path];
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    if (!source) {
        return NO;
    }
    CFStringRef UTI = CGImageSourceGetType(source);
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, UTI, 1, NULL);
    if (!destination) {
        CFRelease(source);
        return NO;
    }
    CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metadata);
    BOOL success = CGImageDestinationFinalize(destination);
    CFRelease(destination);
    CFRelease(source);
    return success;
}

cc_iOSOrientationToExifOrientation:UIImage 类别的一个方法。

+ (int)cc_iOSOrientationToExifOrientation:(UIImageOrientation)iOSOrientation {
    int exifOrientation = -1;
    switch (iOSOrientation) {
        case UIImageOrientationUp:
            exifOrientation = 1;
            break;

        case UIImageOrientationDown:
            exifOrientation = 3;
            break;

        case UIImageOrientationLeft:
            exifOrientation = 8;
            break;

        case UIImageOrientationRight:
            exifOrientation = 6;
            break;

        case UIImageOrientationUpMirrored:
            exifOrientation = 2;
            break;

        case UIImageOrientationDownMirrored:
            exifOrientation = 4;
            break;

        case UIImageOrientationLeftMirrored:
            exifOrientation = 5;
            break;

        case UIImageOrientationRightMirrored:
            exifOrientation = 7;
            break;

        default:
            exifOrientation = -1;
    }
    return exifOrientation;
}

你也可以使用CGImageDestinationCreateWithData将图像保存到NSMutableData中,并在CGImageDestinationCreateWithURL中传递NSMutableData而不是NSURL


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