iOS PNG图像旋转90度

时间:2012-04-24 23:44:10

标签: iphone objective-c ios png exif

在我写的iOS应用程序中,我处理PNG因为我处理alpha通道。出于某种原因,我可以将PNG加载到我的imageView中,但是当需要将图像从我的应用程序中复制到PasteBoard上或将图像保存到我的相机胶卷时,图像会旋转90度。

我在这里搜索过,我学到的一件事是,如果我使用JPEG,由于EXIF信息,我不会有这个问题(听起来)。

我的应用程序具有完整的复制/粘贴功能,这里是踢球者(我会分步编写,以便更容易理解):

  1. 转到我的相机胶卷并复制图像
  2. 进入我的应用程序并按“粘贴”,图像粘贴就好了,我可以整天这样做
  3. 单击我实施的复制功能,然后单击“粘贴”,图像粘贴但旋转。
  4. 我100%确定我的复制和粘贴代码不是错误的,因为如果我回到上面的第2步,然后点击“保存”,照片会保存到我的库中,但它会旋转90度!

    更奇怪的是,它似乎可以正常使用从互联网上下载的图像,但是我手动用手机拍摄的图像非常受欢迎。有些它有效,有些则没有......

    有人对此有任何想法吗?我可以使用任何可能的工作吗?我对代码非常有信心,因为它适用于大约75%的图像。我可以根据要求发布代码。

6 个答案:

答案 0 :(得分:26)

对于那些需要Swift解决方案的人,请创建UIImage的扩展并添加以下方法:

func correctlyOrientedImage() -> UIImage {
    if self.imageOrientation == .up {
        return self
    }

    UIGraphicsBeginImageContextWithOptions(size, false, scale)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    let normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return normalizedImage ?? self;
}

答案 1 :(得分:14)

如果由于现有的图片imageOrientation属性而遇到问题,您可以构建一个具有不同方向的其他相同图像,如下所示:

CGImageRef imageRef = [sourceImage CGImage];

UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];

您可能需要尝试在替换图像上设置的方向,可能会根据您开始时的方向进行切换。

还要留意你的记忆力。摄影应用程序经常耗尽,这会使每张照片的存储量翻倍,直到您发布源图像。

答案 2 :(得分:13)

花了几天时间,但由于@Dondragmer发布的答案,我终于想通了。但我想我会发布完整的解决方案。

所以基本上我必须编写一种方法来智能地自动旋转我的图像。缺点是我必须在我的代码中随处调用这种方法,这是一种处理器密集型,特别是在移动设备上工作时,但优点是我可以拍摄图像,复制图像,粘贴图像,保存图像和它们都旋转得很好。这是我最终使用的代码(该方法尚未100%完成,仍然需要编辑内存泄漏,什么不是)。

我最终了解到第一次将图像插入到我的应用程序中(无论是由于用户按下“拍摄图像”,“粘贴图像”或“选择图像”,由于某种原因它只是插入没有自动旋转就好了。此时,我将旋转值存储在名为imageOrientationWhenAddedToScreen的全局变量中。这使我的生活更轻松,因为当操作图像并将图像保存到程序之外时,我只是检查了这个缓存的全局变量,并确定是否需要正确旋转图像。

    - (UIImage*) rotateImageAppropriately:(UIImage*) imageToRotate {
    //This method will properly rotate our image, we need to make sure that
    //We call this method everywhere pretty much...

    CGImageRef imageRef = [imageToRotate CGImage];
    UIImage* properlyRotatedImage;

    if (imageOrientationWhenAddedToScreen == 0) {
       //Don't rotate the image
        properlyRotatedImage = imageToRotate;

    } else if (imageOrientationWhenAddedToScreen == 3) {

        //We need to rotate the image back to a 3
        properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:3];

    } else if (imageOrientationWhenAddedToScreen == 1) {

        //We need to rotate the image back to a 1
        properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:1];        

    }

    return properlyRotatedImage;

}

我仍然不能100%肯定为什么Apple有这种奇怪的图像旋转行为(试试这个......拿起你的手机并将其翻转并拍照,你会注意到最后的图片是正确的 - 也许这就是为什么Apple有这种功能?)。

我知道我花了很多时间搞清楚这一点,所以我希望它可以帮助其他人!

答案 3 :(得分:13)

这种“奇怪的旋转”行为真的不是那么奇怪。它很聪明,聪明的我指的是内存效率。旋转iOS设备时,相机硬件随之旋转。当您拍摄照片时,将拍摄照片,但相机是朝向的。 UIImage能够使用这些原始图片数据而无需复制,只需跟踪它应该处于的方向。当您使用UIImagePNGRepresentation()时,您将丢失此方向数据并获取基础图像的PNG,因为它是由相机。要修复此问题而不是旋转,您可以告诉原始图像将自己绘制到新的上下文中,并从该上下文中获取正确定向的UIImage

UIImage *image = ...;

//Have the image draw itself in the correct orientation if necessary
if(!(image.imageOrientation == UIImageOrientationUp ||
    image.imageOrientation == UIImageOrientationUpMirrored))
{
    CGSize imgsize = image.size;
    UIGraphicsBeginImageContext(imgsize);
    [image drawInRect:CGRectMake(0.0, 0.0, imgsize.width, imgsize.height)];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

NSData *png = UIImagePNGRepresentation(image);

答案 4 :(得分:0)

以下是实现这一目标的另一种方法:

@IBAction func rightRotateAction(sender: AnyObject) {

    let imgToRotate = CIImage(CGImage: sourceImageView.image?.CGImage)
    let transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
    let rotatedImage = imgToRotate.imageByApplyingTransform(transform)
    let extent = rotatedImage.extent()
    let contex = CIContext(options: [kCIContextUseSoftwareRenderer: false])
    let cgImage = contex.createCGImage(rotatedImage, fromRect: extent)
    adjustedImage = UIImage(CGImage: cgImage)!
    UIView.transitionWithView(sourceImageView, duration: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
            self.sourceImageView.image = self.adjustedImage
        }, completion: nil)
}

答案 5 :(得分:0)

您可以使用图像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;
}

您也可以使用NSData将图片保存到CGImageDestinationCreateWithData,然后在NSMutableData中传递NSURL代替CGImageDestinationCreateWithURL