Je souhaite charger des images à partir de UIImagePickerController, puis enregistrer la photo sélectionnée dans le répertoire de documents de mon application.
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];
mais après avoir sauvegardé l'image dans mon document, j'ai constaté que l'image pivotait de 90 degrés, puis je changeais la méthode UIImagePNGRepresentation en UIImageJPEGRepresentation, cette fois, tout va bien, tout le monde sait quel est le problème?
J'avais le même problème et je venais juste d'en comprendre la raison: à partir de iOS 4.0, lorsque l'appareil photo prend une photo, il ne la fait pas pivoter avant de l'enregistrer, mais il active simplement un indicateur de rotation dans les données EXIF du fichier JPEG.
Si vous enregistrez une UIImage au format JPEG, le drapeau de rotation sera défini.
Les fichiers PNG ne prennent pas en charge un indicateur de rotation. Par conséquent, si vous enregistrez une UIImage en tant que fichier PNG, sa rotation sera incorrecte et aucun indicateur ne le configurera. Donc, si vous voulez des PNG, vous devez les faire tourner vous-même.
J'appellerais cela un bug dans la fonction de sauvegarde de PNG mais ce n'est qu'un avis (ils devraient au moins vous en avertir).
Essaye celui-là:
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
}
Je résous ce problème avec le code suivant.
- (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;
}
La fonction Swift suivante résout le problème.
var rotatedCopy: UIImage {
if (imageOrientation == UIImageOrientation.Up) {
return self
}
UIGraphicsBeginImageContext(size)
drawInRect(CGRect(Origin: CGPoint.zeroPoint, size: size))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy
}
Oui, c'est aussi simple que cela, simplement parce que la fonction drawInRect
tiendra compte de l'orientation de l'image.
J'ai créé cette extension UIImage pour résoudre ce problème avec UIImagePNGRepresentation, basé sur cette réponse . Je propose donc d’utiliser cette classe func UIImage.PNGRepresentation(img: UIImage)
à la place de UIKit func UIImagePNGRepresentation.
Swift 3 code:
// 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)
}
}
La réponse de Stefan mise à jour pour Swift 4:
func rotateImage(image: UIImage) -> UIImage {
if (image.imageOrientation == UIImage.Orientation.up) {
return image
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(Origin: .zero, size: image.size))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy!
}
Et alors:
var originalImage = yourImage.image!
image = rotateImage(image: originalImage)