2013-11-25 3 views
13

Я разрабатываю универсальное приложение, и я кодирую iOS6.Ориентация изображения MFMailComposeViewController

Я использую imagePickerController, чтобы сделать снимок, а затем отправлю его в виде вложения с помощью MFMailComposeViewController. Все это работает.

Проблема заключается в том, что когда я снимаю изображение в портретном режиме, он отображается в режиме MFMailComposeViewController в ландшафтном режиме. Кроме того, когда он достигает адреса электронной почты адресата, он отображается в альбомном режиме.

Если я снимаю изображение в ландшафтном режиме, он отображается в режиме MFMailComposeViewController в ландшафтном режиме, и когда он достигнет адреса электронной почты адресата, он отображается в ландшафтном режиме. Так что все в порядке.

У меня такая же проблема на обоих моих тестовых устройствах; iPhone5 и iPad2.

Как сделать снимок, сделанный в портретном режиме, до адресата электронной почты в портретном режиме?

Вот как я добавляю изображение на E-Mail:

if ([MFMailComposeViewController canSendMail]) 
    { 
    MFMailComposeViewController * mailVC = [MFMailComposeViewController new]; 
    NSArray * aAddr = [NSArray arrayWithObjects: gAddr, nil]; 
    NSData * imageAsNSData = UIImagePNGRepresentation(gImag); 

    [mailVC setMailComposeDelegate: self]; 
    [mailVC  setToRecipients: aAddr]; 
    [mailVC    setSubject: gSubj]; 
    [mailVC  addAttachmentData: imageAsNSData 
         mimeType: @"image/png" 
         fileName: @"myPhoto.png"]; 
    [mailVC   setMessageBody: @"Blah blah" 
          isHTML: NO]; 

    [self presentViewController: mailVC 
         animated: YES 
        completion: nil]; 
    } 
else 
    { 
    NSLog(@"Device is unable to send email in its current state."); 
    } 

ответ

55

Я провел несколько часов работы по этому вопросу, и я теперь ясно, о том, что происходит и как это исправить.

Повторим, проблема я столкнулся это:

Когда я снимать изображение в портретном режиме на камеру с помощью imagePickerController и передать этот образ в MFMailComposeViewController и по электронной почте, он прибыл в пункт назначения Адрес электронной почты и отображается в ландшафтном режиме неправильно.

Однако, если я снимаю картину в ландшафтном режиме, а затем отправить его, он отображается в пункте назначения электронной почты, в правильно в ландшафтном режиме

Итак, как я могу сделать снимок снятый в портретном режиме прибывают на адресате электронной почты в портретном режиме? Это был мой первоначальный вопрос.

Вот код, как я показал его в исходном вопросе, за исключением того, что теперь я отправляю изображение как JPEG, а не PNG, но это не имеет никакого значения.

Это, как я захватить изображение с imagePickerController и поместить его в глобальную называется gImag:

gImag = (UIImage *)[info valueForKey: UIImagePickerControllerOriginalImage]; 
[[self imageView] setImage: gImag];    // send image to screen 
[self imagePickerControllerRelease: picker ]; // free the picker object 

И это, как я отправить по электронной почте с помощью MFMailComposeViewController:

if ([MFMailComposeViewController canSendMail]) 
    { 
    MFMailComposeViewController * mailVC = [MFMailComposeViewController new]; 
    NSArray * aAddr = [NSArray arrayWithObjects: gAddr, nil]; 
    NSData * imageAsNSData = UIImageJPEGRepresentation(gImag); 

    [mailVC setMailComposeDelegate: self]; 
    [mailVC  setToRecipients: aAddr]; 
    [mailVC    setSubject: gSubj]; 
    [mailVC  addAttachmentData: imageAsNSData 
         mimeType: @"image/jpg" 
         fileName: @"myPhoto.jpg"]; 
    [mailVC   setMessageBody: @"Blah blah" 
          isHTML: NO]; 

    [self presentViewController: mailVC 
         animated: YES 
        completion: nil]; 
    } 
