Image iOS PNG tournée de 90 degrés

dans mon application iOS j'écris, je traite avec les png parce que je traite avec la chaîne alpha. Pour une raison quelconque, je peux charger un PNG dans mon imageView très bien, mais quand il vient le temps de copier l'image hors de mon application (sur le carton) ou enregistrer l'image dans mon rouleau de caméra, l'image tourne de 90 degrés.

j'ai cherché partout sur ce, et une des choses que j'ai appris est que si j'ai utilisé JPEGs, Je n'aurais pas ce problème( il semble), en raison à l'information EXIF.

mon application a la fonctionnalité copier/coller complet, et voici le kicker (je vais écrire ceci par étapes afin qu'il soit plus facile de suivre):

  1. allez à mon rouleau de caméra et copiez une image
  2. allez dans mon application et appuyez sur "Paste", pâtes d'image juste très bien, et je peux le faire toute la journée
  3. clique sur la fonction de copie que j'ai implémentée, puis clique sur "Coller", et l'image passe mais est tournée.

je suis sûr à 100% que mon code de copier-coller n'est pas ce qui ne va pas ici, parce que si je reviens à L'Étape 2 ci-dessus, et que je clique sur" Enregistrer", la photo enregistre dans ma bibliothèque mais elle est tournée de 90 degrés!

ce qui est encore plus étrange, c'est qu'il semble bien fonctionner avec des images téléchargées à partir de l'internet, mais est très frappé ou manquer avec des images que j'ai pris manuellement avec le téléphone. Certains qu'il fonctionne, certains, il ne le fait pas...

est-ce que quelqu'un a pensées à ce sujet? Toutes les solutions de contournement possibles que je peux utiliser? Je suis assez confiant dans le code, il fonctionne pour environ 75% de mes images. Je peux poster le code sur demande.

26
demandé sur Boeckm 2012-04-25 03:44:10

6 réponses

pour ceux qui veulent une solution Swift, créer une extension D'UIImage et ajouter la méthode suivante:

func correctlyOrientedImage() -> UIImage {
    if self.imageOrientation == .up {
        return self
    }

    UIGraphicsBeginImageContextWithOptions(size, false, scale)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    let normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return normalizedImage ?? self;
}
25
répondu Tom J 2018-04-25 12:43:08

si vous avez des problèmes en raison de l'image existante imageOrientation propriété, vous pouvez construire une image par ailleurs identique avec une orientation différente comme celle-ci:

CGImageRef imageRef = [sourceImage CGImage];

UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];

vous pourriez avoir besoin d'expérimenter avec juste quelle orientation pour mettre sur vos images de remplacement, éventuellement commutation basée sur l'orientation que vous avez commencé avec.

gardez également un oeil sur votre utilisation de la mémoire. Les applications de photographie sont souvent épuisées, et cela doublera votre stockage par image, jusqu'à ce que vous relâchiez l'image source.

14
répondu Dondragmer 2012-04-25 02:46:32

a pris quelques jours, mais j'ai finalement compris grâce à la réponse @Dondragmer posté. Mais j'ai pensé poster ma solution complète.

donc j'ai dû écrire une méthode pour auto-tourner intelligemment mes images. L'inconvénient est que je dois appeler cette méthode partout dans mon code et c'est une sorte de processeur intensif, surtout quand on travaille sur des appareils mobiles, mais le côté positif est que je peux prendre des images, copier des images, coller des images, et sauver des images et ils tournent tous correctement. Voici le code que j'ai fini par utiliser (la méthode n'est pas 100% complète encore, encore besoin d'éditer les fuites de mémoire et ce qui ne l'est pas).

j'ai fini par apprendre que la toute première fois qu'une image a été insérée dans mon application (que ce soit en raison d'un utilisateur pressant" prendre l'image"," coller l'image", ou" sélectionner l'image", pour une raison quelconque, il insère très bien sans rotation automatique. À ce moment, j'ai stocké quelque soit la valeur de rotation dans une variable globale appelée imageOrientationWhenAddedToScreen . Cela a rendu ma vie plus facile parce que quand il est venu le temps de manipuler l'image et sauver l'image hors du programme, j'ai simplement vérifié cette variable globale mise en cache et déterminé si j'avais besoin de tourner correctement l'image.

    - (UIImage*) rotateImageAppropriately:(UIImage*) imageToRotate {
    //This method will properly rotate our image, we need to make sure that
    //We call this method everywhere pretty much...

    CGImageRef imageRef = [imageToRotate CGImage];
    UIImage* properlyRotatedImage;

    if (imageOrientationWhenAddedToScreen == 0) {
       //Don't rotate the image
        properlyRotatedImage = imageToRotate;

    } else if (imageOrientationWhenAddedToScreen == 3) {

        //We need to rotate the image back to a 3
        properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:3];

    } else if (imageOrientationWhenAddedToScreen == 1) {

        //We need to rotate the image back to a 1
        properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:1];        

    }

    return properlyRotatedImage;

}

