Perder la orientación de la image al convertir una image a CGImage

Estoy enfrentando un problema de orientación de image al recortar una parte cuadrada de una image de una image original rectangular. Cuando la image está en paisaje, está bien. Pero cuando está en retrato, parece que la orientación de la image no se conserva, lo que da como resultado una image con orientación incorrecta y un recorte incorrecto:

func cropImage(cropRectangleCoordinates: CGRect) { let croppedImage = originalImage let finalCroppedImage : CGImageRef = CGImageCreateWithImageInRect(croppedImage.CGImage, cropRectangleCoordinates) finalImage = UIImage(CGImage: finalCroppedImage)! } 

Creo que el problema es con croppedImage.CGImage . Aquí la image se convierte a CGImage , pero parece que no conserva la orientación. Es fácil preservar la orientación utilizando solo UIImage , pero para hacer el recorte, la image debe ser temporalmente CGImage y este es el problema. Incluso si reoriento la image al convertir de nuevo a UIImage , podría estar en la orientación correcta, pero el daño ya se ha CGImage al recortar CGImage .

Esta es una pregunta rápida, así que responda rápidamente, ya que la solución puede ser diferente en Objective-C.

SWIFT 3:

convertir cgImage rotado a UIImage por este método

 UIImage(cgImage:croppedCGImage, scale:originalImage.scale, orientation:originalImage.imageOrientation) 

Fuente @David Berry respuesta

Encontré una solución … el time dirá si es lo suficientemente robusto, pero parece funcionar en todas las situaciones. Ese fue un error vicioso para arreglar.

Entonces, el problema es que UIImage, en algunos casos solo, pierde su orientación cuando se convierte a CGImage. Afecta a la image de los retratos, que se ponen automáticamente en modo horizontal. Entonces, la image que son paisajes de forma pnetworkingeterminada no se ve afectada. ¡Pero donde el error es vicioso es que no afecta TODAS las imágenes de retrato! Además, el valor de orientación de image no ayudará a algunas imágenes. Esas imágenes problemáticas son imágenes que el usuario tiene en su biblioteca que obtuvo de correos electrónicos, posts o guardados de la web, por lo que no se toman con una camera. Es posible que estas imágenes no tengan información de orientación y, en algunos casos, una image en retrato … PERMANECE en retrato cuando se convierte a CGImage. Realmente me quedé atrapado en eso hasta que me di count de que parte de mi image en la biblioteca de mi dispositivo se guardaba de posts o correos electrónicos.

Por lo tanto, la única manera confiable que encontré para adivinar qué image será reorientada es crear ambas versiones de una image determinada: UIImage y CGImage, y comparar su valor de altura. Si son iguales, la versión de CGImage no se rotará y podría trabajar con ella como se esperaba. Pero si su altura es diferente, puede estar seguro de que la conversión de CGImage de CGImageCreateWithImageInRect paisajizará la image. En este caso, solo cambio la coorderada x / y de origen, que paso como una coorderada de rectángulo para recortar y trata esas imágenes especiales correctamente.

Esa fue una publicación larga, pero la idea principal es comparar la altura de CGImage con el ancho de UIImage, y si son diferentes, se espera que el punto de origen se invierta.

Cambie su llamada de creación UIImage a:

 finalImage = UIImage(CGImage:finalCroppedImage, scale:originalImage.scale, orientation:originalImage.orientation) 

para mantener la orientación original (y la escala) de la image.

Aquí hay una extensión de UIImage que escribí después de search y mirar varias piezas de código antiguas escritas por otros. Está escrito en Swift 3 y usa la propiedad de orientación iOS más CGAffineTransform para volver a dibujar la image en la orientación adecuada.

SWIFT 3:

 public extension UIImage { /// Extension to fix orientation of an UIImage without EXIF func fixOrientation() -> UIImage { guard let cgImage = cgImage else { return self } if imageOrientation == .up { return self } var transform = CGAffineTransform.identity switch imageOrientation { case .down, .downMirronetworking: transform = transform.translatedBy(x: size.width, y: size.height) transform = transform.rotated(by: CGFloat(M_PI)) case .left, .leftMirronetworking: transform = transform.translatedBy(x: size.width, y: 0) transform = transform.rotated(by: CGFloat(M_PI_2)) case .right, .rightMirronetworking: transform = transform.translatedBy(x: 0, y: size.height) transform = transform.rotated(by: CGFloat(-M_PI_2)) case .up, .upMirronetworking: break } switch imageOrientation { case .upMirronetworking, .downMirronetworking: transform.translatedBy(x: size.width, y: 0) transform.scaledBy(x: -1, y: 1) case .leftMirronetworking, .rightMirronetworking: transform.translatedBy(x: size.height, y: 0) transform.scaledBy(x: -1, y: 1) case .up, .down, .left, .right: break } if let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: cgImage.colorSpace!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) { ctx.concatenate(transform) switch imageOrientation { case .left, .leftMirronetworking, .right, .rightMirronetworking: ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width)) default: ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) } if let finalImage = ctx.makeImage() { return (UIImage(cgImage: finalImage)) } } // something failed -- return original return self } }