iOS-Bildorientierung hat ein seltsames Verhalten

94

In den letzten Wochen habe ich mit Bildern in Ziel-C gearbeitet und viele seltsame Verhaltensweisen bemerkt. Erstens hatte ich, wie viele andere Menschen, dieses Problem, bei dem Bilder, die mit der Kamera (oder mit der Kamera eines anderen und MMS für mich) aufgenommen wurden, um 90 Grad gedreht wurden. Ich war mir nicht sicher, warum in aller Welt dies geschah (daher meine Frage ), aber ich konnte mir eine billige Lösung ausdenken.

Meine Frage ist diesmal, warum das passiert . Warum dreht Apple Bilder? Wenn ich ein Foto mit der Kamera mit der rechten Seite nach oben aufnehme, wird das Foto beim Speichern gedreht, sofern ich meinen oben genannten Code nicht ausführe. Jetzt war meine Problemumgehung bis vor ein paar Tagen in Ordnung.

Meine Anwendung ändert einzelne Pixel eines Bildes, insbesondere den Alphakanal eines PNG (sodass jede JPEG-Konvertierung für mein Szenario aus dem Fenster geworfen wird). Vor ein paar Tagen habe ich festgestellt, dass das Bild, obwohl es dank meines Workaround-Codes in meiner App korrekt angezeigt wird, beim Ändern der einzelnen Pixel des Bildes denkt, dass das Bild gedreht wird. Anstatt also die Pixel oben im Bild zu ändern, werden die Pixel an der Seite des Bildes geändert (weil es der Meinung ist, dass es gedreht werden sollte)! Ich kann nicht herausfinden, wie das Bild im Speicher gedreht werden soll - idealerweise würde ich es vorziehen, diese imageOrientationFlagge alle zusammen wegzuwischen .

Hier ist noch etwas, das mich ebenfalls verblüfft hat ... Wenn ich das Foto mache, imageOrientationist das auf 3 gesetzt. Mein Workaround-Code ist klug genug, um dies zu erkennen und umzudrehen, damit der Benutzer es nie bemerkt. Zusätzlich mein Code , um das Bild in die Bibliothek speichern realisiert dies, dreht sie, dann speichert sie , damit es richtig in der Kamera Rolle erscheint.

Dieser Code sieht so aus:

NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap 
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];   
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);

Wenn ich dieses neu gespeicherte Bild in meine App lade, imageOrientationist dies 0 - genau das, was ich sehen möchte, und meine Rotationsumgehung muss nicht einmal ausgeführt werden (Hinweis: Beim Laden von Bildern aus dem Internet im Gegensatz zu Bildern, die mit einer Kamera aufgenommen wurden , das imageOrientationist immer 0, was zu einem perfekten Verhalten). Aus irgendeinem Grund scheint mein Speichercode diese imageOrientationFlagge zu löschen . Ich hatte gehofft, diesen Code einfach zu stehlen und damit meine imageOrientation zu löschen, sobald der Benutzer ein Foto macht und es der App hinzufügt, aber es scheint nicht zu funktionieren. Macht UIImageWriteToSavedPhotosAlbumetwas Besonderes mit imageOrientation?

Die beste Lösung für dieses Problem wäre, einfach wegzublasen, imageOrientationsobald der Benutzer ein Bild aufgenommen hat. Ich gehe davon aus, dass Apple das Rotationsverhalten aus einem bestimmten Grund durchgeführt hat, oder? Einige Leute schlugen vor, dass dies ein Apple-Defekt ist.

(... wenn Sie noch nicht verloren sind ... Hinweis 2: Wenn ich ein horizontales Foto mache, scheint alles perfekt zu funktionieren, genau wie Fotos aus dem Internet.)

BEARBEITEN:

Hier sehen Sie, wie einige der Bilder und Szenarien tatsächlich aussehen. Basierend auf den bisherigen Kommentaren sieht es so aus, als ob dieses seltsame Verhalten mehr als nur ein iPhone-Verhalten ist, was ich für gut halte.

Dies ist ein Bild des Fotos, das ich mit meinem Telefon aufgenommen habe (beachten Sie die richtige Ausrichtung). Es wird genauso angezeigt wie auf meinem Telefon, als ich das Foto aufgenommen habe:

Tatsächliches Foto auf dem iPhone aufgenommen