else NSLog(@"Device is unable to send email in its current state."); 

Когда я описываю, как это решить, я собираюсь сосредоточиться на работе с iPhone 5 и с помощью своей основной камеры, которая стреляет по 3264x2448, просто чтобы все было просто. Однако эта проблема влияет на другие устройства и разрешения.

Ключом к разблокированию этой проблемы является, чтобы понять, что при съемке изображения, в любом портрете пейзажа, iPhone всегда сохраняет UIImage одинаково: 3264 широкий и 2448 высоко.

UIImage имеет свойство, описывающее его ориентацию в то время образ был взят в плен, и вы можете получить его, как это:

UIImageOrientation orient = image.imageOrientation; 

Обратите внимание, что свойство ориентации делает не описывают, как данные в UIImage физически настроен (как 3264w x 2448h); он только описывает свою ориентацию во время захвата изображения.

Для использования программного обеспечения, которое предназначено для отображения изображения, как его повернуть, оно должно отображаться правильно.

Если вы снимаете изображение в портретном режиме, image.imageOrientation вернет UIImageOrientationRight. Это говорит о том, что для отображения программного обеспечения необходимо поворачивать изображение на 90 градусов, чтобы он отображался правильно. Понятно, что это «вращение» не влияет на базовое хранилище UIImage, которое остается 3264w x 2448h.

Если вы сделаете захват изображения в ландшафтном режиме, image.imageOrientation вернет UIImageOrientationUp. UIImageOrientationUp сообщает отображать программное обеспечение, что изображение должно отображаться как есть; нет вращение не требуется. Опять же, базовое хранилище UIIMage составляет 3264w x 2448h.

Как только вы четко понимаете разницу между физическим хранением данных и тем, как свойство ориентации используется для описания его ориентации в момент его захвата, все становится понятнее.

Я создал несколько строк кода отладки, чтобы «видеть» все это.

Вот код imagePickerController снова с кодом отладки добавил:

gImag = (PIMG)[info valueForKey: UIImagePickerControllerOriginalImage]; 

UIImageOrientation orient = gImag.imageOrientation; 
CGFloat   width = CGImageGetWidth(gImag.CGImage); 
CGFloat   height = CGImageGetHeight(gImag.CGImage); 

[[self imageView] setImage: gImag];     // send image to screen 
[self imagePickerControllerRelease: picker ]; // free the picker object 

Если мы снимаем портрет, gImage приходит с UIImageOrientationRight и шириной = 3264 и высота = 2448.

Если мы снимаем пейзаж, gImage поступает с UIImageOrientationUp и шириной = 3264 и высотой = 2448.

Если мы перейдем к коду E-Mailng MFMailComposeViewController, я также добавил туда код отладки:

if ([MFMailComposeViewController canSendMail]) 
    { 
    MFMailComposeViewController * mailVC = [MFMailComposeViewController new]; 
    NSArray * aAddr = [NSArray arrayWithObjects: gAddr, nil]; 

    UIImageOrientation orient = gImag.imageOrientation; 
    CGFloat   width = CGImageGetWidth(gImag.CGImage); 
    CGFloat   height = CGImageGetHeight(gImag.CGImage); 

    NSData * imageAsNSData = UIImageJPEGRepresentation(gImag); 

    [mailVC setMailComposeDelegate: self]; 
    [mailVC  setToRecipients: aAddr]; 
    [mailVC    setSubject: gSubj]; 
    [mailVC  addAttachmentData: imageAsNSData 
         mimeType: @"image/jpg" 
         fileName: @"myPhoto.jpg"]; 
    [mailVC   setMessageBody: @"Blah blah" 
          isHTML: NO]; 

    [self presentViewController: mailVC 
         animated: YES 
        completion: nil]; 
    } 
else NSLog(@"Device is unable to send email in its current state."); 

Ничего удивительного здесь увидеть. Мы получаем те же значения, что и в коде imagePickerController.

Давайте посмотрим, как именно эта проблема проявляется:

