La orientación de la imagen de iOS tiene un comportamiento extraño

Durante las últimas semanas he estado trabajando con imágenes en Objective-C y noté un montón de comportamientos extraños. En primer lugar, como muchas otras personas, he tenido este problema en el que las imágenes tomadas con la cámara (o tomadas con la cámara de otra persona y MMS) se giran 90 grados. No estaba seguro de por qué en el mundo esto estaba sucediendo (de ahí mi pregunta ) pero pude encontrar un trabajo barato.

Mi pregunta esta vez es por qué está pasando esto ? ¿Por qué Apple está rotando imágenes? Cuando tomo una foto con mi cámara con el lado derecho hacia arriba, a menos que realice el código mencionado anteriormente, cuando guardo la foto, se guarda rota. Ahora, mi solución estuvo bien hasta hace unos días.

Mi aplicación modifica los píxeles individuales de una imagen, específicamente el canal alfa de un archivo PNG (por lo que cualquier conversión JPEG se sale de la ventana para mi escenario). Hace unos días noté que a pesar de que la imagen se muestra correctamente en mi aplicación gracias a mi código de solución, cuando mi algoritmo modifica los píxeles individuales de la imagen, cree que la imagen se rota. Por lo tanto, en lugar de modificar los píxeles en la parte superior de la imagen, modifica los píxeles en el costado de la imagen (¡porque cree que debería girarse)! No puedo imaginar cómo rotar la imagen en la memoria. Idealmente, preferiría simplemente borrar esa bandera de imageOrientation .

Aquí hay algo más que también me ha estado desconcertando … Cuando tomo la foto, la imageOrientation la imageOrientation se establece en 3. Mi código de solución es lo suficientemente inteligente como para darme cuenta de esto y voltearlo para que el usuario nunca lo note. Además, mi código para guardar la imagen en la biblioteca se da cuenta de esto, lo voltea y luego lo guarda para que aparezca en el carrete de la cámara correctamente.

Ese código se ve así:

 NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]]; UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil); 

Cuando cargo esta imagen recién guardada en mi aplicación, imageOrientation es 0, exactamente lo que quiero ver, y mi solución de rotación ni siquiera necesita ejecutarse (nota: al cargar imágenes de Internet en lugar de imágenes tomadas con un cámara, la imageOrientation la imageOrientation siempre es 0, lo que resulta en un comportamiento perfecto). Por alguna razón, mi código de guardado parece borrar este indicador de imageOrientation . Esperaba robar ese código y usarlo para eliminar mi orientación de imagen tan pronto como el usuario toma una foto y la agrega a la aplicación, pero parece que no funciona. ¿ UIImageWriteToSavedPhotosAlbum hace algo especial con imageOrientation ?

La mejor solución para este problema sería simplemente eliminar la imageOrientation tan pronto como el usuario imageOrientation tomar una imagen. Supongo que Apple tiene el comportamiento de rotación hecho por una razón, ¿verdad? Algunas personas sugirieron que este es un defecto de Apple.

(… si aún no estás perdido … Nota 2: cuando tomo una foto horizontal, todo parece funcionar perfectamente, al igual que las fotos tomadas de Internet)

EDITAR:

Estas son algunas de las imágenes y escenarios que realmente se ven. Basado en los comentarios hasta el momento, parece que este comportamiento extraño es más que solo un comportamiento de iPhone, que creo que es bueno.

Esta es una foto de la foto que tomé con mi teléfono (tenga en cuenta la orientación correcta), aparece exactamente como lo hizo en mi teléfono cuando tomé la foto:

Foto real tomada en iPhone

Así es como se ve la imagen en Gmail después de que me lo envié por correo electrónico (parece que Gmail lo maneja correctamente):

Foto tal como aparece en Gmail

Aquí se muestra cómo se ve la imagen como una miniatura en las ventanas (no parece que se maneje correctamente):

Miniatura de Windows

Y así es como se ve la imagen real cuando se abre con Windows Photo Viewer (aún no se maneja correctamente):

Versión de Windows Photo Viewer

Después de todos los comentarios sobre esta pregunta, esto es lo que estoy pensando … El iPhone toma una imagen y dice “para que se muestre correctamente, debe girarse 90 grados”. Esta información estaría en los datos EXIF. (Por qué necesita girarse 90 grados, en lugar de predeterminarlo a vertical, no lo sé). Desde aquí, Gmail es lo suficientemente inteligente como para leer y analizar los datos EXIF ​​y mostrarlos correctamente. Sin embargo, Windows no es lo suficientemente inteligente como para leer los datos EXIF ​​y, por lo tanto, muestra la imagen incorrectamente . ¿Son mis suposiciones correctas?