Je ne suis toujours pas sûr à 100% pourquoi Apple a ce comportement bizarre de rotation d'image (essayer ceci... Prenez votre téléphone et tournez-le à l'envers et prenez une photo, vous remarquerez que la photo finale tourne à droite vers le haut - peut-être ceci pourquoi Apple a ce type de fonctionnalité?).

je sais que j'ai passé beaucoup de temps à comprendre cela, alors j'espère que cela aidera les autres!

13
répondu Boeckm 2012-07-19 16:07:59

ce comportement de "rotation bizarre" n'est vraiment pas si bizarre que ça. C'est intelligent, et par Intelligent je veux dire efficace de mémoire. Lorsque vous faites tourner un appareil iOS, le matériel de l'appareil tourne avec lui. Lorsque vous prenez une image que l'image sera capturée cependant la caméra est orientée. L'UIImage est capable d'utiliser ces données d'image brutes sans les copier en gardant simplement la trace de l'orientation dans laquelle elles devraient être. Lorsque vous utilisez UIImagePNGRepresentation() vous perdez ces données d'orientation et d'obtenir un PNG de l'image sous-jacente telle qu'elle a été prise par la caméra. Pour corriger cela au lieu de tourner, vous pouvez dire à l'image originale de se dessiner dans un nouveau contexte et d'obtenir le correctement orienté UIImage à partir de ce contexte.

UIImage *image = ...;

//Have the image draw itself in the correct orientation if necessary
if(!(image.imageOrientation == UIImageOrientationUp ||
    image.imageOrientation == UIImageOrientationUpMirrored))
{
    CGSize imgsize = image.size;
    UIGraphicsBeginImageContext(imgsize);
    [image drawInRect:CGRectMake(0.0, 0.0, imgsize.width, imgsize.height)];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

NSData *png = UIImagePNGRepresentation(image);
13
répondu Joe 2014-02-05 19:35:13

Voici une autre façon d'y parvenir:

@IBAction func rightRotateAction(sender: AnyObject) {

    let imgToRotate = CIImage(CGImage: sourceImageView.image?.CGImage)
    let transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
    let rotatedImage = imgToRotate.imageByApplyingTransform(transform)
    let extent = rotatedImage.extent()
    let contex = CIContext(options: [kCIContextUseSoftwareRenderer: false])
    let cgImage = contex.createCGImage(rotatedImage, fromRect: extent)
    adjustedImage = UIImage(CGImage: cgImage)!
    UIView.transitionWithView(sourceImageView, duration: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
            self.sourceImageView.image = self.adjustedImage
        }, completion: nil)
}
0
répondu Dharmesh Kheni 2015-08-13 10:38:32

vous pouvez utiliser L'image I/O pour sauvegarder L'image PNG dans le fichier(ou NSMutableData ) en ce qui concerne l'orientation de l'image. Dans l'exemple ci-dessous, je sauvegarde L'image PNG dans un fichier path .

- (BOOL)savePngFile:(UIImage *)image toPath:(NSString *)path {
    NSData *data = UIImagePNGRepresentation(image);
    int exifOrientation = [UIImage cc_iOSOrientationToExifOrientation:image.imageOrientation];
    NSDictionary *metadata = @{(__bridge id)kCGImagePropertyOrientation:@(exifOrientation)};
    NSURL *url = [NSURL fileURLWithPath:path];
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    if (!source) {
        return NO;
    }
    CFStringRef UTI = CGImageSourceGetType(source);
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, UTI, 1, NULL);
    if (!destination) {
        CFRelease(source);
        return NO;
    }
    CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metadata);
    BOOL success = CGImageDestinationFinalize(destination);
    CFRelease(destination);
    CFRelease(source);
    return success;
}

cc_iOSOrientationToExifOrientation: est une méthode de la catégorie UIImage .

+ (int)cc_iOSOrientationToExifOrientation:(UIImageOrientation)iOSOrientation {
    int exifOrientation = -1;
    switch (iOSOrientation) {
        case UIImageOrientationUp:
            exifOrientation = 1;
            break;

        case UIImageOrientationDown:
            exifOrientation = 3;
            break;

        case UIImageOrientationLeft:
            exifOrientation = 8;
            break;

        case UIImageOrientationRight:
            exifOrientation = 6;
            break;

        case UIImageOrientationUpMirrored:
            exifOrientation = 2;
            break;

        case UIImageOrientationDownMirrored:
            exifOrientation = 4;
            break;

        case UIImageOrientationLeftMirrored:
            exifOrientation = 5;
            break;

        case UIImageOrientationRightMirrored:
            exifOrientation = 7;
            break;

        default:
            exifOrientation = -1;
    }
    return exifOrientation;
}

vous pouvez alternativement enregistrer l'image à NSData en utilisant CGImageDestinationCreateWithData et passer NSMutableData au lieu de NSURL dans CGImageDestinationCreateWithURL .

0
répondu KudoCC 2016-05-17 10:30:12