Для начала, камера делает портретную съемку и он правильно отображается в портретном режиме по линии:

[[self imageView] setImage: gImag];     // send image to screen 

Это дисплей правильно потому что эта строка кода видит свойство ориентации и соответствующим образом поворачивает изображение (при этом НЕ касаясь базового хранилища 3264x2448).

Теперь поток управления переходит к коду E-Mailer, и свойство ориентации все еще присутствует в gImag, поэтому, когда код MFMailComposeViewController отображает изображение в исходящей электронной почте, он правильно ориентирован. Физическое изображение сохраняется как 3264x2448.

Электронная почта отправляется, и на принимающей стороне информация о свойстве ориентации теряется, поэтому принимающее программное обеспечение отображает изображение, поскольку оно физически выложено как 3264x2448, то есть пейзаж.

В отладке я столкнулся с дополнительной путаницей. И это означает, что свойство ориентации можно удалить из UIImage, если вы сделаете копию его неправильно.

Этот код показывает проблему:

if ([MFMailComposeViewController canSendMail]) 
    { 
    MFMailComposeViewController * mailVC = [MFMailComposeViewController new]; 
    NSArray * aAddr = [NSArray arrayWithObjects: gAddr, nil]; 

    UIImageOrientation orient = gImag.imageOrientation; 
    CGFloat   width = CGImageGetWidth(gImag.CGImage); 
    CGFloat   height = CGImageGetHeight(gImag.CGImage); 

    UIImage * tmp = [[UIImage alloc] initWithCGImage: gImag.CGImage]; 

    orient = tmp.imageOrientation; 
    width = CGImageGetWidth(tmp.CGImage); 
    height = CGImageGetHeight(tmp.CGImage); 

    NSData * imageAsNSData = UIImageJPEGRepresentation(tmp); 

    [mailVC setMailComposeDelegate: self]; 
    [mailVC  setToRecipients: aAddr]; 
    [mailVC    setSubject: gSubj]; 
    [mailVC  addAttachmentData: imageAsNSData 
         mimeType: @"image/jpg" 
         fileName: @"myPhoto.jpg"]; 
    [mailVC   setMessageBody: @"Blah blah" 
          isHTML: NO]; 

    [self presentViewController: mailVC 
         animated: YES 
        completion: nil]; 
    } 
else NSLog(@"Device is unable to send email in its current state."); 

Когда мы посмотрим на данные отладки для нового UIImage TMP, мы получаем UIImageOrientationUp и ширину = 3264 и высота = 2448.

Ориентацию свойство было разделение и ориентация по умолчанию - Up. Если вы не знаете, что происходит зачистка, это может действительно запутать вещи.

Если я запускаю этот код, я теперь получить следующие результаты:

Вещи без изменений в коде imagePickerController; изображение захватывается по-прежнему.

Поток управления переходит к коду E-Mailer, но теперь свойство ориентации было удалено из изображения tmp, поэтому, когда код MFMailComposeViewController отображает изображение tmp в исходящей электронной почте, он отображается в виде пейзажа (потому что ориентация по умолчанию - UIImageOrientationUp, поэтому нет поворота изображения 3264x2448).

Электронная почта отправляется, и на принимающей стороне также отсутствует знание свойства ориентации, поэтому получающее программное обеспечение отображает изображение, поскольку оно физически выложено как 3264x2448, т. Е. Пейзаж.

Этот «зачистки» свойства ориентации при принятии копии UIImage можно избежать, если один знает, что происходит, используя следующий код, чтобы сделать UIImage скопировать:

UIImage * tmp = [UIImage imageWithCGImage: gImag.CGImage 
            scale: gImag.scale 
           orientation: gImag.imageOrientation]; 

Это позволит вам избежать потери свойства ориентации на этом пути, но все равно не будет иметь дело с его потерей на дальнем конце при отправке по электронной почте изображения.

Есть лучший способ, чем все это возиться и беспокоиться о свойстве ориентации.

Я нашел код here, который я включил в свою программу. Этот код будет физически вращать базовое сохраненное изображение в соответствии со свойством ориентации.

