L'orientamento dell'immagine iOS ha un comportamento strano


94

Nelle ultime settimane ho lavorato con immagini in Object-C e ho notato molti comportamenti strani. Innanzitutto, come molte altre persone, ho riscontrato questo problema in cui le immagini scattate con la fotocamera (o scattate con la fotocamera di qualcun altro e l'MMS per me) vengono ruotate di 90 gradi. Non ero sicuro del motivo per cui nel mondo stesse accadendo (da qui la mia domanda ) ma sono stato in grado di trovare un lavoro economico in giro.

La mia domanda questa volta è: perché sta accadendo ? Perché Apple ruota le immagini? Quando scatto una foto con la fotocamera rivolta verso l'alto, a meno che non esegua il codice sopra menzionato, quando salvo la foto viene salvata ruotata. Ora, la mia soluzione alternativa andava bene fino a pochi giorni fa.

La mia applicazione modifica i singoli pixel di un'immagine, in particolare il canale alfa di un PNG (quindi qualsiasi conversione JPEG viene buttata fuori dalla finestra per il mio scenario). Qualche giorno fa ho notato che anche se l'immagine viene visualizzata correttamente nella mia app grazie al mio codice di soluzione alternativa, quando il mio algoritmo modifica i singoli pixel dell'immagine, pensa che l'immagine sia ruotata. Quindi, invece di modificare i pixel nella parte superiore dell'immagine, modifica i pixel sul lato dell'immagine (perché pensa che dovrebbe essere ruotato)! Non riesco a capire come ruotare l'immagine in memoria - idealmente preferirei semplicemente cancellare quella imageOrientationbandiera tutta insieme.

Ecco qualcos'altro che mi ha sconcertato ... Quando scatto la foto, imageOrientationè impostato su 3. Il mio codice di soluzione alternativa è abbastanza intelligente da rendersene conto e capovolgerlo in modo che l'utente non se ne accorga. Inoltre, il mio codice per salvare l'immagine nella libreria lo realizza, la capovolge, quindi la salva in modo che appaia correttamente nel rullino fotografico.

Quel codice sembra così:

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

Quando carico questa immagine appena salvata nella mia app, imageOrientationè 0, esattamente quello che voglio vedere e la mia soluzione alternativa di rotazione non deve nemmeno essere eseguita (nota: quando si caricano immagini da Internet rispetto alle immagini scattate con una fotocamera , imageOrientationè sempre 0, risultando in un comportamento perfetto). Per qualche motivo, il mio codice di salvataggio sembra cancellare questo imageOrientationflag. Speravo di rubare quel codice e usarlo per cancellare il mio ImageOrientation non appena l'utente scatta una foto e l'ha aggiunta all'app, ma non sembra funzionare. Fa UIImageWriteToSavedPhotosAlbumqualcosa di speciale con imageOrientation?

La soluzione migliore per questo problema sarebbe semplicemente spazzare via imageOrientationnon appena l'utente ha finito di scattare un'immagine. Presumo che Apple abbia eseguito il comportamento di rotazione per un motivo, giusto? Alcune persone hanno suggerito che si tratta di un difetto di Apple.

(... se non ti sei ancora perso ... Nota2: quando scatto una foto orizzontale, sembra che tutto funzioni perfettamente, proprio come le foto prese da Internet)

MODIFICARE:

Ecco come appaiono effettivamente alcune delle immagini e degli scenari. Sulla base dei commenti finora, sembra che questo strano comportamento sia più di un semplice comportamento di iPhone, che penso sia buono.

Questa è una foto della foto che ho scattato con il mio telefono (nota l'orientamento corretto), appare esattamente come sul mio telefono quando ho scattato la foto:

Foto reale scattata su iPhone

Ecco come appare l'immagine in Gmail dopo che l'ho inviata a me stesso (sembra che Gmail la gestisca correttamente):

Foto come appare in Gmail

Ecco come appare l'immagine come miniatura in Windows (non sembra che sia gestita correttamente):

Miniatura di Windows

Ed ecco come appare l'immagine reale quando viene aperta con Windows Photo Viewer (ancora non gestita correttamente):

Versione del visualizzatore di foto di Windows

Dopo tutti i commenti su questa domanda, ecco cosa sto pensando ... L'iPhone scatta un'immagine e dice "per visualizzarla correttamente, deve essere ruotata di 90 gradi". Questa informazione sarebbe nei dati EXIF. (Perché deve essere ruotato di 90 gradi, invece di essere impostato automaticamente in verticale, non lo so). Da qui, Gmail è abbastanza intelligente da leggere e analizzare i dati EXIF ​​e visualizzarli correttamente. Windows, tuttavia, non è abbastanza intelligente da leggere i dati EXIF ​​e quindi visualizza l'immagine in modo improprio . Le mie ipotesi sono corrette?


Interessante ... se è vero, perché le immagini scattate sono impostate ad angolo retto? So che questo non è un difetto dell'iPhone, perché ho notato un comportamento simile quando un amico (con un BlackBerry) scatta un'immagine e me la invia con un MMS.
Boeckm

Guarda la tua fotocamera scrive metadati per ruotarla di 90 gradi, alcuni sistemi operativi leggono che i metadati e il resto no.
HarshIT

Lettura abbastanza buona (vedi la risposta di @ Hadley sotto - era in un commento). Quindi la mia app deve chiaramente essere abbastanza intelligente da gestire immagini che contengono dati EXIF, così come immagini che non li contengono ... Continuo a non capire perché quando scatto una foto con il lato destro in alto, il flag di orientamento dice che dovrebbe essere ruotato di 90 gradi?
Boeckm

Hai impostato la modalità foto su Ritratto e non stai ruotando la fotocamera ad angolo retto o la modalità Paesaggio è impostata e la fotocamera ha catturato l'immagine in posizione ad angolo retto, il sensore imposterà automaticamente l'orientamento su quello corretto. Check it out
HarshIT

1
La soluzione è molto probabilmente che la tua app deve leggere i metadati e ruotare l'immagine e / o modificare i metadati secondo i requisiti.
HarshIT

Risposte:


50

Ci ho fatto ricerca e sviluppo e ho scoperto che ogni file immagine ha proprietà di metadati. Se i metadati specificano l'orientamento dell'immagine che viene generalmente ignorato da altri sistemi operativi tranne Mac. La maggior parte delle immagini scattate ha la proprietà dei metadati impostata sull'angolo retto. Quindi il Mac mostra il modo ruotato di 90 gradi. Puoi vedere la stessa immagine in modo corretto nel sistema operativo Windows.

Per maggiori dettagli leggi questa risposta http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm

prova a leggere l'exif della tua immagine qui http://www.exifviewer.org/ , o http://regex.info/exif.cgi , o http://www.addictivetips.com/internet-tips/view-complete-exif -metadati-informazioni-di-qualsiasi-immagine-jpeg-online /


1
WOW! Non avevo idea che ci fossero QUESTE informazioni nei dati EXIF! regex.info/exif.cgi è un sito incredibile! Stasera giocherò sicuramente con le immagini su questo sito. Dovrò testare ogni scenario, le immagini riprendono direttamente, le immagini prese da Internet, le immagini scattate ruotate, ecc. Grazie mille!
Boeckm

Il primo collegamento exif ora è interrotto e il secondo è stato aggiornato a exif.regex.info/exif.cgi Ho provato a modificare la risposta ma @ cj-dennis l'ha rifiutata per qualche motivo.
Ryan

55

Ho avuto lo stesso problema quando ho ricevuto l'immagine da Camera, ho inserito il seguente codice per risolverlo .. Aggiunto il metodo scaleAndRotateImage da qui

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

3
Che aspetto ha il codice scaleAndRotateImage? Dopo aver fatto un google, è lo stesso di quello qui? discussioni.apple.com/thread/1537011?start=0&tstart=0
Boeckm

2
WOW ... Haha! Ha funzionato molto bene! Ho usato il codice nel mio commento sopra. Ho due fantastiche risposte alla mia domanda! Penso che questo significhi che ho fatto una domanda troppo grande ... Grazie mille. Avrò alcuni test approfonditi da fare, ma finora il problema di orientamento funziona benissimo con le foto scattate in verticale e in orizzontale.
Boeckm

3
Penso che manchi una parte del tuo metodo, ma quella e il collegamento erano ancora sufficienti per me per elaborare il resto e finalmente far funzionare correttamente la mia vista di ritaglio dell'immagine, quindi grazie :)
Vic Smith

Sono contento che abbia aiutato .. :)
Dilip Rajkumar

questo blocco di codice preserva l'aspetto dell'immagine originale ma cambia l'orientamento in alto?
Junchao Gu

18

Copia / incolla veloce Traduzione rapida dell'eccellente risposta di Dilip .

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

1
Grazie, ma cos'è "let ratio = width / height;" usando per? Non riesco a vedere alcun luogo che utilizzi il rapporto in quel {}
Pengzhi Zhou

18

La mia domanda questa volta è: perché sta accadendo? Perché Apple ruota le immagini?

La risposta a questa domanda è molto semplice. Apple NON sta ruotando l'immagine. Ecco dove sta la confusione.

La fotocamera CCD non ruota, quindi scatta sempre la foto in modalità orizzontale.

Apple ha fatto una cosa molto intelligente - invece di spendere tutto il tempo per ruotare l'immagine - mescolando megabyte di dati in giro - basta etichettarla con COME è stata scattata la foto.

OpenGL esegue traduzioni molto facilmente, quindi i DATI non vengono mai mescolati, solo COME SONO DISEGNATI.

Da qui i metadati di orientamento.

Questo diventa un problema se vuoi ritagliare, ridimensionare ecc. - Ma una volta che sai cosa sta succedendo, devi solo definire la tua matrice e tutto funziona.


1
Grazie per questa spiegazione. Il buon senso una volta che ci pensi, ma nessun altro risultato su Google lo ha spiegato.
Dakine83

16

Versione Swift 4 con controlli di sicurezza della risposta di 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
}