Hice investigación y desarrollo en él y descubrí que cada archivo de imagen tiene propiedad de metadatos. Si los metadatos especifican la orientación de la imagen, generalmente es ignorada por otros sistemas operativos, pero Mac. La mayoría de las imágenes tomadas tienen sus propiedades de metadatos en ángulo recto. Así que Mac lo muestra 90 grados girados. Puede ver la misma imagen de la manera correcta en el sistema operativo Windows.

Para obtener más detalles, lea esta respuesta http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm

intente leer el exif de su imagen aquí http://www.exifviewer.org/ , o http://regex.info/exif.cgi , o http://www.addictivetips.com/internet-tips/view-complete-exper -metadata-información-de-cualquier-jpeg-image-online /

Tuve el mismo problema cuando recibí la imagen de la cámara, puse el siguiente código para arreglarlo. Agregué el método scaleAndRotateImage desde aquí

 - (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo { // Images from the camera are always in landscape, so rotate UIImage *image = [self scaleAndRotateImage: [imageInfo objectForKey:UIImagePickerControllerOriginalImage]]; //then save the image to photo gallery or wherever } - (UIImage *)scaleAndRotateImage:(UIImage *) image { int kMaxResolution = 320; 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; } 

Copie / pegue rápidamente la traducción rápida de la excelente respuesta de Dilip.

 import Darwin class func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage { let imgRef = imageSource.CGImage; let width = CGFloat(CGImageGetWidth(imgRef)); let height = CGFloat(CGImageGetHeight(imgRef)); var bounds = CGRectMake(0, 0, width, height) var scaleRatio : CGFloat = 1 if (width > maxResolution || height > maxResolution) { scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height) bounds.size.height = bounds.size.height * scaleRatio bounds.size.width = bounds.size.width * scaleRatio } var transform = CGAffineTransformIdentity let orient = imageSource.imageOrientation let imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef))) switch(imageSource.imageOrientation) { case .Up : transform = CGAffineTransformIdentity case .UpMirrored : transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); transform = CGAffineTransformScale(transform, -1.0, 1.0); case .Down : transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); transform = CGAffineTransformRotate(transform, CGFloat(M_PI)); case .DownMirrored : transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); transform = CGAffineTransformScale(transform, 1.0, -1.0); case .Left : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransformMakeTranslation(0.0, imageSize.width); transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0); case .LeftMirrored : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width); transform = CGAffineTransformScale(transform, -1.0, 1.0); transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0); case .Right : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0); transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0); case .RightMirrored : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransformMakeScale(-1.0, 1.0); transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0); default : () } UIGraphicsBeginImageContext(bounds.size) let context = UIGraphicsGetCurrentContext() if orient == .Right || orient == .Left { 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); let imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageCopy; } 

Versión Swift 3 con controles de seguridad de la respuesta de Dilip .

 public static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? { guard let imgRef = imageSource.cgImage else { return nil } let width = CGFloat(imgRef.width) let height = CGFloat(imgRef.height) var bounds = CGRect(x: 0, y: 0, width: width, height: height) var scaleRatio : CGFloat = 1 if (width > maxResolution || height > maxResolution) { scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height) bounds.size.height = bounds.size.height * scaleRatio bounds.size.width = bounds.size.width * scaleRatio } var transform = CGAffineTransform.identity let orient = imageSource.imageOrientation let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height)) switch(imageSource.imageOrientation) { case .up: transform = .identity case .upMirrored: transform = CGAffineTransform .init(translationX: imageSize.width, y: 0) .scaledBy(x: -1.0, y: 1.0) case .down: transform = CGAffineTransform .init(translationX: imageSize.width, y: imageSize.height) .rotated(by: CGFloat.pi) case .downMirrored: transform = CGAffineTransform .init(translationX: 0, y: imageSize.height) .scaledBy(x: 1.0, y: -1.0) case .left: let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform .init(translationX: 0, y: imageSize.width) .rotated(by: 3.0 * CGFloat.pi / 2.0) case .leftMirrored: let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform .init(translationX: imageSize.height, y: imageSize.width) .scaledBy(x: -1.0, y: 1.0) .rotated(by: 3.0 * CGFloat.pi / 2.0) case .right : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform .init(translationX: imageSize.height, y: 0) .rotated(by: CGFloat.pi / 2.0) case .rightMirrored: let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform .init(scaleX: -1.0, y: 1.0) .rotated(by: CGFloat.pi / 2.0) } UIGraphicsBeginImageContext(bounds.size) if let context = UIGraphicsGetCurrentContext() { if orient == .right || orient == .left { context.scaleBy(x: -scaleRatio, y: scaleRatio) context.translateBy(x: -height, y: 0) } else { context.scaleBy(x: scaleRatio, y: -scaleRatio) context.translateBy(x: 0, y: -height) } context.concatenate(transform) context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height)) } let imageCopy = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return imageCopy } 

