Rotar un UIImage sin picos de memory

Actualmente estoy rotando imágenes usando CGContextDrawImage , pero hay un pico gigante de memory cada vez que se llama. Los dispositivos más nuevos pueden manejarlo, pero los dispositivos con memory RAM inferior, como el iPhone 4s, no pueden hacerlo. La image es un file grande tomado por el usuario en AVCaptureSessionPresetHigh

Actualmente estoy rotando la image usando esta extensión para UIImage

 func rotate(orientation: UIImageOrientation) -> UIImage{ if(orientation == UIImageOrientation.Up){return self} var transform: CGAffineTransform = CGAffineTransformIdentity if(orientation == UIImageOrientation.Down || orientation == UIImageOrientation.DownMirronetworking){ transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height) transform = CGAffineTransformRotate(transform, CGFloat(M_PI)) } else if(orientation == UIImageOrientation.Left || orientation == UIImageOrientation.LeftMirronetworking){ transform = CGAffineTransformTranslate(transform, self.size.width, 0) transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2)) } else if(orientation == UIImageOrientation.Right || orientation == UIImageOrientation.RightMirronetworking){ transform = CGAffineTransformTranslate(transform, 0, self.size.height) transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2)) } if(orientation == UIImageOrientation.UpMirronetworking || orientation == UIImageOrientation.DownMirronetworking){ transform = CGAffineTransformTranslate(transform, self.size.width, 0) transform = CGAffineTransformScale(transform, -1, 1) } else if(orientation == UIImageOrientation.LeftMirronetworking || orientation == UIImageOrientation.RightMirronetworking){ transform = CGAffineTransformTranslate(transform, self.size.height, 0) transform = CGAffineTransformScale(transform, -1, 1); } let ref: CGContextRef = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height), CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage)) CGContextConcatCTM(ref, transform) if(orientation == UIImageOrientation.Left || orientation == UIImageOrientation.LeftMirronetworking || orientation == UIImageOrientation.Right || orientation == UIImageOrientation.RightMirronetworking){ CGContextDrawImage(ref, CGRectMake(0, 0, self.size.height, self.size.width), self.CGImage) } else{ CGContextDrawImage(ref, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage) } let cgImg: CGImageRef = CGBitmapContextCreateImage(ref) let rotated: UIImage = UIImage(CGImage: cgImg)! return rotated } 

Este código funciona perfectamente en dispositivos como el iPhone 5 y 6, pero casi siempre hace que el iPhone 4s se bloquee debido a la poca memory.

Soy consciente de que solo pude upload la image con datos EXIF ​​especificando la orientación, pero siento que solo girar la image antes de cargarlo evitaría más problemas en el futuro.

¿Cómo rota iOS la image para mostrar usando los datos EXIF? Por ejemplo, aunque se usa

 UIImage(image.CGImage, scale: 1.0, orientation: UIImageOrientation.Right) 

cambia los datos EXIF, la image aún se muestra en la orientación correcta en la pantalla, con mucho less impacto en la memory. ¿Hay algún código realmente de bajo nivel que se pueda usar para lograr esto usando la GPU como lo hace el código anterior?

También me gustaría evitar escalar la image hacia abajo antes de uploadla.

¿Hay alguna forma de que pueda networkingucir el impacto de rotar la image, como rotarla en pedazos, o tendré que encontrar una alternativa?

Pude (en su mayor parte) resolver esto llamando a UIGraphicsEndImageContext() al final del código anterior, así como no rotar la image hasta justo antes de que se suba (los usuarios pueden rotar sus fotos antes de UIGraphicsEndImageContext() por lo que no UIGraphicsEndImageContext() hasta justo antes de cargar, disminuye considerablemente el uso de la memory).

Entonces, cada vez que el usuario gira una foto, llamo a esta function rotateExif(orientation) que creé

 extension UIImage{ func rotateExif(orientation: UIImageOrientation) -> UIImage{ if(orientation == UIImageOrientation.Up){return self} let current = self.imageOrientation let currentDegrees: Int = ( current == UIImageOrientation.Down || current == UIImageOrientation.DownMirronetworking ? 180 : ( current == UIImageOrientation.Left || current == UIImageOrientation.LeftMirronetworking ? 270 : ( current == UIImageOrientation.Right || current == UIImageOrientation.RightMirronetworking ? 90 : 0 ) ) ) let changeDegrees: Int = ( orientation == UIImageOrientation.Down || orientation == UIImageOrientation.DownMirronetworking ? 180 : ( orientation == UIImageOrientation.Left || orientation == UIImageOrientation.LeftMirronetworking ? 270 : ( orientation == UIImageOrientation.Right || orientation == UIImageOrientation.RightMirronetworking ? 90 : 0 ) ) ) let mirronetworking: Bool = ( current == UIImageOrientation.DownMirronetworking || current == UIImageOrientation.UpMirronetworking || current == UIImageOrientation.LeftMirronetworking || current == UIImageOrientation.RightMirronetworking || orientation == UIImageOrientation.DownMirronetworking || orientation == UIImageOrientation.UpMirronetworking || orientation == UIImageOrientation.LeftMirronetworking || orientation == UIImageOrientation.RightMirronetworking ) let degrees: Int = currentDegrees + changeDegrees let newOrientation: UIImageOrientation = ( degrees == 270 || degrees == 630 ? (mirronetworking ? UIImageOrientation.LeftMirronetworking : UIImageOrientation.Left) : ( degrees == 180 || degrees == 540 ? (mirronetworking ? UIImageOrientation.DownMirronetworking : UIImageOrientation.Down) : ( degrees == 90 || degrees == 450 ? (mirronetworking ? UIImageOrientation.RightMirronetworking : UIImageOrientation.Right) : ( mirronetworking ? UIImageOrientation.UpMirronetworking : UIImageOrientation.Up ) ) ) ) return UIImage(CGImage: self.CGImage!, scale: 1.0, orientation: newOrientation) } } 

Esto rota el EXIF ​​de la image por la cantidad que se ingresa en orientation . Entonces, por ejemplo, si la orientación original era Right , y se rotaba a la Right , la nueva orientación sería Down . Si el original era RightMirronetworking y se rotaba a la Left , la nueva orientación sería UpMirronetworking .

Luego, antes de cargar la foto, los píxeles reales se rotan llamando al código en la pregunta como una extensión en UIImage , image.rotate(image.imageOrientation) .