So sieht das Bild in Google Mail aus, nachdem ich es mir per E-Mail gesendet habe (es sieht so aus, als würde Google Mail es richtig handhaben):

Foto wie es in Google Mail angezeigt wird

So sieht das Bild als Miniaturansicht in Windows aus (sieht nicht so aus, als würde es richtig behandelt):

Windows-Miniaturansicht

Und so sieht das eigentliche Bild aus, wenn es mit Windows Photo Viewer geöffnet wird (immer noch nicht richtig gehandhabt):

Windows Photo Viewer-Version

Nach all den Kommentaren zu dieser Frage denke ich Folgendes: Das iPhone nimmt ein Bild auf und sagt: "Um dies richtig anzuzeigen, muss es um 90 Grad gedreht werden." Diese Informationen wären in den EXIF-Daten enthalten. (Warum es um 90 Grad gedreht werden muss, anstatt standardmäßig gerade vertikal zu sein, weiß ich nicht). Von hier aus ist Google Mail intelligent genug, um diese EXIF-Daten zu lesen, zu analysieren und ordnungsgemäß anzuzeigen. Windows ist jedoch nicht intelligent genug, um die EXIF-Daten zu lesen, und zeigt das Bild daher nicht ordnungsgemäß an . Sind meine Annahmen richtig?

Boeckm
quelle
Interessant ... wenn das stimmt, warum werden die aufgenommenen Bilder auf den richtigen Winkel eingestellt? Ich weiß, dass dies kein iPhone-Defekt ist, da ich ein ähnliches Verhalten festgestellt habe, wenn ein Freund (mit einem BlackBerry) ein Bild aufnimmt und MMS es mir vorlegt.
Boeckm
Sehen Sie, wie Ihre Kamera Metadaten schreibt, um sie um 90 Grad zu drehen. Einige Betriebssysteme lesen, dass Metadaten und Rest dies nicht tun.
HarshIT
Ziemlich gut gelesen (siehe @ Hadleys Antwort unten - war früher in einem Kommentar). Meine App muss also eindeutig intelligent genug sein, um Bilder zu verarbeiten, die EXIF-Daten enthalten, sowie Bilder, die diese nicht enthalten. Ich verstehe immer noch nicht, warum, wenn ich ein Foto mit der rechten Seite nach oben mache, die Orientierungsflagge angezeigt wird sagt, es sollte um 90 Grad gedreht werden?
Boeckm
Sie stellen Ihren Fotomodus auf Hochformat ein und drehen Ihre Kamera nicht in den rechten Winkel oder der Querformatmodus ist eingestellt und die Kamera hat das Bild in einer rechtwinkligen Position aufgenommen. Der Sensor stellt die Ausrichtung automatisch auf die richtige ein.
Probieren
1
Die Lösung besteht höchstwahrscheinlich darin, dass Ihre App die Metadaten lesen und das Bild drehen und / oder die Metadaten gemäß den Anforderungen ändern muss.
HarshIT

Antworten:

50

Ich habe F & E durchgeführt und festgestellt, dass jede Bilddatei Metadateneigenschaften hat. Wenn die Metadaten die Ausrichtung des Bildes angeben, die von anderen Betriebssystemen als Mac im Allgemeinen ignoriert wird. Bei den meisten aufgenommenen Bildern ist die Metadateneigenschaft auf den rechten Winkel eingestellt. Mac zeigt es also um 90 Grad gedreht. Sie können dasselbe Bild unter Windows ordnungsgemäß anzeigen.

Weitere Informationen finden Sie in dieser Antwort unter http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm

Lesen Sie das Exif Ihres Bildes hier http://www.exifviewer.org/ oder http://regex.info/exif.cgi oder http://www.addictivetips.com/internet-tips/view-complete-exif -metadata-information-of-any-jpeg-image-online /

HarshIT
quelle
1
BEEINDRUCKEND! Ich hatte keine Ahnung, dass es so viele Informationen in EXIF-Daten gibt! regex.info/exif.cgi ist eine unglaubliche Seite! Ich werde heute Abend auf dieser Seite sicherlich mit Bildern herumspielen. Ich muss jedes Szenario testen, Bilder werden direkt aufgenommen, Bilder aus dem Internet aufgenommen, Bilder gedreht gedreht usw. Vielen Dank!
Boeckm
Der erste Exif-Link ist jetzt defekt und der zweite wurde auf exif.regex.info/exif.cgi aktualisiert. Ich habe versucht, die Antwort zu bearbeiten, aber @ cj-dennis hat sie aus irgendeinem Grund abgelehnt.
Ryan
55