Для UIImage с ориентацией UIImageOrientationRight он будет физически вращать UIImage, чтобы он заканчивался как 2448x3264, и он отделяет свойство ориентации, поэтому он рассматривается как UIImageOrientationUp по умолчанию.

Для UIImage с ориентацией UIImageOrientationUp он ничего не делает. Это позволяет лгать собакам спящего ландшафта.

Если вы сделаете это, я думаю (исходя из того, что я видел до сих пор), что свойство ориентации UIImage является излишним после этого. До тех пор, пока он не будет отсутствовать/снят или установлен в UIImageOrientationUp, ваши изображения должны отображаться правильно на каждом шаге по пути и на дальнем конце, когда отображаются изображения, встроенные в ваш E-Mail.

Все, что я обсуждал в ответ, у меня лично одноступенчатый и наблюдал, как это происходит.

Итак, вот мой окончательный код, который работает:

gImag = (PIMG)[info valueForKey: UIImagePickerControllerOriginalImage]; 
[[self imageView] setImage: gImag];    // send image to screen 
[self imagePickerControllerRelease: picker ]; // free the picker object 

и

if ([MFMailComposeViewController canSendMail]) 
    { 
    MFMailComposeViewController * mailVC = [MFMailComposeViewController new]; 
    NSArray      * aAddr = [NSArray arrayWithObjects: gAddr, nil]; 

    //...lets not touch the original UIImage 

    UIImage * tmpImag = [UIImage imageWithCGImage: gImag.CGImage 
              scale: gImag.scale 
            orientation: gImag.imageOrientation]; 

    //...do physical rotation, if needed 

    PIMG ImgOut = [gU scaleAndRotateImage: tmpImag]; 

    //...note orientation is UIImageOrientationUp now 

    NSData * imageAsNSData = UIImageJPEGRepresentation(ImgOut, 0.9f); 

    [mailVC setMailComposeDelegate: self]; 
    [mailVC  setToRecipients: aAddr]; 
    [mailVC    setSubject: gSubj]; 
    [mailVC  addAttachmentData: imageAsNSData 
         mimeType: @"image/jpg" 
         fileName: @"myPhoto.jpg"]; 
    [mailVC   setMessageBody: @"Blah blah" 
          isHTML: NO]; 

    [self presentViewController: mailVC 
         animated: YES 
        completion: nil]; 
    } 
else NSLog(@"Device is unable to send email in its current state."); 

И, наконец, вот код, который я взял из here, что делает физическое вращение, при необходимости:

- (UIImage *) scaleAndRotateImage: (UIImage *) imageIn 
    //...thx: http://blog.logichigh.com/2008/06/05/uiimage-fix/ 
    { 
    int kMaxResolution = 3264; // Or whatever 

    CGImageRef  imgRef = imageIn.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)); 
    UIImageOrientation orient  = imageIn.imageOrientation; 
    CGFloat   boundHeight; 

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

Cheers, from New Зеландия.

+1

Очень полный и полезный ответ, спасибо, я собираюсь попытаться реализовать это сейчас. Просто FYI - вы можете отметить это как ответ. – Greg

+1

Спасибо, Грег. Я намеревался это сделать, а потом забыл вернуться к нему. – Gallymon

+0

Работал отлично! в отличие от многих других решений, которые я прочитал и попробовал. Благодаря! – Nate

0

Вам нужно повернуть изображение в соответствии с его ориентацией. Вот трюк, как сделать это легко:

NSData *data = UIImagePNGRepresentation(sourceImage); 
UIImage *tmp = [UIImage imageWithData:data]; 
UIImage *fixed = [UIImage imageWithCGImage:tmp.CGImage 
            scale:sourceImage.scale 
           orientation:sourceImage.imageOrientation]; 
+0

