web-dev-qa-db-de.com

iOS: Das Bild wird nach dem Speichern als PNG-Repräsentationsdaten um 90 Grad gedreht

Ich habe genug recherchiert, um dieses Problem zu beheben, konnte es aber nicht beheben. Nachdem ich ein Bild von der Kamera aufgenommen habe, solange ich ein Bild als UIImage gespeichert habe, ist es in Ordnung, aber sobald ich dieses Bild als PNG-Darstellung gespeichert habe, wird es um 90 Grad gedreht.

Folgendes ist mein Code und alles, was ich versucht habe:

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

Hier sind fixOrientation- und scaleAndRotateImage-Funktionen aus hier und hier übernommen. Sie funktionieren gut und drehen das Bild, wenn ich sie auf UIImage anwende. Es funktioniert jedoch nicht, wenn ich Bilder als PNG-Darstellung speichere und sie anwende.

Verweisen Sie bitte das folgende Bild, nachdem Sie die obigen Funktionen ausgeführt haben:

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

35
applefreak

Ab iOS 4.0, wenn die Kamera ein Foto aufnimmt, wird sie vor dem Speichern nicht gedreht 

setzt einfach ein Rotationsflag in den EXIF-Daten des JPEG. Wenn Sie einen UIImage als JPEG speichern, dann 

setzt das Rotationsflag.PNGs unterstützen kein Rotationsflag, wenn Sie also einen UIImage als speichern 

PNG, es wird falsch gedreht und es ist kein Flag gesetzt, um es zu beheben. Also, wenn Sie PNG wollen 

bilder müssen Sie selbst drehen, dazu das Kontrollkästchen link .

63
Mudit Bajpai

Swift 3.1-Version der von Rao geposteten UIImage-Erweiterung:

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

Verwendungszweck:

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

Für Swift 2.1

Fügen Sie Folgendes als UIImage-Erweiterung hinzu:

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

Verwendungsbeispiel:

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

Ich habe die folgenden Tipps als äußerst nützlich empfunden:

1. natürlicher Ertrag ist Landschaft

2.. Breite /. Höhe sind von .imageOrientation betroffen

3 Verwenden Sie statt der Breite die kurze Dimension


(1) Die "natürliche" Ausgabe der Kamera für Standbilder IS LANDSCAPE.

das ist nicht intuitiv. UIImagePickerController usw. bietet nur das Portrait-Format. Sie erhalten jedoch UIImageOrientationRight als "normale" Ausrichtung, wenn Sie die "normale" Portrait-Kamera verwenden

(Die Art, wie ich mich daran erinnere - die natürliche Ausgabe von Video ist (natürlich) Landschaft; also sind Standbilder die gleichen - obwohl das iPhone nur mit Porträt zu tun hat.)


(2). Breite und. Höhe sind in der Tat von der .ImageOrientation betroffen !!!!!!!!!

Stellen Sie sicher, dass Sie dies tun, und versuchen Sie es auf beide Arten auf Ihrem iPhone.

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

sie werden sehen, dass die Höhe und Breite vertauscht werden, "obwohl" die echten Pixel im Querformat sind.


(3) einfach die "kurze Dimension" anstelle von. Width verwendet, kann oft viele Probleme lösen

Ich fand das unglaublich hilfreich. Sagen Sie, Sie möchten vielleicht das oberste Quadrat des Bildes:

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

das funktioniert eigentlich nicht, du bekommst ein zerquetschtes Bild, wenn die Kamera ("wirklich") im Querformat gehalten wird.

wenn Sie dies jedoch ganz einfach tun

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

dann "alles ist fixiert" und man muss sich eigentlich "braucht sich nicht zu sorgen" das Orientierungsflag. Auch Punkt (3) ist kein Allheilmittel, löst aber sehr oft alle Probleme.

Hoffe, es hilft jemandem, Zeit zu sparen.

6
Fattie

Ich habe diesen Code hier gefunden, der ihn für mich behoben hat. Für meine App habe ich ein Foto aufgenommen und gespeichert, und jedes Mal, wenn ich es lade, hätte es die nervige Rotation angehängt (ich habe nachgeschlagen und es hat anscheinend etwas mit EXIF ​​zu tun und der Art und Weise, wie das iPhone Bilder nimmt und speichert). Dieser Code hat es für mich behoben. Ich muss sagen, es war ursprünglich eine Ergänzung zu einer Klasse/einer Erweiterung/Kategorie (Sie können das Original über den Link finden. Ich habe es wie folgt als einfache Methode verwendet, da ich nicht wirklich ein Ganzes machen wollte Klasse oder Kategorie für genau das. Ich habe nur Portrait verwendet, aber ich denke, der Code funktioniert für jede Orientierung. Ich bin mir jedoch nicht sicher

Rant vorbei, hier ist der 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;
}

Ich bin nicht sicher, wie nützlich das für Sie sein wird, aber ich hoffe, es hat geholfen :) 

2
Septronic

Versuchen Sie es mit Sie können verwenden 

NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0);

anstatt

NSData *somenewImageData = UIImagePNGRepresentation(newimg);
2
vijay

Versuchen Sie den folgenden Code

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

Und 

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

Ich habe von folgendem Link aus referenziert, suche mehr detail

Freundliche Grüße :-)

1
NIKHIL

Versuchen Sie diesen Code:

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