Przez ostatnie kilka tygodni pracowałem z obrazami w obiektyw-c i zauważyłem wiele dziwnych zachowań. Po pierwsze, podobnie jak wiele innych osób, mam problem polegający na tym, że zdjęcia zrobione aparatem (lub zrobione innym aparatem i wysłane do mnie w wiadomości MMS) są obrócone o 90 stopni. Nie byłem pewien, dlaczego tak się dzieje na świecie (stąd moje pytanie ), ale udało mi się wymyślić tanią pracę.
Moje pytanie tym razem brzmi: dlaczego tak się dzieje ? Dlaczego Apple obraca obrazy? Kiedy robię zdjęcie aparatem prawą stroną do góry, o ile nie wykonuję powyższego kodu, kiedy zapisuję zdjęcie, zostaje ono zapisane jako obrócone. Aż do kilku dni temu moje obejście było w porządku.
Moja aplikacja modyfikuje poszczególne piksele obrazu, w szczególności kanał alfa pliku PNG (więc każda konwersja JPEG jest wyrzucana z okna w moim scenariuszu). Kilka dni temu zauważyłem, że chociaż obraz jest wyświetlany poprawnie w mojej aplikacji dzięki kodowi obejścia, kiedy mój algorytm modyfikuje poszczególne piksele obrazu, uważa, że obraz jest obrócony. Więc zamiast modyfikować piksele na górze obrazu, modyfikuje piksele z boku obrazu (ponieważ uważa, że powinien być obrócony)! Nie potrafię wymyślić, jak obrócić obraz w pamięci - najlepiej byłoby, gdybyśmy po prostu usunęli tę imageOrientation
flagę razem.
Jest jeszcze coś, co mnie zaskoczyło ... Kiedy robię zdjęcie, imageOrientation
jest ustawiony na 3. Mój kod obejścia jest wystarczająco inteligentny, aby to zrealizować i odwrócić go, aby użytkownik nigdy tego nie zauważył. Dodatkowo mój kod zapisujący obraz w bibliotece zdaje sobie z tego sprawę, odwraca go, a następnie zapisuje, aby był prawidłowo wyświetlany w rolce aparatu.
Ten kod wygląda tak:
NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
Kiedy ładuję ten nowo zapisany obraz do mojej aplikacji, imageOrientation
jest 0 - dokładnie to, co chcę zobaczyć, a moje obejście nie musi nawet uruchamiać (uwaga: podczas ładowania obrazów z Internetu w przeciwieństwie do zdjęć zrobionych aparatem , imageOrientation
zawsze wynosi 0, co daje doskonałe zachowanie). Z jakiegoś powodu mój kod zapisu wydaje się usuwać tę imageOrientation
flagę. Miałem nadzieję, że po prostu wykradnę ten kod i użyję go do usunięcia mojej orientacji obrazu, gdy tylko użytkownik zrobi zdjęcie i doda je do aplikacji, ale wydaje się, że nie działa. Robi UIImageWriteToSavedPhotosAlbum
coś specjalnego imageOrientation
?
Najlepszym rozwiązaniem tego problemu byłoby po prostu zdmuchnięcie, imageOrientation
gdy tylko użytkownik skończy robić zdjęcie. Zakładam, że Apple ma jakieś zachowanie związane z rotacją, prawda? Kilka osób zasugerowało, że to wada Apple.
(... jeśli jeszcze się nie zgubiłeś ... Uwaga 2: Kiedy robię poziome zdjęcie, wszystko wydaje się działać idealnie, tak jak zdjęcia zrobione z internetu)
EDYTOWAĆ:
Oto, jak faktycznie wyglądają niektóre obrazy i scenariusze. Na podstawie dotychczasowych komentarzy wygląda na to, że to dziwne zachowanie jest czymś więcej niż tylko zachowaniem iPhone'a, co moim zdaniem jest dobre.
To jest zdjęcie zdjęcia, które zrobiłem telefonem (zwróć uwagę na właściwą orientację), wygląda dokładnie tak, jak na moim telefonie, kiedy zrobiłem zdjęcie:
Oto, jak wygląda obraz w Gmailu po wysłaniu go do siebie e-mailem (wygląda na to, że Gmail obsługuje go poprawnie):
Oto jak obraz wygląda jako miniatura w oknach (nie wygląda na to, że jest prawidłowo obsługiwany):
A oto, jak wygląda rzeczywisty obraz po otwarciu za pomocą przeglądarki fotografii systemu Windows (nadal nie jest obsługiwany prawidłowo):
Po wszystkich komentarzach do tego pytania, oto, co myślę ... iPhone robi zdjęcie i mówi „aby wyświetlić go poprawnie, należy go obrócić o 90 stopni”. Ta informacja byłaby w danych EXIF. (Dlaczego należy go obrócić o 90 stopni, zamiast domyślnie ustawiać go na prostą pionową, nie wiem). Stąd Gmail jest wystarczająco inteligentny, aby odczytywać i analizować dane EXIF oraz prawidłowo je wyświetlać. Jednak system Windows nie jest wystarczająco inteligentny, aby odczytać dane EXIF, a zatem wyświetla obraz nieprawidłowo . Czy moje przypuszczenia są prawidłowe?
źródło
Odpowiedzi:
Przeprowadziłem badania i odkryłem, że każdy plik obrazu ma właściwość metadanych. Jeśli metadane określają orientację obrazu, która jest zwykle ignorowana przez inne systemy operacyjne oprócz Mac. Większość wykonanych zdjęć ma właściwość metadanych ustawioną pod kątem prostym. Więc Mac pokazuje to w sposób obrócony o 90 stopni. Możesz zobaczyć ten sam obraz we właściwy sposób w systemie operacyjnym Windows.
Aby uzyskać więcej informacji, przeczytaj tę odpowiedź http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm
spróbuj przeczytać plik exif swojego obrazu tutaj http://www.exifviewer.org/ , http://regex.info/exif.cgi lub http://www.addictivetips.com/internet-tips/view-complete-exif -metadata-information-of-any-jpeg-image-online /
źródło
Miałem ten sam problem, gdy otrzymałem obraz z aparatu, wstawiłem następujący kod, aby to naprawić .. Dodano metodę scaleAndRotateImage stąd
- (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; }
źródło
Odpowiedź na to jest bardzo prosta. Apple NIE obraca obrazu. W tym tkwi zamieszanie.
Kamera CCD nie obraca się, więc zawsze robi zdjęcie w trybie poziomym.
Apple zrobił bardzo sprytną rzecz - zamiast spędzać cały czas na obracaniu obrazu - tasowaniu megabajtów danych - po prostu otaguj go, JAK to zdjęcie zostało zrobione.
OpenGL bardzo łatwo wykonuje tłumaczenia - dzięki czemu DANE nigdy nie są tasowane - po prostu JAK JEST RYSOWANE.
Stąd orientacja metadanych.
Staje się to problemem, jeśli chcesz przyciąć, zmienić rozmiar itp. - ale kiedy już wiesz, co się dzieje, po prostu definiujesz swoją macierz i wszystko działa.
źródło
Szybkie kopiowanie / wklejanie Szybkie tłumaczenie doskonałej odpowiedzi Dilipa .
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; }
źródło
Wersja Swift 4 z kontrolą bezpieczeństwa odpowiedzi Dilipa .
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 }
źródło
(bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)
bez tworzenia zmiennej jako magazynu.bounds.size.height.round()
ibounds.size.width.round()
Każdy obraz wygenerowany przez iPhone'a / iPada jest zapisywany jako Poziomo lewy ze znacznikiem EXIF Orientation (Exif.Image.Orientation) określającym aktualną orientację.
Ma następujące wartości: 1: Poziomo Lewo 6: Pionowo Normalnie 3: Poziomo Prawo 4: Pionowo do góry nogami
W systemie IOS informacje EXIF są poprawnie odczytywane, a obrazy są wyświetlane w taki sam sposób, w jaki zostały zrobione. Ale w systemie Windows informacje EXIF NIE są używane.
Jeśli otworzysz jeden z tych obrazów w GIMP-ie, powie, że obraz ma informacje o obrocie.
źródło
Dla każdego, kto korzysta z platformy Xamarin, oto tłumaczenie C # doskonałej odpowiedzi Dilipa oraz podziękowania dla thattyson za tłumaczenie w języku 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; }
źródło
Trafiłem na to pytanie, ponieważ miałem podobny problem, ale używam Swift. Chciałem tylko podać link do odpowiedzi, która działała dla mnie w przypadku innych programistów Swift: https://stackoverflow.com/a/26676578/3904581
Oto fragment kodu Swift, który skutecznie rozwiązuje problem:
let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!
Super proste. Jedna linia kodu. Problem rozwiązany.
źródło
Wiem dokładnie, na czym polega twój problem. Używasz UIImagePicker, co jest dziwne pod każdym względem. Sugerowałbym użycie AVFoundation do aparatu, który zapewnia elastyczność w orientacji, a także jakość. Użyj AVCaptureSession. Możesz pobrać kod tutaj. Jak zapisać zdjęcia zrobione za pomocą programu AVFoundation w Albumie zdjęć?
źródło
Szybka refaktoryzacja dla Swift 3 (czy ktoś może to przetestować i potwierdzić, że wszystko działa dobrze?):
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! }
źródło
Oto niesamowita odpowiedź Dilipa w wersji Swift3
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!; }
źródło
Spróbuj zmienić format obrazu na .jpeg. To zadziałało dla mnie
źródło