Ich hatte das gleiche Problem, als ich das Bild von der Kamera erhielt. Ich habe den folgenden Code eingegeben, um es zu beheben. Die Methode scaleAndRotateImage wurde von hier hinzugefügt

- (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo {
            // Images from the camera are always in landscape, so rotate
                    UIImage *image = [self scaleAndRotateImage: [imageInfo objectForKey:UIImagePickerControllerOriginalImage]];
    //then save the image to photo gallery or wherever  
        }


- (UIImage *)scaleAndRotateImage:(UIImage *) image {
    int kMaxResolution = 320;

    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;
}
Dilip Rajkumar
quelle
3
Wie sieht Ihr scaleAndRotateImage-Code aus? Ist es nach dem Google das gleiche wie hier? diskussionen.apple.com/thread/1537011?start=0&tstart=0
Boeckm
2
WOW ... Haha! Das hat sehr gut funktioniert! Ich habe den Code in meinem Kommentar oben verwendet. Ich habe zwei tolle Antworten auf meine Frage bekommen! Ich denke, das bedeutet, dass ich eine zu große Frage gestellt habe ... Vielen Dank. Ich werde einige eingehende Tests durchführen müssen, aber bisher funktioniert das Orientierungsproblem bei vertikal und horizontal aufgenommenen Fotos hervorragend.
Boeckm
3
Ich denke, es fehlt ein Teil Ihrer Methode, aber das und der Link waren immer noch genug für mich, um den Rest zu klären und endlich meine Bildbeschneidungsansicht richtig zum Laufen zu bringen, also danke :)
Vic Smith
Ich bin froh, dass es geholfen hat .. :)
Dilip Rajkumar
Bewahrt dieser Codeblock das Aussehen des Originalbilds, ändert jedoch die Ausrichtung, um nach oben zu gelangen?
Junchao Gu
18

Schnelles Kopieren / Einfügen Schnelle Übersetzung von Dilips hervorragender Antwort .

import Darwin

class func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {

    let imgRef = imageSource.CGImage;

    let width = CGFloat(CGImageGetWidth(imgRef));
    let height = CGFloat(CGImageGetHeight(imgRef));

    var bounds = CGRectMake(0, 0, width, height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransformIdentity
    let orient = imageSource.imageOrientation
    let imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef)))


    switch(imageSource.imageOrientation) {
    case .Up :
        transform = CGAffineTransformIdentity

    case .UpMirrored :
        transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);

    case .Down :
        transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI));

    case .DownMirrored :
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
        transform = CGAffineTransformScale(transform, 1.0, -1.0);

    case .Left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .LeftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .Right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    case .RightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeScale(-1.0, 1.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    default : ()
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .Right || orient == .Left {
        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);

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}
thattyson
quelle
1
Danke, aber was ist "let ratio = width / height;" mit für? Ich kann keinen Ort mit Verhältnis in diesem {}
Pengzhi Zhou
17

Meine Frage ist diesmal, warum das passiert. Warum dreht Apple Bilder?

Die Antwort darauf ist sehr einfach. Apple dreht das Bild NICHT. Hier liegt die Verwirrung.

Die CCD-Kamera dreht sich nicht und nimmt das Foto daher immer im Querformat auf.

Apple hat eine sehr clevere Sache gemacht - anstatt die ganze Zeit damit zu verbringen, das Bild zu drehen - Megabyte an Daten zu mischen - kennzeichnen Sie es einfach mit WIE das Bild aufgenommen wurde.

OpenGL macht Übersetzungen sehr einfach - so dass die DATEN nie gemischt werden - nur wie sie gezeichnet werden.

Daher die Orientierungs-Metadaten.

Dies wird zu einem Problem, wenn Sie zuschneiden, die Größe ändern usw. möchten. Sobald Sie jedoch wissen, was passiert, definieren Sie einfach Ihre Matrix und alles funktioniert.

Roy
quelle
1
Vielen Dank für diese Erklärung. Der gesunde Menschenverstand, sobald Sie darüber nachdenken, aber kein anderes gegoogeltes Ergebnis erklärte es.
Dakine83
16