Cualquier imagen generada por iPhone / iPad se guarda como Horizontal izquierda con etiqueta de orientación EXIF ​​(Exif.Image.Orientation) que especifica la orientación real.

Tiene los siguientes valores: 1: paisaje a la izquierda 6: retrato normal 3: paisaje a la derecha 4: retrato al revés

En IOS, la información EXIF ​​se lee correctamente y las imágenes se muestran de la misma manera en que se tomaron. Pero en Windows, la información EXIF ​​NO se usa.

Si abre una de estas imágenes en GIMP, dirá que la imagen tiene información de rotación.

Mi pregunta esta vez es por qué está pasando esto? ¿Por qué Apple está rotando imágenes?

La respuesta a esto es muy simple. Apple NO está rotando la imagen. Ahí es donde yace la confusión.

La cámara CCD no gira, por lo que siempre toma la foto en modo horizontal.

Apple hizo algo muy inteligente: en lugar de gastar todo el tiempo para rotar la imagen, mezclando megabytes de datos, simplemente marque con CÓMO se tomó la fotografía.

OpenGL hace traducciones muy fácilmente, por lo que los DATOS nunca se barajan, simplemente CÓMO SE SORTEO.

De ahí los metadatos de orientación.

Esto se convierte en un problema si quieres recortar, cambiar el tamaño, etc., pero una vez que sabes lo que está sucediendo, solo defines tu matriz y todo funciona.

Para cualquier otra persona que use Xamarin, aquí hay una traducción de C # de la gran respuesta de Dilip, y un agradecimiento a thattyson por la traducción de Swift .

 public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution) { var imgRef = imageSource.CGImage; var width = (nfloat)imgRef.Width; var height = (nfloat)imgRef.Height; var bounds = new CGRect(0, 0, width, height); nfloat scaleRatio = 1; if (width > maxResolution || height > maxResolution) { scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height); bounds.Height = bounds.Height * scaleRatio; bounds.Width = bounds.Width * scaleRatio; } var transform = CGAffineTransform.MakeIdentity(); var orient = imageSource.Orientation; var imageSize = new CGSize(imgRef.Width, imgRef.Height); nfloat storedHeight; switch(imageSource.Orientation) { case UIImageOrientation.Up: transform = CGAffineTransform.MakeIdentity(); break; case UIImageOrientation.UpMirrored : transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f); transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f); break; case UIImageOrientation.Down : transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height); transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI); break; case UIImageOrientation.DownMirrored : transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height); transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f); break; case UIImageOrientation.Left: storedHeight = bounds.Height; bounds.Height = bounds.Width; bounds.Width = storedHeight; transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width); transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f); break; case UIImageOrientation.LeftMirrored : storedHeight = bounds.Height; bounds.Height = bounds.Width; bounds.Width = storedHeight; transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width); transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f); transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f); break; case UIImageOrientation.Right : storedHeight = bounds.Height; bounds.Height = bounds.Width; bounds.Width = storedHeight; transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f); transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f); break; case UIImageOrientation.RightMirrored : storedHeight = bounds.Height; bounds.Height = bounds.Width; bounds.Width = storedHeight; transform = CGAffineTransform.MakeScale(-1.0f, 1.0f); transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f); break; default : break; } UIGraphics.BeginImageContext(bounds.Size); var context = UIGraphics.GetCurrentContext(); if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) { context.ScaleCTM(-scaleRatio, scaleRatio); context.TranslateCTM(-height, 0); } else { context.ScaleCTM(scaleRatio, -scaleRatio); context.TranslateCTM(0, -height); } context.ConcatCTM(transform); context.DrawImage(new CGRect(0, 0, width, height), imgRef); var imageCopy = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); return imageCopy; } 

Me encontré con esta pregunta porque estaba teniendo un problema similar, pero usando Swift. Solo quería vincular la respuesta que funcionó para mí para cualquier otro desarrollador de Swift: https://stackoverflow.com/a/26676578/3904581

Aquí hay un fragmento de Swift que soluciona el problema de manera eficiente:

 let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)! 

Súper simple. Una linea de codigo Problema resuelto.

Sé exactamente cuál es tu problema. Estás usando UIImagePicker, que es extraño en todos los sentidos. Le sugiero que use AVFoundation para la cámara, que brinda flexibilidad en la orientación y la calidad. Use AVCaptureSession. Puede obtener el código aquí ¿Cómo guardar fotos tomadas con AVFoundation en Photo Album?

