2010-08-24 2 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]; 

하지만, 나는, 사람이 문제가 어떤 건지, 이미지가 내가 UIImageJPEGRepresentation의 방법 UIImagePNGRepresentation을 변경 한 후, 90도를 회전 한 것을이 괜찮 이번에 발견?

+0

같은 문제가 있었다. – ZaBlanc

+0

업로드 후 [iOS UIImagePickerController 결과 이미지 방향] 가능한 복제본 (http://stackoverflow.com/questions/5427656/ios-uiimagepickercontroller-result-image-orientation-after-upload) –

답변

70

나는 같은 문제가 있었는데 그 이유를 알아 냈다. 카메라가 사진을 찍을 때 iOS 4.0부터 저장하기 전에 사진을 회전시키지 않고 단순히 JPEG의 EXIF ​​데이터에 회전 플래그를 설정한다.

UIImage를 JPEG로 저장하면 회전 플래그가 설정됩니다.

PNG는 회전 플래그를 지원하지 않으므로 PNG로 UIImage를 저장하면 잘못 회전되어 플래그가 고정되어 있지 않습니다. 따라서 PNG를 원한다면 직접 회전해야합니다.

나는 이것을 PNG 저장 함수에서 버그라고 부르 겠지만, 그것은 단지 의견 일 뿐이다 (적어도 이것에 대해 경고해야한다).

+0

대단히 감사합니다. – disorderdev

+0

엄지 손가락이 만들어 질 때 내 PNG CGImageSource (데이터에서 생성 된)를 제대로 만들려고 노력하는 데 1 시간 정도를 소비했습니다 ... CGImageSource 만들기 옵션 등으로 exif 데이터를 삽입하고 UIImageJPEGRepresentation이 바로 수정했습니다. ! 감사! – taber

+3

@ jasongregori : JPEG로 저장하더라도 내 문제는 해결되지 않습니다. 이미지가 계속 회전합니다. –

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주기에서 작동시키는 데 문제가 있습니다. 그 문제가 어디에있을 수 있는지 생각해? –

+0

고맙습니다! 매력처럼 일했습니다! 현재 프로젝트에 대해 2.0으로 신속하게 번역했습니다. 여기에 요점이 있습니다 : https : //gist.github.com/fnk0/2e108700bdbe4a92766c –

+0

@MarcusGabilheri 코드를 90도 회전하려면 어떻게해야합니까? – alex

2

다음과 같은 신속한 기능으로 문제가 해결됩니다. 그 그래

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

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

1

내가 this response에 따라, UIImagePNGRepresentation이 문제를 해결하기 위해이있는 UIImage 확장을 만들었습니다. 그래서이 클래스 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) 
    } 

}