2010-08-24 7 views
42

Quiero cargar imágenes de UIImagePickerController, luego guardo la foto seleccionada en el directorio de documentos de mi aplicación.UIImagePNGR ¿Problemas con la presentación?/Imágenes giradas 90 grados

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]; 

pero después de guardar la imagen en mi documento, he encontrado que, la imagen se gira 90 grados, entonces puedo cambiar el método UIImagePNGRepresentation a UIImageJPEGRepresentation, esta vez está bien, alguien sabe cuál es el problema?

+0

tenía el mismo problema. – ZaBlanc

+0

posible duplicado de [iOS UIImagePickerController orientación de la imagen del resultado después de la carga] (http://stackoverflow.com/questions/5427656/ios-uiimagepickercontroller-result-image-orientation-after-upload) –

Respuesta

70

Tuve el mismo problema y me di cuenta de la razón: a partir de iOS 4.0 cuando la cámara toma una foto no la gira antes de guardarla, simplemente establece un indicador de rotación en los datos EXIF ​​de JPEG.

Si guarda un UIImage como JPEG, establecerá el indicador de rotación.

Los PNG no admiten un indicador de rotación, por lo que si guarda un UIImage como PNG, se rotará incorrectamente y no tendrá un indicador configurado para corregirlo. Entonces, si quieres PNG, debes rotarlos tú mismo.

Llamaría esto un error en la función de guardado de PNG, pero eso es solo una opinión (al menos deberían advertirlo).

+0

muchas gracias. – disorderdev

+0

Pasé probablemente una hora más o menos tratando de hacer girar mi PNG CGImageSource (creado a partir de datos) cuando se creó el pulgar ... insertando datos exif en las opciones de creación de CGImageSource, etc. etc. y UIImageJPEGRepresentation lo arregló de inmediato ! ¡Gracias! – taber

+3

@jasongregori: Incluso guardarlo como JPEG no resuelve mi problema. La imagen aún gira. –

14

Resuelvo este problema con el siguiente código.

- (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

Me gusta este código y de alguna manera es el único que funciona en términos de rotación de mi imagen. De todos modos, tengo problemas para hacer que funcione en iOS 7.1 y el ciclo ARC. ¿Alguna idea de dónde podría estar el problema? –

+0

¡Gracias por esto! ¡Trabajado como un encanto! Lo traduje a swift 2.0 para mi proyecto actual. Aquí hay una esencia: https: //gist.github.com/fnk0/2e108700bdbe4a92766c –

+0

@MarcusGabilheri ¿cómo usaría su código para girar 90 grados? – alex

2

La siguiente función rápida resuelve el problema.

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

    UIGraphicsBeginImageContext(size) 

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

    UIGraphicsEndImageContext() 

    return copy 
} 

Sí es así de simple, sólo porque la función drawInRect tomará en consideración orientación de la imagen.

+0

¿cómo usaría esto? en este momento mi código imageHolder se ve así: 'invoiceImageHolder.image = loadImageFromPath (fileInDocumentsDirectory ((" \ (imagePath!) ")))' y obtengo errores Uso del identificador sin resolver 'imageOrientation' – alex

9

prueba este:

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

Muchas gracias. Hacer esto antes de guardar la imagen como .png lo resolvió para mí. – Alexandros

1

He creado esta extensión UIImage para solucionar este problema UIImagePNGRepresentation, basado en this response. Así que propongo usar esta clase func UIImage.PNGRepresentation(img: UIImage) en lugar de UIKit func UIImagePNGRepresentation.

Swift 3 Código:

// 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) 
    } 

} 
Cuestiones relacionadas