【问题标题】:MFMailComposeViewController image orientationMFMailComposeViewController 图像方向
【发布时间】:2013-12-10 20:28:52
【问题描述】:

我正在开发一个通用应用程序,并且正在为 iOS6 编写代码。

我使用 imagePickerController 拍摄照片,然后使用 MFMailComposeViewController 将其作为附件发送。所有这些都有效。

我的问题是,当我以纵向模式拍摄照片时,MFMailComposeViewController 以横向模式显示它。此外,当它到达目标电子邮件地址时,它会以横向模式显示。

如果我以横向模式拍摄图片,MFMailComposeViewController 会以横向模式显示它,当它到达目标电子邮件地址时,它会以横向模式显示。所以没关系。

我的两台测试设备都有同样的问题; iPhone5 和 iPad2。

如何使以纵向模式拍摄的照片以纵向模式到达电子邮件目的地?

这是我将图像添加到电子邮件的方式:

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

【问题讨论】:

    标签: iphone image email ios6 orientation


    【解决方案1】:

    如果有人最终来到这里并需要 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()
    

    【讨论】:

      【解决方案2】:

      比例部分的swift版本:

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

      【讨论】:

        【解决方案3】:

        我自己在 iOS SDK7 中遇到了图像方向问题,我想在此讨论中添加一些内容,希望对其他人有用。 UIImageJPEGRepresentation 工作正常,但请注意,使用 UIImagePNGRepresentation 可能会导致图像方向不正确。

        我正在开发一个应用程序,在使用设备相机拍摄后上传图片。我不会将图像临时存储到磁盘,而是直接将其发送到服务器。

        在将 UIImage 渲染到 NSData 时,您可以在 UIImagePNGRepresentationUIImageJPEGRepresentation 之间进行选择。

        使用UIImagePNGRepresentation 时,纵向和横向拍摄的图片都会生成横向图像。在这种情况下,纵向图像逆时针旋转 90 度。

        使用UIImageJPEGRepresentation 时,纵向和横向图像都会产生正确的方向。

        【讨论】:

          【解决方案4】:

          我认为您可以让 UIImage API 自动为您处理旋转,而无需手动进行转换。

          UIImage 方法 sizedrawInRect: 的文档都说它们考虑了方向,所以我将 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 by an0 几乎是一样的,但还包括在方向已经正确的情况下不重新绘制图像的优化。

          【讨论】:

            【解决方案5】:

            我已经在这个问题上花费了几个小时,现在我清楚发生了什么以及如何解决它。

            重复一遍,我遇到的问题是:

            当我使用 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;
            

            请注意,orientation 属性描述了 UIImage 中的数据是如何物理配置的(如 3264w x 2448h);它仅描述捕获图像时的方向。

            该属性的作用是告诉即将显示图像的软件如何旋转它以使其正确显示。

            如果您以纵向模式捕获图像,image.imageOrientation 将返回 UIImageOrientationRight。这告诉显示软件它需要将图像旋转 90 度才能正确显示。请注意,这种“旋转”不会影响 UIImage 的底层存储,它保持为 3264w x 2448h。

            如果您在横向模式下捕获图像,image.imageOrientation 将返回 UIImageOrientationUp。 UIImageOrientationUp 告诉显示软件图像可以按原样显示;无需旋转。同样,UIIMage 的底层存储是 3264w x 2448h。

            一旦您清楚数据的物理存储方式与orientation 属性如何用于描述其在捕获时的方向之间的区别,事情就会变得更加清晰。

            我创建了几行调试代码来“查看”所有这些。

            这里又是 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 和 width = 3264 和 height = 2448 到达。

            如果我们拍摄风景,gImage 会以 UIImageOrientationUp 和 width = 3264 和 height = 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 的底层存储)。

            控制流现在转到电子邮件程序代码,并且方向属性仍然存在于 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 和 width = 3264 和 height = 2448。

            方向属性已被剥离,默认方向为向上。如果你不知道剥离是怎么回事,那真的很混乱。

            如果我运行这段代码,我现在得到以下结果:

            imagePickerController 代码中的东西没有改变;图像像以前一样被捕获。

            控制流继续到 E-Mailer 代码,但现在方向属性已从 tmp 图像中剥离,因此当 MFMailComposeViewController 代码在外发电子邮件中显示 tmp 图像时,它以横向模式显示(因为默认方向是 UIImageOrientationUp 所以没有旋转 3264x2448 图像)。

            电子邮件已发送,而在接收端,方向属性的知识也丢失了,因此接收软件将图像显示为物理布局为 3264x2448,即横向。

            在制作 UIImage 的副本时,可以避免这种方向属性的“剥离”,如果有人知道它正在发生,通过使用以下代码制作 UIImage 副本:

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

            这可以让您避免在途中丢失方向属性,但当您通过电子邮件发送图像时,它仍然不会处理远端的丢失。

            有一个比这一切搞砸和担心方向属性更好的方法。

            我发现了一些代码here,已集成到我的程序中。此代码将根据其方向属性物理旋转底层存储的图像。

            对于方向为 UIImageOrientationRight 的 UIImage,它将物理旋转 UIImage,使其最终为 2448x3264,并且它会剥离方向属性,因此此后将其视为默认的 UIImageOrientationUp。

            对于具有 UIImageOrientationUp 方向的 UIImage,它什么也不做。它让睡觉的风景狗躺着。

            如果你这样做,那么我认为(基于我目前所见),UIImage 的方向属性此后就多余了。只要它仍然丢失/剥离或设置为 UIImageOrientationUp,您的图像应该在沿途的每一步正确显示,并且在显示嵌入在您的电子邮件中的图像时在远端正确显示。

            我在答案中讨论的所有内容,我都亲眼目睹了它的发生。

            所以,这是我的最终代码:

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

            干杯,来自新西兰。

            【讨论】:

            • 一个非常全面和有用的答案,谢谢,我现在要尝试实现它。仅供参考 - 您可能想将此标记为答案。
            • 谢谢,格雷格。我本来打算这样做,然后忘记了。
            • 完美运行!与我阅读并尝试过的许多其他解决方案相反。谢谢!
            • @Gallymon 你能解释一下 gImag = (PIMG)[info valueForKey: UIImagePickerControllerOriginalImage];和 PIMG ImgOut = [gU scaleAndRotateImage: tmpImag];这个代码示例中的 PIMG 和 gU 是什么?
            • @Oskariagon,我在我给出的代码示例中为 PIMG 和 gU 道歉。我使用很多定义在我的代码中创建缩写,以使代码更紧凑并且(对我而言)更具可读性。因此,PIMG 代表 UIImage *。我以为我在发布之前已经将所有这些都根除,但我错过了这个。 gU 指向一个全局可见的对象,该对象包含我从所有代码中调用的实用程序。
            【解决方案6】:

            您需要根据其方向旋转图像。这里有一个技巧如何轻松做到这一点:

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

            【讨论】:

            • Leo Natan,对不起,这根本没有区别。我添加了你的代码,就在它之前,我做了一个 image.imageOrientation 并得到了 3 的“正确”。就在您的代码之后,我重复并得到 0 表示“向上”。因此,您的代码完成了它打算做的事情,并且传递给 UIImagePNGRepresentation 的 gImag 具有“向上”方向。但是,我仍然得到相同的结果:纵向旋转并且横向很好。
            • 我已经说服自己进入 setMailComposeDelegate 调用的 image.imageOrientation 状态是无关紧要的。它可以是 UIOrientation = up 或 right 并且结果不会改变。肖像旋转为风景,风景作为风景穿过。
            • Leo Natan,您建议的代码不会旋转 UIImage。它会根据您的要求创建具有方向设置的新副本。
            • @Gallymon 请立即尝试。
            • Leo Natan,我确实试过这个。我看到与 sourceImage 一起到达的方向属性由第三行保留。请您告诉我,将 sourceImage 转换为 NSData 然后在前两行中转换回 UIImage 有什么意义?此代码不会旋转底层物理图像。请查看我的回答,了解为什么我认为需要轮换才能解决此问题。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多