Swift 4-Version mit Sicherheitsüberprüfungen der Antwort von Dilip .

public static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? {

    guard let imgRef = imageSource.cgImage else {
        return nil
    }

    let width = CGFloat(imgRef.width)
    let height = CGFloat(imgRef.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))

    switch(imageSource.imageOrientation) {
    case .up:
        transform = .identity
    case .upMirrored:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: 0)
            .scaledBy(x: -1.0, y: 1.0)
    case .down:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: imageSize.height)
            .rotated(by: CGFloat.pi)
    case .downMirrored:
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.height)
            .scaledBy(x: 1.0, y: -1.0)
    case .left:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.width)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .leftMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: imageSize.width)
            .scaledBy(x: -1.0, y: 1.0)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: 0)
            .rotated(by: CGFloat.pi / 2.0)
    case .rightMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(scaleX: -1.0, y: 1.0)
            .rotated(by: CGFloat.pi / 2.0)
    }

    UIGraphicsBeginImageContext(bounds.size)
    if let context = UIGraphicsGetCurrentContext() {
        if orient == .right || orient == .left {
            context.scaleBy(x: -scaleRatio, y: scaleRatio)
            context.translateBy(x: -height, y: 0)
        } else {
            context.scaleBy(x: scaleRatio, y: -scaleRatio)
            context.translateBy(x: 0, y: -height)
        }

        context.concatenate(transform)
        context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))
    }

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy
}
Dávid Tímár
quelle
Sie können auch auf das (bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)Erstellen einer Variablen als Speicher verzichten.
Almas Sapargali
Ich hatte manchmal das Problem, dass am unteren Rand des Bildes nach dem Skalieren eine weiße Linie erschien. Dies liegt daran, dass CGFloat nicht präzise genug zu sein scheint. Ich habe dies mit bounds.size.height.round()undbounds.size.width.round()
ndreisg
13

Jedes vom iPhone / iPad erzeugte Bild wird als Querformat links mit dem Tag EXIF-Ausrichtung (Exif.Image.Orientation) gespeichert, das die tatsächliche Ausrichtung angibt.

Es hat die folgenden Werte: 1: Querformat links 6: Hochformat Normal 3: Querformat rechts 4: Hochformat verkehrt herum

In IOS werden die EXIF-Informationen ordnungsgemäß gelesen und die Bilder werden auf die gleiche Weise angezeigt, wie sie aufgenommen wurden. In Windows werden die EXIF-Informationen jedoch NICHT verwendet.

Wenn Sie eines dieser Bilder in GIMP öffnen, wird angezeigt, dass das Bild Rotationsinformationen enthält.

ATOzTOA
quelle
8

Für alle anderen, die Xamarin verwenden, ist hier eine C # -Übersetzung von Dilips großartiger Antwort und ein Dank an thattyson für die Swift-Übersetzung .

public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution) {

    var imgRef = imageSource.CGImage;

    var width = (nfloat)imgRef.Width;
    var height = (nfloat)imgRef.Height;

    var bounds = new CGRect(0, 0, width, height);

    nfloat scaleRatio = 1;

    if (width > maxResolution || height > maxResolution) 
    {
        scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height);
        bounds.Height = bounds.Height * scaleRatio;
        bounds.Width = bounds.Width * scaleRatio;
    }

    var transform = CGAffineTransform.MakeIdentity();
    var orient = imageSource.Orientation;
    var imageSize = new CGSize(imgRef.Width, imgRef.Height);
    nfloat storedHeight;

    switch(imageSource.Orientation) {
        case UIImageOrientation.Up:
            transform = CGAffineTransform.MakeIdentity();
            break;

        case UIImageOrientation.UpMirrored :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            break;

        case UIImageOrientation.Down :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI);
            break;

        case UIImageOrientation.DownMirrored :
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height);
            transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f);
            break;

        case UIImageOrientation.Left:
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.LeftMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.Right :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.RightMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeScale(-1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        default :
            break;
    }

    UIGraphics.BeginImageContext(bounds.Size);
    var context = UIGraphics.GetCurrentContext();

    if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) {
        context.ScaleCTM(-scaleRatio, scaleRatio);
        context.TranslateCTM(-height, 0);
    } else {
        context.ScaleCTM(scaleRatio, -scaleRatio);
        context.TranslateCTM(0, -height);
    }

    context.ConcatCTM(transform);
    context.DrawImage(new CGRect(0, 0, width, height), imgRef);

    var imageCopy = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();

    return imageCopy;
}
Tetowill
quelle
Dies hat mir geholfen, mein Problem zu lösen, nachdem ich viele Stunden damit verbracht habe! Es ist unglaublich, dass Xamarin keine eingebaute Unterstützung dafür hat, da es jetzt ein Microsoft-Produkt ist.
Sami.C
4

