2010-08-24 165 views
42

我想從UIImagePickerController加載圖像,然後將選定的照片保存到我的應用程序的文檔目錄中。UIImagePNGRepresentation問題? /圖像旋轉90度

UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; 
NSData *data1 = UIImagePNGRepresentation(image); 

NSString *fileName = "1.png"; 
NSString *path = //get Document path, then add fileName 
BOOL succ = [data1 writeToFile:path atomically:YES]; 

但之後,我將圖像保存到我的文檔,我發現,在圖像旋轉90度,然後我改變方法UIImagePNGRepresentation到UIImageJPEGRepresentation,這次是很好,誰知道是什麼問題?

+0

有同樣的問題。 – ZaBlanc 2010-12-06 06:25:35

+0

[iOS UIImagePickerController結果圖像方向上傳後]的可能重複](http://stackoverflow.com/questions/5427656/ios-uiimagepickercontroller-result-image-orientation-after-upload) – 2015-04-03 00:12:45

回答

70

我有同樣的問題,只是想出了原因:從iOS 4.0開始,當相機拍照時它不會在保存前旋轉它,它只是在JPEG的EXIF數據中設置旋轉標誌。

如果將UIImage保存爲JPEG,則會設置旋轉標誌。

PNG不支持旋轉標誌,因此如果將UIImage保存爲PNG,它將被錯誤地旋轉,並且沒有設置標誌來修復它。所以如果你想要PNG,你必須自己旋轉它們。

我會稱這是一個PNG保存功能的錯誤,但這只是一個意見(他們至少應該警告你)。

+0

非常感謝。 – disorderdev 2011-03-03 00:46:55

+0

我花了大概一個小時左右的時間試圖讓我的PNG CGImageSource(從數據創建)在拇指創建時正確旋轉......將exif數據插入到我的CGImageSource創建選項等等中,並且UIImageJPEGRepresentation立即修復它!謝謝! – taber 2011-09-28 06:11:28

+3

@jasongregori:即使將它保存爲JPEG也不能解決我的問題。圖像仍然旋轉。 – 2012-01-02 10:57:33

14

我用下面的代碼解決了這個問題。

- (UIImage *)scaleAndRotateImage:(UIImage *)image 
{ 
    int kMaxResolution = 640; 

    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; 
} 
+0

我喜歡這個代碼,並以某種方式它是唯一一個在旋轉我的形象方面工作。無論如何,我無法在iOS 7.1和ARC週期中使用它。有什麼想法可以解決問題? – 2014-08-29 13:37:21

+0

謝謝!像魅力一樣工作!我將它翻譯爲swift 2.0,用於當前的項目。這是一個要點:https://gist.github。com/fnk0/2e108700bdbe4a92766c – 2015-10-13 03:33:49

+0

@MarcusGabilheri我將如何使用您的代碼旋轉90度? – alex 2015-10-22 20:04:10

2

下面的swift函數可以解決問題。

var rotatedCopy: UIImage { 
    if (imageOrientation == UIImageOrientation.Up) { 
     return self 
    } 

    UIGraphicsBeginImageContext(size) 

    drawInRect(CGRect(origin: CGPoint.zeroPoint, size: size)) 
    let copy = UIGraphicsGetImageFromCurrentImageContext() 

    UIGraphicsEndImageContext() 

    return copy 
} 

燁就是這麼簡單,只是因爲drawInRect功能將圖像的方向考慮。

+0

我會如何使用它?目前我的imageHolder代碼如下所示:'invoiceImageHolder.image = loadImageFromPath(fileInDocumentsDirectory((「\(imagePath!)」)))'並且出現錯誤使用未解析的標識符'imageOrientation' – alex 2015-10-22 19:45:13

9

試試這個:

func rotateImage(image: UIImage) -> UIImage { 

    if (image.imageOrientation == UIImageOrientation.Up) { 
     return image 
    } 

    UIGraphicsBeginImageContext(image.size) 

    image.drawInRect(CGRect(origin: CGPoint.zero, size: image.size)) 
    let copy = UIGraphicsGetImageFromCurrentImageContext() 

    UIGraphicsEndImageContext() 

    return copy 
} 
+0

非常感謝。在將圖像保存爲.png之前這樣做解決了我的問題。 – Alexandros 2018-01-21 17:59:19

1

我創造了這個擴展的UIImage來解決這個問題,UIImagePNGRepresentation,基於this response。所以我建議使用這個類func UIImage.PNGRepresentation(img: UIImage)而不是UIKit func UIImagePNGRepresentation。

夫特3代碼:

// MyUIImage.swift 
// MyEasyMovie-Public-App 
// 
// Created by Ahmed Zahraz on 19/12/2016. 
// Copyright © 2016 AhmedZahraz. All rights reserved.  

import Foundation 
import UIKit 

extension UIImage { 


    public class func PNGRepresentation(_ img: UIImage) -> Data? { 
     // No-op if the orientation is already correct 
     if (img.imageOrientation == UIImageOrientation.up) { 
      return UIImagePNGRepresentation(img); 
     } 
     // We need to calculate the proper transformation to make the image upright. 
     // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 
     var transform:CGAffineTransform = CGAffineTransform.identity 

     if (img.imageOrientation == UIImageOrientation.down 
      || img.imageOrientation == UIImageOrientation.downMirrored) { 

      transform = transform.translatedBy(x: img.size.width, y: img.size.height) 
      transform = transform.rotated(by: CGFloat(M_PI)) 
     } 

     if (img.imageOrientation == UIImageOrientation.left 
      || img.imageOrientation == UIImageOrientation.leftMirrored) { 

      transform = transform.translatedBy(x: img.size.width, y: 0) 
      transform = transform.rotated(by: CGFloat(M_PI_2)) 
     } 

     if (img.imageOrientation == UIImageOrientation.right 
      || img.imageOrientation == UIImageOrientation.rightMirrored) { 

      transform = transform.translatedBy(x: 0, y: img.size.height); 
      transform = transform.rotated(by: CGFloat(-M_PI_2)); 
     } 

     if (img.imageOrientation == UIImageOrientation.upMirrored 
      || img.imageOrientation == UIImageOrientation.downMirrored) { 

      transform = transform.translatedBy(x: img.size.width, y: 0) 
      transform = transform.scaledBy(x: -1, y: 1) 
     } 

     if (img.imageOrientation == UIImageOrientation.leftMirrored 
      || img.imageOrientation == UIImageOrientation.rightMirrored) { 

      transform = transform.translatedBy(x: img.size.height, y: 0); 
      transform = transform.scaledBy(x: -1, y: 1); 
     } 


     // Now we draw the underlying CGImage into a new context, applying the transform 
     // calculated above. 
     let ctx:CGContext = CGContext(data: nil, width: Int(img.size.width), height: Int(img.size.height), 
             bitsPerComponent: img.cgImage!.bitsPerComponent, bytesPerRow: 0, 
             space: img.cgImage!.colorSpace!, 
             bitmapInfo: img.cgImage!.bitmapInfo.rawValue)! 

     ctx.concatenate(transform) 


     if (img.imageOrientation == UIImageOrientation.left 
      || img.imageOrientation == UIImageOrientation.leftMirrored 
      || img.imageOrientation == UIImageOrientation.right 
      || img.imageOrientation == UIImageOrientation.rightMirrored 
      ) { 


      ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.height,height:img.size.width)) 

     } else { 
      ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.width,height:img.size.height)) 
     } 


     // And now we just create a new UIImage from the drawing context 
     let cgimg:CGImage = ctx.makeImage()! 
     let imgEnd:UIImage = UIImage(cgImage: cgimg) 

     return UIImagePNGRepresentation(imgEnd) 
    } 

}