Лео Натан, извините, это не имело никакого значения. Я добавил вам код и только до этого, я сделал image.imageOrientation и получил 3 для «права». Сразу после вашего кода я повторил и получил 0 для «вверх». Итак, ваш код сделал то, что он намеревался сделать, и gImag, переданный в UIImagePNGRпредставление, имел ориентацию «вверх». Но у меня все тот же результат: портрет вращается, а пейзаж - в порядке. – Gallymon

+0

Я убедил себя, что состояние image.imageOrientation, входящее в вызов setMailComposeDelegate, не имеет значения. Это может быть UIOrientation = вверх или вправо, и результат не изменяется. Портреты повернуты к пейзажу, а пейзажи проходят через ландшафты. – Gallymon

+0

Leo Natan, ваш предлагаемый код не вращает UIImage. Он создает новую копию с установкой ориентации по вашему запросу. – Gallymon

1

Я думаю, вы можете получить API UIImage для автоматического поворота для вас, без необходимости вручную выполнять преобразования.

документация для методов UIImage размера и drawInRect: как говорят, они принимают во внимание ориентацию, так что я drawInRect в UIImage в новый контекст и захватить результирующий (автоматический повернутых) изображение оттуда. Вот код в категории:

@interface UIImage (Orientation) 

- (UIImage*)imageAdjustedForOrientation; 

@end 

@implementation UIImage (Orientation) 
- (UIImage*)imageAdjustedForOrientation 
{ 
    // The UIImage methods size and drawInRect take into account 
    // the value of its imageOrientation property 
    // so the rendered image is rotated as necessary. 
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); 

    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; 

    UIImage *orientedImage = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return orientedImage; 
} 
@end 

Я только что нашел this better answer по AN0 что практически то же самое, но также включает в себя оптимизацию повторно не перерисовывать изображение, если ориентация уже правильно.

3

Я боролся с ориентациями изображений в iOS SDK7, и я хочу добавить что-то к этой дискуссии в надежде, что это полезно для других. UIImageJPEGRepresentation отлично работает, но имейте в виду, что использование UIImagePNGRepresentation может привести к неправильной ориентации изображения.

Я разрабатываю приложение, в котором изображение загружается после съемки с камеры устройства. Я не сохраняю изображение временно на диск, а скорее отправляю его непосредственно на сервер.

При визуализации UIImage в NSData вы можете выбирать между UIImagePNGRepresentation и UIImageJPEGRepresentation.

При использовании UIImagePNGRepresentation изображение, снятое в портретной и альбомной ориентации, приводит к пейзажному изображению. В этом случае портретное изображение поворачивается на 90 градусов против часовой стрелки.

При использовании UIImageJPEGRepresentation изображение как в портретном, так и в ландшафтном изображении получается с правильной ориентацией.

2

быстры версия шкалы части:

class func scaleAndRotateImageUsingOrientation(imageIn : UIImage) -> UIImage 
    { 
     //takes into account the stored rotation on the image fromt he camera and makes it upright 
     let kMaxResolution = 3264; // Or whatever 

     let imgRef = imageIn.CGImage 
     let width  = CGImageGetWidth(imgRef) 
     let height = CGImageGetHeight(imgRef) 
     var transform = CGAffineTransformIdentity 
     var bounds = CGRectMake(0.0, 0.0, CGFloat(width), CGFloat(height)) 

     if (width > kMaxResolution || height > kMaxResolution) 
     { 
      let ratio : CGFloat = CGFloat(width)/CGFloat(height); 

      if (ratio > 1) 
      { 
       bounds.size.width = CGFloat(kMaxResolution) 
       bounds.size.height = bounds.size.width/ratio; 
      } 
      else 
      { 
       bounds.size.height = CGFloat(kMaxResolution) 
       bounds.size.width = bounds.size.height * ratio 
      } 
     } 

     let scaleRatio : CGFloat = bounds.size.width/CGFloat(width) 
     var imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef))) 
     let orient  = imageIn.imageOrientation; 
     var boundHeight : CGFloat = 0.0 

     switch(orient) 
     { 
     case UIImageOrientation.Up:          //EXIF = 1 
      transform = CGAffineTransformIdentity; 
      break; 

     case UIImageOrientation.UpMirrored:        //EXIF = 2 
      transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); 
      transform = CGAffineTransformScale(transform, -1.0, 1.0); 
     break; 

     case UIImageOrientation.Down:          //EXIF = 3 
      transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 
      transform = CGAffineTransformRotate(transform, CGFloat(M_PI)); 
      break; 

     case UIImageOrientation.DownMirrored:        //EXIF = 4 
      transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); 
      transform = CGAffineTransformScale(transform, 1.0, -1.0); 
      break; 

     case UIImageOrientation.LeftMirrored:        //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 * CGFloat(M_PI)/2.0); 
      break; 

     case UIImageOrientation.Left:          //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 * CGFloat(M_PI)/2.0); 
      break; 

     case UIImageOrientation.RightMirrored:        //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, CGFloat(M_PI)/2.0); 
      break; 

     case UIImageOrientation.Right:          //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, CGFloat(M_PI)/2.0); 
      break; 

     default: 
      break 

     } 

     UIGraphicsBeginImageContext(bounds.size); 

     var context = UIGraphicsGetCurrentContext(); 

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

     CGContextConcatCTM(context, transform); 

     CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, CGFloat(width), CGFloat(height)), imgRef); 
     let imageCopy = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 

     return(imageCopy); 
    } 