Puoi anche fare a (bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)meno di creare variabili come archiviazione.
Almas Sapargali

A volte ho avuto il problema che una linea bianca apparisse nella parte inferiore dell'immagine dopo averla ridimensionata. Questo perché CGFloat sembra non essere abbastanza preciso. Ho risolto il problema con bounds.size.height.round()ebounds.size.width.round()
ndreisg

13

Qualsiasi immagine generata da iPhone / iPad viene salvata come Orizzontale a sinistra con il tag di orientamento EXIF ​​(Exif.Image.Orientation) che specifica l'orientamento effettivo.

Ha i seguenti valori: 1: Orizzontale a sinistra 6: Verticale normale 3: Orizzontale a destra 4: Verticale capovolto

In IOS, le informazioni EXIF ​​vengono lette correttamente e le immagini vengono visualizzate nello stesso modo in cui sono state scattate. Ma in Windows, le informazioni EXIF ​​NON vengono utilizzate.

Se apri una di queste immagini in GIMP, dirà che l'immagine ha informazioni sulla rotazione.


8

Per chiunque altro usi Xamarin, ecco una traduzione in C # dell'ottima risposta di Dilip e un ringraziamento a Thattyson per la traduzione Swift .

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

Questo ha aiutato a risolvere il mio problema dopo aver trascorso molte ore a giocare con questo! Incredibile che Xamarin non abbia alcun supporto integrato per questo dato che ora è un prodotto Microsoft.
Sami.C

4

Mi sono imbattuto in questa domanda perché stavo avendo un problema simile, ma usando Swift. Volevo solo collegarmi alla risposta che ha funzionato per me per qualsiasi altro sviluppatore Swift: https://stackoverflow.com/a/26676578/3904581

Ecco uno snippet Swift che risolve il problema in modo efficiente:

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

Super semplice. Una riga di codice. Problema risolto.


Questo non ha funzionato per me, ho usato questa soluzione: stackoverflow.com/a/27775741/945247
Leon


0

Refactored rapido per Swift 3 (qualcuno può testarlo e confermare che tutto funzioni correttamente?):

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

0

Ecco la versione Swift3 della fantastica risposta di Dilip

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

-3

Prova a cambiare il formato dell'immagine in .jpeg. Questo ha funzionato per me

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.