iOS: la imagen se gira 90 grados después de guardar como datos de representación PNG

Investigué lo suficiente para que esto funcione, pero no puedo solucionarlo. Después de tomar una foto de la cámara, siempre y cuando tenga la imagen almacenada como UIImage, está bien, pero tan pronto como almacené esta imagen como una representación PNG, se giró 90 grados.

Lo siguiente es mi código y todas las cosas que probé:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType]; if([mediaType isEqualToString:(NSString*)kUTTypeImage]) { AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; delegate.originalPhoto = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; NSLog(@"Saving photo"); [self saveImage]; NSLog(@"Fixing orientation"); delegate.fixOrientationPhoto = [self fixOrientation:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]]; NSLog(@"Scaling photo"); delegate.scaledAndRotatedPhoto = [self scaleAndRotateImage:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]]; } [picker dismissModalViewControllerAnimated:YES]; [picker release]; } - (void)saveImage { AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; NSData *imageData = UIImagePNGRepresentation(delegate.originalPhoto); [imageData writeToFile:[delegate filePath:imageName] atomically:YES]; } 

Aquí las funciones fixOrientation y scaleAndRotateImage son tomadas aquí y aquí, respectivamente. Funcionan bien y giran la imagen cuando los aplico en UIImage, pero no funcionan si guardo la imagen como representación PNG y la aplico.

Por favor refiera la siguiente imagen después de ejecutar las funciones anteriores:

La primera foto es original, la segunda se guarda y la tercera y la cuarta después de aplicar las funciones de orientación y escalado y giro en la imagen guardada

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á la bandera de rotación. Los GPG 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

las imágenes deben rotarlas usted mismo, para eso revise este enlace .

Versión de Swift 3.1 de la extensión de UIImage publicada por Rao:

 extension UIImage { func fixOrientation() -> UIImage { if self.imageOrientation == UIImageOrientation.up { return self } UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)) if let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() { UIGraphicsEndImageContext() return normalizedImage } else { return self } } } 

Uso:

 let cameraImage = //image captured from camera let orientationFixedImage = cameraImage.fixOrientation() 

Para Swift 2.1

Agregue lo siguiente como extensión de UIImage,

 extension UIImage { func fixOrientation() -> UIImage { if self.imageOrientation == UIImageOrientation.Up { return self } UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) self.drawInRect(CGRectMake(0, 0, self.size.width, self.size.height)) let normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return normalizedImage; } } 

Ejemplo de uso:

 let cameraImage = //image captured from camera let orientationFixedImage = cameraImage.fixOrientation() 

He encontrado los siguientes consejos para ser de gran utilidad:

1. salida natural es paisaje

2. .width / .height SON afectados por .imageOrientation

3 usa una dimensión corta en lugar de. Ancho


(1) la salida ‘natural’ de la cámara para fotogtwigs ES PAISAJE.

esto es contrario a la intuición el retrato es la única forma ofrecida por UIImagePickerController, etc. Pero obtendrás UIImageOrientationRight como orientación “normal” cuando usas la cámara vertical “normal”

(La forma en que recuerdo esto es que el resultado natural para el video es (por supuesto) el paisaje, por lo que las instantáneas son las mismas, aunque el iPhone se trata solo de retratos).


(2) .width y .height se ven afectados por .imageOrientation !!!!!!!!!

Asegúrate de hacer esto y pruébalo de ambas maneras en tu iPhone.

 NSLog(@"fromImage.imageOrientation is %d", fromImage.imageOrientation); NSLog(@"fromImage.size.width %f fromImage.size.height %f", fromImage.size.width, fromImage.size.height); 

verá que el swap .height y .width, “aunque” los píxeles reales son horizontales.


(3) simplemente usar la “dimensión corta” en lugar de .width, a menudo puede resolver muchos problemas

Me pareció increíblemente útil. Digamos que quieres tal vez el cuadro superior de la imagen:

 CGRect topRectOfOriginal = CGRectMake(0,0, im.size.width,im.size.width); 

que en realidad no funcionará, obtendrás una imagen aplastada, cuando la cámara está (“realmente”) retenida en el paisaje.

sin embargo, si simplemente haces esto

 float shortDimension = fminf(im.size.width, im.size.height); CGRect topRectOfOriginal = CGRectMake(0,0, shortDimension,shortDimension); 