0

В случае, если кто заканчивает здесь и требует Swift 4 решения:

// UIImage+orientedUp.swift 
// ID Fusion Software Inc 
// Created by Dave Poirier on 2017-12-27 
// Unlicensed 
// 

import UIKit 

extension UIImage { 
    func orientedUp() -> UIImage { 
     guard self.imageOrientation != UIImageOrientation.up, 
      let cgImage = self.cgImage, 
      let colorSpace = cgImage.colorSpace 
      else { return self } 

     guard let ctx: CGContext = CGContext(data: nil, 
              width: Int(self.size.width), height: Int(self.size.height), 
              bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, 
              bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { return self } 
     ctx.concatenate(self.orientedUpTransform()) 

     switch self.imageOrientation { 
     case UIImageOrientation.left, UIImageOrientation.leftMirrored, UIImageOrientation.right, UIImageOrientation.rightMirrored: 
      ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: self.size.height, height: self.size.width)) 
     default: 
      ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)) 
     } 

     guard let orientedCGImage: CGImage = ctx.makeImage() 
      else { return self } 

     return UIImage(cgImage: orientedCGImage) 
    } 

    func orientedUpTransform() -> CGAffineTransform { 
     var transform: CGAffineTransform = CGAffineTransform.identity 

     switch self.imageOrientation { 
     case UIImageOrientation.down, UIImageOrientation.downMirrored: 
      transform = transform.translatedBy(x: self.size.width, y: self.size.height) 
      transform = transform.rotated(by: CGFloat(Double.pi)) 
     case UIImageOrientation.left, UIImageOrientation.leftMirrored: 
      transform = transform.translatedBy(x: self.size.width, y: 0) 
      transform = transform.rotated(by: CGFloat(Double.pi/2.0)) 
     case UIImageOrientation.right, UIImageOrientation.rightMirrored: 
      transform = transform.translatedBy(x: 0, y: self.size.height) 
      transform = transform.rotated(by: CGFloat(-Double.pi/2.0)) 
     default: 
      break 
     } 

     switch self.imageOrientation { 
     case UIImageOrientation.upMirrored, UIImageOrientation.downMirrored: 
      transform = transform.translatedBy(x: self.size.width, y: 0) 
      transform = transform.scaledBy(x: -1, y: 1) 
     case UIImageOrientation.leftMirrored, UIImageOrientation.rightMirrored: 
      transform = transform.translatedBy(x: self.size.height, y: 0) 
      transform = transform.scaledBy(x: -1, y: 1) 
     default: 
      break 
     } 

     return transform 
    } 
} 

Вы можете использовать его как это:

let image = UIImage(data: imageData)?.orientedUp() 
Смежные вопросы