web-dev-qa-db-fra.com

iOS: l'image subit une rotation de 90 degrés après son enregistrement en tant que données de représentation PNG

J'ai suffisamment recherché pour que cela fonctionne, mais je ne suis pas capable de le réparer. Après avoir pris une photo de l'appareil photo tant que l'image est stockée au format UIImage, tout va bien, mais dès que j'ai stocké cette image au format PNG, sa rotation est effectuée à 90 degrés.

Voici mon code et toutes les choses que j'ai essayées:

- (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];
}

Voici les fonctions fixOrientation et scaleAndRotateImage extraites de ici et ici respectivement. Ils fonctionnent bien et font pivoter l'image lorsque je les applique sur UIImage, mais ne fonctionnent pas si je sauvegarde l'image en représentation PNG et que je les applique.

Veuillez regarder l'image suivante après avoir exécuté les fonctions ci-dessus:

The first photo is original, second is saved, and third and fourth after applying fixorientation and scaleandrotate functions on saved image

35
applefreak

À partir de iOS 4.0, lorsque l'appareil photo prend une photo, il ne la fait pas pivoter avant de l'enregistrer. 

définit simplement un indicateur de rotation dans les données EXIF ​​du fichier JPEG.Si vous enregistrez une UIImage au format JPEG, 

définira l’indicateur de rotation.PNG ne prend pas en charge l’indicateur de rotation. Par conséquent, si vous enregistrez une 

PNG, la rotation sera incorrecte et aucun indicateur ne le réglera. Donc si vous voulez PNG 

images que vous devez faire pivoter vous-même, pour cela vérifier ce link .

63
Mudit Bajpai

Version Swift 3.1 de l'extension UIImage publiée par 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
        }
    }
}

Usage:

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

Pour Swift 2.1

Ajouter ce qui suit comme extension 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;
    }
}

Exemple d'utilisation:

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

J'ai trouvé les conseils suivants extrêmement utiles:

1. sortie naturelle est paysage

2. .width/.height SONT affectés par .imageOrientation

3 utilise la dimension courte plutôt que la largeur.


(1) la sortie 'naturelle' de la caméra pour les images fixes IS PAYSAGE.

c'est contre-intuitif. Le portrait est le seul moyen offert par UIImagePickerController etc.

(La façon dont je me souviens de ceci - la sortie naturelle de la vidéo est (bien sûr) du paysage; ainsi, les images fixes sont identiques - bien que l'iPhone soit tout en portrait


(2) .width et .height sont en effet affectés par le .imageOrientation !!!!!!!!!

Assurez-vous de le faire et essayez-le dans les deux sens sur votre iPhone,

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

vous verrez que les changements de hauteur et de largeur sont "même si" les vrais pixels sont en paysage.


(3) utiliser simplement la "dimension courte" plutôt que la largeur, peut souvent résoudre de nombreux problèmes

J'ai trouvé cela extrêmement utile. Supposons que vous souhaitiez peut-être le carré supérieur de l'image:

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

cela ne fonctionnera pas, vous obtiendrez une image écrasée, lorsque la caméra est ("vraiment") en position paysage.

mais si vous le faites très simplement

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

alors "tout est corrigé" et vous "vous n'avez pas à vous soucier de" l'indicateur d'orientation. Encore une fois, le point (3) n’est pas une panacée, mais il règle très souvent tous les problèmes.

J'espère que cela aide quelqu'un à gagner du temps.

6
Fattie

J'ai trouvé ce code ici , qui l'a corrigé pour moi. Pour mon application, je prenais une photo et la sauvegardais, et chaque fois que je la chargeais, la rotation gênante était attachée (j'ai levé les yeux, et cela a apparemment un rapport avec EXIF ​​et la manière dont l'iPhone prend et stocke les images). Ce code l'a corrigé pour moi. Je dois dire que c’était à l’origine un ajout à une classe/une extension/catégorie (vous pouvez trouver l’original à partir du lien. Je l’ai utilisé comme ci-dessous comme méthode simple car je ne voulais pas vraiment en faire un ensemble. Je n'ai utilisé que le mode portrait, mais je pense que le code fonctionne pour n'importe quelle orientation. Je ne suis pas sûr que

Rant over, voici le code:

- (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;
}

Je ne sais pas à quel point cela vous sera utile, mais j'espère que cela vous a aidé :) 

2
Septronic

Essayez ceci, vous pouvez utiliser 

NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0);

au lieu de

NSData *somenewImageData = UIImagePNGRepresentation(newimg);
2
vijay

Pls Essayez le code suivant

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];

Et 

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];

J'ai référencé de lien suivant ont cherché plus détail

Meilleures salutations :-)

1
NIKHIL

Essayez ce code:

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