Orientasi Gambar iOS memiliki Perilaku Aneh

94

Selama beberapa minggu terakhir saya telah bekerja dengan gambar di obyektif-c dan memperhatikan banyak perilaku aneh. Pertama, seperti banyak orang lain, saya mengalami masalah ini di mana gambar yang diambil dengan kamera (atau diambil dengan kamera orang lain dan MMS ke saya) diputar 90 derajat. Saya tidak yakin mengapa di dunia ini terjadi (karena itu pertanyaan saya ) tetapi saya dapat menemukan solusi yang murah.

Pertanyaan saya kali ini adalah mengapa ini terjadi ? Mengapa Apple memutar gambar? Ketika saya mengambil foto dengan kamera saya menghadap ke atas, kecuali saya menjalankan kode saya yang disebutkan di atas, ketika saya menyimpan foto, foto itu akan disimpan diputar. Sekarang, solusi saya baik-baik saja hingga beberapa hari yang lalu.

Aplikasi saya memodifikasi piksel individu dari sebuah gambar, khususnya saluran alfa dari PNG (sehingga setiap konversi JPEG dibuang dari jendela untuk skenario saya). Beberapa hari yang lalu saya memperhatikan bahwa meskipun gambar ditampilkan dengan benar di aplikasi saya berkat kode solusi saya, ketika algoritme saya memodifikasi piksel individual gambar, ia mengira gambar itu diputar. Jadi alih-alih memodifikasi piksel di bagian atas gambar, ia memodifikasi piksel di sisi gambar (karena menurutnya itu harus diputar)! Saya tidak tahu cara memutar gambar dalam memori - idealnya saya lebih suka menghapusnyaimageOrientation semua bendera itu secara bersamaan.

Berikut hal lain yang juga membingungkan saya ... Saat saya mengambil foto, imageOrientationdisetel ke 3. Kode solusi saya cukup pintar untuk menyadari hal ini dan membaliknya sehingga pengguna tidak pernah menyadarinya. Selain itu, kode saya untuk menyimpan gambar ke perpustakaan menyadari hal ini, membaliknya, lalu menyimpannya sehingga muncul di rol kamera dengan benar.

Kode itu terlihat seperti ini:

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

Ketika saya memuat gambar yang baru disimpan ini ke dalam aplikasi saya, imageOrientationadalah 0 - persis seperti yang ingin saya lihat, dan solusi rotasi saya bahkan tidak perlu dijalankan (catatan: saat memuat gambar dari internet sebagai kebalikan dari gambar yang diambil dengan kamera , imageOrientationselalu 0, menghasilkan perilaku yang sempurna). Untuk beberapa alasan, kode penyimpanan saya tampaknya menghapus imageOrientationbendera ini . Saya berharap untuk mencuri kode itu dan menggunakannya untuk menghapus imageOrientation saya segera setelah pengguna mengambil foto dan menambahkannya ke aplikasi, tetapi tampaknya tidak berhasil. Apakah UIImageWriteToSavedPhotosAlbummelakukan sesuatu yang istimewa dengan imageOrientation?

Apakah perbaikan terbaik untuk masalah ini adalah dengan pergi begitu saja imageOrientation segera setelah pengguna selesai mengambil gambar. Saya berasumsi Apple melakukan perilaku rotasi karena suatu alasan, bukan? Beberapa orang berpendapat bahwa ini adalah cacat Apple.

(... jika Anda belum tersesat ... Note2: Saat saya mengambil foto horizontal, semuanya tampak bekerja dengan sempurna, seperti foto yang diambil dari internet)

EDIT:

Berikut adalah beberapa gambar dan skenario yang sebenarnya terlihat. Berdasarkan komentar selama ini, sepertinya perilaku aneh ini lebih dari sekedar perilaku iPhone, yang menurut saya bagus.

Ini adalah gambar dari foto yang saya ambil dengan ponsel saya (perhatikan orientasi yang benar), itu muncul persis seperti yang terjadi di ponsel saya ketika saya mengambil foto:

Foto Aktual diambil dengan iPhone

Berikut adalah tampilan gambar di Gmail setelah saya mengirimkannya ke email saya sendiri (sepertinya Gmail menanganinya dengan benar):

Foto seperti yang terlihat di Gmail

Berikut adalah tampilan gambar sebagai thumbnail di windows (sepertinya tidak ditangani dengan benar):

Gambar Mini Windows

Dan inilah tampilan gambar sebenarnya saat dibuka dengan Windows Photo Viewer (masih belum ditangani dengan benar):

Versi Windows Photo Viewer