Refactorizado rápidamente para Swift 3 (¿alguien puede probarlo y confirmar que todo funciona bien?):

 static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage { let imgRef = imageSource.cgImage let width = CGFloat(imgRef!.width) let height = CGFloat(imgRef!.height) var bounds = CGRect(x: 0, y: 0, width: width, height: height) var scaleRatio : CGFloat = 1 if width > maxResolution || height > maxResolution { scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height) bounds.size.height = bounds.size.height * scaleRatio bounds.size.width = bounds.size.width * scaleRatio } var transform = CGAffineTransform.identity let orient = imageSource.imageOrientation let imageSize = CGSize(width: imgRef!.width, height: imgRef!.height) switch imageSource.imageOrientation { case .up : transform = CGAffineTransform.identity case .upMirrored : transform = CGAffineTransform(translationX: imageSize.width, y: 0) transform = transform.scaledBy(x: -1, y: 1) case .down : transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height) transform = transform.rotated(by: CGFloat.pi) case .downMirrored : transform = CGAffineTransform(translationX: 0, y: imageSize.height) transform = transform.scaledBy(x: 1, y: -1) case .left : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width bounds.size.width = storedHeight transform = CGAffineTransform(translationX: 0, y: imageSize.width) transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0) case .leftMirrored : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width bounds.size.width = storedHeight transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width) transform = transform.scaledBy(x: -1, y: 1) transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0) case .right : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width bounds.size.width = storedHeight transform = CGAffineTransform(translationX: imageSize.height, y: 0) transform = transform.rotated(by: CGFloat.pi / 2.0) case .rightMirrored : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width bounds.size.width = storedHeight transform = CGAffineTransform(scaleX: -1, y: 1) transform = transform.rotated(by: CGFloat.pi / 2.0) } UIGraphicsBeginImageContext(bounds.size) let context = UIGraphicsGetCurrentContext() if orient == .right || orient == .left { context!.scaleBy(x: -scaleRatio, y: scaleRatio) context!.translateBy(x: -height, y: 0) } else { context!.scaleBy(x: scaleRatio, y: -scaleRatio) context!.translateBy(x: 0, y: -height) } context!.concatenate(transform) context!.draw(imgRef!, in: CGRect(x: 0, y: 0, width: width, height: height)) let imageCopy = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return imageCopy! } 

Aquí está la versión Swift3 de la increíble respuesta de Dilip

 func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage { let imgRef = imageSource.cgImage!; let width = CGFloat(imgRef.width); let height = CGFloat(imgRef.height); var bounds = CGRect(x: 0, y: 0, width: width, height: height) var scaleRatio : CGFloat = 1 if (width > maxResolution || height > maxResolution) { scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height) bounds.size.height = bounds.size.height * scaleRatio bounds.size.width = bounds.size.width * scaleRatio } var transform = CGAffineTransform.identity let orient = imageSource.imageOrientation let imageSize = CGSize(width: width, height: height) switch(imageSource.imageOrientation) { case .up : transform = CGAffineTransform.identity case .upMirrored : transform = CGAffineTransform(translationX: imageSize.width, y: 0.0); transform = transform.scaledBy(x: -1, y: 1); case .down : transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height); transform = transform.rotated(by: CGFloat(Double.pi)); case .downMirrored : transform = CGAffineTransform(translationX: 0.0, y: imageSize.height); transform = transform.scaledBy(x: 1, y: -1); case .left : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform(translationX: 0.0, y: imageSize.width); transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0); case .leftMirrored : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width); transform = transform.scaledBy(x: -1, y: 1); transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0); case .right : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform(translationX: imageSize.height, y: 0.0); transform = transform.rotated(by: CGFloat(Double.pi) / 2.0); case .rightMirrored : let storedHeight = bounds.size.height bounds.size.height = bounds.size.width; bounds.size.width = storedHeight; transform = CGAffineTransform(scaleX: -1.0, y: 1.0); transform = transform.rotated(by: CGFloat(Double.pi) / 2.0); } UIGraphicsBeginImageContext(bounds.size) let context = UIGraphicsGetCurrentContext()! if orient == .right || orient == .left { context.scaleBy(x: -scaleRatio, y: scaleRatio); context.translateBy(x: -height, y: 0); } else { context.scaleBy(x: scaleRatio, y: -scaleRatio); context.translateBy(x: 0, y: -height); } context.concatenate(transform); context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height)) let imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageCopy!; } 

Intente cambiar el formato de la imagen a .jpeg. Esto funcionó para mí