entonces “todo está arreglado” y en realidad “no necesita preocuparse” de la bandera de orientación. De nuevo, el punto (3) no es una panacea, pero a menudo resuelve todos los problemas.

Espero que ayude a alguien a ahorrar algo de tiempo.

Encontré este código aquí , que realmente lo solucionó para mí. Para mi aplicación, tomé una foto y la guardé, y cada vez que la cargaba, tenía la rotación molesta adjunta (levanté la vista, y aparentemente tiene que ver con el EXIF ​​y la forma en que el iPhone toma y almacena las imágenes). Este código me lo arregló Tengo que decir que fue originalmente como una adición a una clase / una extensión / categoría (puedes encontrar el original del enlace. Lo usé a continuación como un método simple, ya que realmente no quería hacer un todo clase o categoría solo por esto. Solo usé retrato, pero creo que el código funciona para cualquier orientación. No estoy seguro

Rant más, aquí está el código:

 - (UIImage *)fixOrientationForImage:(UIImage*)neededImage { // No-op if the orientation is already correct if (neededImage.imageOrientation == UIImageOrientationUp) return neededImage; // 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. CGAffineTransform transform = CGAffineTransformIdentity; switch (neededImage.imageOrientation) { case UIImageOrientationDown: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, neededImage.size.width, neededImage.size.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: transform = CGAffineTransformTranslate(transform, neededImage.size.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, 0, neededImage.size.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; case UIImageOrientationUp: case UIImageOrientationUpMirrored: break; } switch (neededImage.imageOrientation) { case UIImageOrientationUpMirrored: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, neededImage.size.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, neededImage.size.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationUp: case UIImageOrientationDown: case UIImageOrientationLeft: case UIImageOrientationRight: break; } // Now we draw the underlying CGImage into a new context, applying the transform // calculated above. CGContextRef ctx = CGBitmapContextCreate(NULL, neededImage.size.width, neededImage.size.height, CGImageGetBitsPerComponent(neededImage.CGImage), 0, CGImageGetColorSpace(neededImage.CGImage), CGImageGetBitmapInfo(neededImage.CGImage)); CGContextConcatCTM(ctx, transform); switch (neededImage.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: // Grr... CGContextDrawImage(ctx, CGRectMake(0,0,neededImage.size.height,neededImage.size.width), neededImage.CGImage); break; default: CGContextDrawImage(ctx, CGRectMake(0,0,neededImage.size.width,neededImage.size.height), neededImage.CGImage); break; } // And now we just create a new UIImage from the drawing context CGImageRef cgimg = CGBitmapContextCreateImage(ctx); UIImage *img = [UIImage imageWithCGImage:cgimg]; CGContextRelease(ctx); CGImageRelease(cgimg); return img; } 

No estoy seguro de lo útil que será para ti, pero espero que haya sido útil 🙂

Prueba esto, puedes usar

 NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0); 

en lugar de

 NSData *somenewImageData = UIImagePNGRepresentation(newimg); 

Pls Pruebe el siguiente código

 UIImage *sourceImage = ... // Our image CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0); CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, selectionRect); UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef]; 

Y

 CGRect TransformCGRectForUIImageOrientation(CGRect source, UIImageOrientation orientation, CGSize imageSize) { switch (orientation) { case UIImageOrientationLeft: { // EXIF #8 CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.height, 0.0); CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI_2); return CGRectApplyAffineTransform(source, txCompound); } case UIImageOrientationDown: { // EXIF #3 CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI); return CGRectApplyAffineTransform(source, txCompound); } case UIImageOrientationRight: { // EXIF #6 CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(0.0, imageSize.width); CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI + M_PI_2); return CGRectApplyAffineTransform(source, txCompound); } case UIImageOrientationUp: // EXIF #1 - do nothing default: // EXIF 2,4,5,7 - ignore return source; } } ... UIImage *sourceImage = ... // Our image CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0); CGRect transformedRect = TransformCGRectForUIImageOrientation(selectionRect, sourceImage.imageOrientation, sourceImage.size); CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, transformedRect); UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef]; 

He referido desde el siguiente enlace he buscado más detalles

Atentamente 🙂

Prueba este código:

 NSData *imageData = UIImageJPEGRepresentation(delegate.originalPhoto,100);