Setelah semua komentar tentang pertanyaan ini, inilah yang saya pikirkan ... iPhone mengambil sebuah gambar, dan berkata "untuk menampilkan ini dengan benar, itu perlu diputar 90 derajat". Informasi ini akan ada dalam data EXIF. (Mengapa harus diputar 90 derajat, daripada default ke vertikal lurus, saya tidak tahu). Dari sini, Gmail cukup pintar untuk membaca dan menganalisis data EXIF ​​itu, dan menampilkannya dengan benar. Namun Windows, tidak cukup pintar untuk membaca data EXIF, dan karena itu menampilkan gambar dengan tidak benar . Apakah asumsi saya benar?

Boeckm
sumber
Menarik ... jika itu benar, mengapa gambar yang diambil disetel ke sudut yang benar? Saya tahu ini bukan cacat iPhone, karena saya memperhatikan perilaku serupa ketika seorang teman (dengan BlackBerry) mengambil gambar dan mengirimkannya ke saya melalui MMS.
Boeckm
Lihat kamera Anda menulis metadata untuk memutarnya pada 90 derajat, beberapa OS membaca bahwa metadata dan sisanya tidak.
HarshIT
Bacaan yang cukup bagus (lihat jawaban @ Hadley di bawah - dulu di komentar). Jadi aplikasi saya jelas harus cukup pintar untuk menangani gambar yang berisi data EXIF, serta gambar yang tidak berisi data itu ... Saya masih tidak mengerti mengapa ketika saya mengambil foto dengan posisi menghadap ke atas, bendera orientasi mengatakan itu harus diputar 90 derajat?
Boeckm
Anda mengatur mode foto ke Potret dan Anda tidak memutar kamera ke sudut kanan atau mode Lansekap diatur dan kamera telah mengambil gambar dalam posisi sudut kanan, sensor secara otomatis akan mengatur orientasi ke posisi yang tepat. Lihat ini
HarshIT
1
Solusinya kemungkinan besar, aplikasi Anda perlu membaca meta data dan memutar gambar dan / atau mengubah metadata sesuai kebutuhan.
HarshIT

Jawaban:

50

Saya melakukan R&D di atasnya dan menemukan, setiap file gambar memiliki properti metadata. Jika metadata menentukan orientasi gambar yang umumnya diabaikan oleh OS lain selain Mac. Sebagian besar gambar yang diambil memiliki properti meta data yang disetel ke sudut kanan. Jadi Mac menunjukkannya dengan cara diputar 90 derajat. Anda dapat melihat gambar yang sama dengan cara yang benar di OS windows.

Untuk detail lebih lanjut, baca jawaban ini http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm

coba baca exif gambar Anda di sini http://www.exifviewer.org/ , atau http://regex.info/exif.cgi , atau http://www.addictivetips.com/internet-tips/view-complete-exif -metadata-informasi-dari-apapun-gambar-jpeg-online /

HarshIT
sumber
1
WOW! Saya tidak tahu ada BANYAK informasi di data EXIF! regex.info/exif.cgi adalah situs yang luar biasa! Saya pasti akan bermain-main dengan gambar malam ini di situs ini. Saya harus menguji setiap skenario, gambar diambil langsung, gambar diambil dari internet, gambar diambil diputar, dll. Terima kasih banyak!
Boeckm
Tautan exif pertama rusak sekarang, dan yang kedua telah diperbarui ke exif.regex.info/exif.cgi Saya mencoba mengedit jawabannya tetapi @ cj-dennis menolaknya karena suatu alasan.
Ryan
55

Saya memiliki masalah yang sama ketika saya mendapatkan gambar dari Kamera, saya meletakkan kode berikut untuk memperbaikinya .. Menambahkan metode scaleAndRotateImage dari sini

- (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
sumber
3
Seperti apa tampilan kode scaleAndRotateImage Anda? Setelah melakukan google, apakah sama dengan yang ada disini? diskusi.apple.com/thread/1537011?start=0&tstart=0
Boeckm
2
WOW ... Haha! Itu bekerja dengan sangat baik! Saya menggunakan kode dalam komentar saya di atas. Saya mendapat dua jawaban luar biasa untuk pertanyaan saya! Saya pikir itu berarti saya mengajukan pertanyaan yang terlalu besar ... Terima kasih banyak. Saya akan melakukan beberapa pengujian mendalam, tetapi sejauh ini masalah orientasi berfungsi baik dengan foto yang diambil secara vertikal dan horizontal.
Boeckm
3
Saya pikir ada bagian dari metode Anda yang hilang, tapi itu dan tautannya masih cukup bagi saya untuk menyelesaikan sisanya dan akhirnya membuat tampilan pemangkasan gambar saya berfungsi dengan baik, jadi terima kasih :)
Vic Smith
Saya senang ini membantu .. :)
Dilip Rajkumar
apakah blok kode ini mempertahankan tampilan gambar asli tetapi mengubah orientasi menjadi ke atas?
Junchao Gu
18