Ich bin auf diese Frage gestoßen, weil ich ein ähnliches Problem hatte, aber Swift benutzte. Ich wollte nur auf die Antwort verweisen, die für andere Swift-Entwickler bei mir funktioniert hat: https://stackoverflow.com/a/26676578/3904581

Hier ist ein Swift-Snippet, das das Problem effizient behebt:

let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!

Super einfach. Eine Codezeile. Problem gelöst.

Melly
quelle
Dies hat bei mir nicht funktioniert, ich habe diese Lösung verwendet: stackoverflow.com/a/27775741/945247
Leon
0

Ich weiß genau, was dein Problem ist. Sie verwenden UIImagePicker, was in jeder Hinsicht seltsam ist. Ich würde vorschlagen, dass Sie AVFoundation für die Kamera verwenden, was Flexibilität in Bezug auf Ausrichtung und Qualität bietet. Verwenden Sie AVCaptureSession. Den Code erhalten Sie hier. Wie speichere ich mit AVFoundation aufgenommene Fotos im Fotoalbum?

Gautam Jain
quelle
0

Schnell überarbeitet für Swift 3 (kann jemand es testen und bestätigen, dass alles in Ordnung ist?):

static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage

    let width = CGFloat(imgRef!.width)
    let height = CGFloat(imgRef!.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if width > maxResolution || height > maxResolution {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: imgRef!.width, height: imgRef!.height)

    switch imageSource.imageOrientation {
    case .up :
        transform = CGAffineTransform.identity

    case .upMirrored :
        transform = CGAffineTransform(translationX: imageSize.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)

    case .down :
        transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height)
        transform = transform.rotated(by: CGFloat.pi)

    case .downMirrored :
        transform = CGAffineTransform(translationX: 0, y: imageSize.height)
        transform = transform.scaledBy(x: 1, y: -1)

    case .left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: 0, y: imageSize.width)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .leftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width)
        transform = transform.scaledBy(x: -1, y: 1)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: 0)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    case .rightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(scaleX: -1, y: 1)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .right || orient == .left {

        context!.scaleBy(x: -scaleRatio, y: scaleRatio)
        context!.translateBy(x: -height, y: 0)
    } else {
        context!.scaleBy(x: scaleRatio, y: -scaleRatio)
        context!.translateBy(x: 0, y: -height)
    }

    context!.concatenate(transform)
    context!.draw(imgRef!, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy!
}
sabiland
quelle
0

Hier ist die Swift3-Version von Dilips großartiger Antwort

func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage!;

    let width = CGFloat(imgRef.width);
    let height = CGFloat(imgRef.height);

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {
        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: width, height: height)


    switch(imageSource.imageOrientation) {
        case .up :
            transform = CGAffineTransform.identity

        case .upMirrored :
            transform = CGAffineTransform(translationX: imageSize.width, y: 0.0);
            transform = transform.scaledBy(x: -1, y: 1);

        case .down :
            transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height);
            transform = transform.rotated(by: CGFloat(Double.pi));

        case .downMirrored :
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.height);
            transform = transform.scaledBy(x: 1, y: -1);

        case .left :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.width);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .leftMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width);
            transform = transform.scaledBy(x: -1, y: 1);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .right :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: 0.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);

        case .rightMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(scaleX: -1.0, y: 1.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()!

    if orient == .right || orient == .left {
        context.scaleBy(x: -scaleRatio, y: scaleRatio);
        context.translateBy(x: -height, y: 0);
    } else {
        context.scaleBy(x: scaleRatio, y: -scaleRatio);
        context.translateBy(x: 0, y: -height);
    }

    context.concatenate(transform);
    context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy!;
}
Sandip Mähne
quelle
-3

Versuchen Sie, das Bildformat in .jpeg zu ändern. Das hat bei mir funktioniert

Victor Rius
quelle