Salin / tempel cepat terjemahan cepat dari jawaban luar biasa 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;
}
thattyson
sumber
1
Terima kasih, tapi apa itu "biarkan rasio = lebar / tinggi;" gunakan untuk? Saya tidak dapat melihat tempat mana pun yang menggunakan rasio dalam {}
Pengzhi Zhou
18

Pertanyaan saya kali ini adalah mengapa ini terjadi? Mengapa Apple memutar gambar?

Jawabannya sangat sederhana. Apple TIDAK memutar gambar. Di situlah letak kebingungan.

Kamera CCD tidak berputar, jadi selalu mengambil foto dalam mode lanskap.

Apple melakukan hal yang sangat cerdas - alih-alih menghabiskan seluruh waktu untuk memutar gambar - mengacak beberapa megabyte data - cukup tandai dengan BAGAIMANA gambar itu diambil.

OpenGL melakukan terjemahan dengan sangat mudah - sehingga DATA tidak pernah terseok-seok - CARA DITARIK.

Oleh karena itu meta data orientasi.

Ini menjadi masalah jika Anda ingin memotong, mengubah ukuran, dll - tetapi begitu Anda tahu apa yang terjadi, Anda tinggal menentukan matriks Anda dan semuanya berhasil.

Roy
sumber
1
Terima kasih atas penjelasannya. Akal sehat setelah Anda memikirkannya, tetapi tidak ada hasil Google lainnya yang menjelaskannya.
Dakine83
16

Versi Swift 4 dengan pemeriksaan keamanan jawaban 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
sumber
Anda juga dapat melakukannya (bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)tanpa membuat variabel sebagai penyimpanan.
Almas Sapargali
Saya terkadang mengalami masalah, bahwa garis putih muncul di bagian bawah gambar setelah menskalakannya. Ini karena CGFloat tampaknya kurang tepat. Saya memperbaikinya dengan bounds.size.height.round()danbounds.size.width.round()
ndreisg
13

Gambar apa pun yang dihasilkan oleh iPhone / iPad disimpan sebagai Landscape Left dengan tag Orientasi EXIF ​​(Exif.Image.Orientation) yang menentukan orientasi sebenarnya.

Ini memiliki nilai berikut: 1: Landscape Left 6: Portrait Normal 3: Landscape Right 4: Portrait Upside Down

Di IOS, info EXIF ​​dibaca dengan benar dan gambar ditampilkan dengan cara yang sama seperti saat diambil. Namun di Windows, info EXIF ​​TIDAK digunakan.

Jika Anda membuka salah satu gambar ini di GIMP, itu akan mengatakan bahwa gambar tersebut memiliki info rotasi.

ATOzTOA
sumber
8

Untuk siapa pun yang menggunakan Xamarin, berikut terjemahan C # dari jawaban hebat Dilip , dan terima kasih kepada thattyson untuk terjemahan 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;
}
tetowill
sumber
Ini telah membantu menyelesaikan masalah saya setelah menghabiskan berjam-jam bermain dengan ini! Tidak dapat dipercaya bahwa Xamarin tidak memiliki dukungan bawaan untuk ini karena sekarang ini adalah produk Microsoft.
Sami.C
4

Saya menemukan pertanyaan ini karena saya mengalami masalah yang sama, tetapi menggunakan Swift. Hanya ingin menautkan ke jawaban yang berhasil bagi saya untuk pengembang Swift lainnya: https://stackoverflow.com/a/26676578/3904581

Berikut cuplikan Swift yang memperbaiki masalah secara efisien:

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

Sangat sederhana. Satu baris kode. Masalah terpecahkan.

Melly
sumber
Ini tidak berhasil untuk saya, saya menggunakan solusi ini: stackoverflow.com/a/27775741/945247
Leon
0

Dengan cepat direfraktorisasi untuk Swift 3 (dapatkah seseorang mengujinya dan mengonfirmasi bahwa semuanya berfungsi dengan baik?):

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
sumber
0

Ini adalah versi Swift3 dari jawaban mengagumkan 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!;
}
Sandip Mane
sumber
-3

Coba ubah format gambar menjadi .jpeg. Ini berhasil untuk saya

Victor Rius
sumber