【问题标题】:iOS UIImagePickerController result image orientation after upload上传后iOS UIImagePickerController结果图像方向
【发布时间】:2011-07-22 14:37:33
【问题描述】:

我正在 iOS 3.1.3 iPhone 上测试我的 iPhone 应用程序。我正在使用UIImagePickerController 选择/捕获图像:

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setDelegate:self];
[self.navigationController presentModalViewController:imagePicker animated:YES];
[imagePicker release];



- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    self.image = [info objectForKey:UIImagePickerControllerOriginalImage];
    imageView.image = self.image;
    [self.navigationController dismissModalViewControllerAnimated:YES];
    submitButton.enabled = YES;
}

然后我会在某个时候使用 ASI 类将其发送到我的 Web 服务器:

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://example.com/myscript.php"]];
[request setDelegate:self];
[request setStringEncoding:NSUTF8StringEncoding];
[request setShouldContinueWhenAppEntersBackground:YES];
//other post keys/values
[request setFile:UIImageJPEGRepresentation(self.image, 100.0f) withFileName:[NSString stringWithFormat:@"%d.jpg", [[NSDate date] timeIntervalSinceNow]] andContentType:@"image/jpg" forKey:@"imageFile"];
[request startAsynchronous];

问题: 当我拿着 iphone 横向拍照时,图像会上传到服务器,它看起来就像你所期望的那样。手持手机纵向拍照时,图像会被上传并以旋转 90 度的方式查看。

我的应用程序设置为仅在纵向模式下工作(颠倒和常规)。

如何让图片在上传后始终显示正确的方向?

在 UIImageView 中显示的图像似乎是正确的(在拍照后直接显示),但在服务器上查看则不然。

【问题讨论】:

    标签: ios iphone cocoa-touch uiimage uiimagepickercontroller


    【解决方案1】:

    UIImage 有一个属性imageOrientation,它指示UIImageView 和其他UIImage 消费者旋转原始图像数据。这个标志很有可能被保存到上传的 jpeg 图像中的 exif 数据中,但是您用来查看它的程序不支持该标志。

    要旋转UIImage 以在上传时正确显示,您可以使用这样的类别:

    UIImage+fixOrientation.h

    @interface UIImage (fixOrientation)
    
    - (UIImage *)fixOrientation;
    
    @end
    

    UIImage+fixOrientation.m

    @implementation UIImage (fixOrientation)
    
    - (UIImage *)fixOrientation {
    
        // No-op if the orientation is already correct
        if (self.imageOrientation == UIImageOrientationUp) return self;
    
        // We need to calculate the proper transformation to make the image upright.
        // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
        CGAffineTransform transform = CGAffineTransformIdentity;
    
        switch (self.imageOrientation) {
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:
                transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
                transform = CGAffineTransformRotate(transform, M_PI);
                break;
    
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                transform = CGAffineTransformTranslate(transform, self.size.width, 0);
                transform = CGAffineTransformRotate(transform, M_PI_2);
                break;
    
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                transform = CGAffineTransformTranslate(transform, 0, self.size.height);
                transform = CGAffineTransformRotate(transform, -M_PI_2);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationUpMirrored:
                break;
        }
    
        switch (self.imageOrientation) {
            case UIImageOrientationUpMirrored:
            case UIImageOrientationDownMirrored:
                transform = CGAffineTransformTranslate(transform, self.size.width, 0);
                transform = CGAffineTransformScale(transform, -1, 1);
                break;
    
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRightMirrored:
                transform = CGAffineTransformTranslate(transform, self.size.height, 0);
                transform = CGAffineTransformScale(transform, -1, 1);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationDown:
            case UIImageOrientationLeft:
            case UIImageOrientationRight:
                break;
        }
    
        // Now we draw the underlying CGImage into a new context, applying the transform
        // calculated above.
        CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
                                                 CGImageGetBitsPerComponent(self.CGImage), 0,
                                                 CGImageGetColorSpace(self.CGImage),
                                                 CGImageGetBitmapInfo(self.CGImage));
        CGContextConcatCTM(ctx, transform);
        switch (self.imageOrientation) {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                // Grr...
                CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
                break;
    
            default:
                CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
                break;
        }
    
        // And now we just create a new UIImage from the drawing context
        CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
        UIImage *img = [UIImage imageWithCGImage:cgimg];
        CGContextRelease(ctx);
        CGImageRelease(cgimg);
        return img;
    }
    
    @end
    

    【讨论】:

    • 谢谢,工作完美。直到现在从未使用过或理解过它们!
    • @Anomie 我很难解释你让我多么开心。你的回答拯救了我的一天。非常感谢。
    • 我试过了,效果很好,但旋转 3264*2448 分辨率图像需要大约 2-3 秒。所以请建议改进​​版本。
    • 我认为stackoverflow.com/questions/8915630/… 是一个更好的答案
    • 这个问题还有另一种解决方案here(与这个非常相似),其中包括对实际情况的冗长讨论。
    【解决方案2】:

    我想出了一个更简单的方法:

    - (UIImage *)normalizedImage {
        if (self.imageOrientation == UIImageOrientationUp) return self; 
    
        UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
        [self drawInRect:(CGRect){0, 0, self.size}];
        UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return normalizedImage;
    }
    

    顺便说一句:@Anomie 的代码没有考虑到scale,因此不适用于 2x 图像。

    【讨论】:

    • 代码中如何使用?我有这个: UIImageJPEGRepresentation(image, 90);其中图像是 UIImage
    • @Odelya 将此方法添加到您的 UIImage 类别,然后调用 [image normalizedImage]。或者直接使用该方法的代码,将self 替换为您的 UIImage 对象。
    • @an0 该方法大约需要一秒钟,这会消耗时间。有什么办法可以改善吗?
    • 谢谢你。从我的测试看来,这种方法比选择的答案要快一些,在我的 iphone4 上大约是 20%。
    • 这个问题还有另一个解决方案here 以及对正在发生的事情的冗长解释。
    【解决方案3】:

    这是@an0 的答案的 Swift 版本:

    func normalizedImage() -> UIImage {
    
      if (self.imageOrientation == UIImageOrientation.Up) { 
          return self;
      }
    
      UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
      let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
      self.drawInRect(rect)
    
      let normalizedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()
      UIGraphicsEndImageContext();
      return normalizedImage;
    }
    

    还有一个更通用的功能:

    func fixOrientation(img:UIImage) -> UIImage {
    
      if (img.imageOrientation == UIImageOrientation.Up) { 
          return img;
      }
    
      UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale);
      let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
      img.drawInRect(rect)
    
      let normalizedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()
      UIGraphicsEndImageContext();
      return normalizedImage;
    
    }
    

    Swift 3 版本:

    func fixOrientation(img: UIImage) -> UIImage {
        if (img.imageOrientation == .up) {
            return img
        }
    
        UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale)
        let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
        img.draw(in: rect)
    
        let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
    
        return normalizedImage
    }
    

    【讨论】:

    • 很少需要一直滚动到底部才能获得最佳答案。 +1!
    • 我应该在哪里使用 fixOrientation?我有一个 saveImage 功能,我应该在那里使用它还是在我的 imageHolder.image 上使用它?
    • 如果您想使用上面更通用的功能,那么您可以在 saveImage 功能中使用它。只需将 fixOrientation 传递给您的 UIImage 对象,它就会返回您传递给它的 UIImage 的正确定向版本。
    • 感谢 Swift 3 版本
    【解决方案4】:

    解决 Swift 3.1 从相机捕获图像时的方向问题。

    我已经更新了 jake 和 Metal Heart 给出的解决方案

    UIImage 扩展

    //MARK:- Image Orientation fix
    
    extension UIImage {
    
        func fixOrientation() -> UIImage {
    
            // No-op if the orientation is already correct
            if ( self.imageOrientation == UIImageOrientation.up ) {
                return self;
            }
    
            // We need to calculate the proper transformation to make the image upright.
            // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
            var transform: CGAffineTransform = CGAffineTransform.identity
    
            if ( self.imageOrientation == UIImageOrientation.down || self.imageOrientation == UIImageOrientation.downMirrored ) {
                transform = transform.translatedBy(x: self.size.width, y: self.size.height)
                transform = transform.rotated(by: CGFloat(Double.pi))
            }
    
            if ( self.imageOrientation == UIImageOrientation.left || self.imageOrientation == UIImageOrientation.leftMirrored ) {
                transform = transform.translatedBy(x: self.size.width, y: 0)
                transform = transform.rotated(by: CGFloat(Double.pi / 2.0))
            }
    
            if ( self.imageOrientation == UIImageOrientation.right || self.imageOrientation == UIImageOrientation.rightMirrored ) {
                transform = transform.translatedBy(x: 0, y: self.size.height);
                transform = transform.rotated(by: CGFloat(-Double.pi / 2.0));
            }
    
            if ( self.imageOrientation == UIImageOrientation.upMirrored || self.imageOrientation == UIImageOrientation.downMirrored ) {
                transform = transform.translatedBy(x: self.size.width, y: 0)
                transform = transform.scaledBy(x: -1, y: 1)
            }
    
            if ( self.imageOrientation == UIImageOrientation.leftMirrored || self.imageOrientation == UIImageOrientation.rightMirrored ) {
                transform = transform.translatedBy(x: self.size.height, y: 0);
                transform = transform.scaledBy(x: -1, y: 1);
            }
    
            // Now we draw the underlying CGImage into a new context, applying the transform
            // calculated above.
            let ctx: CGContext = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height),
                                                          bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0,
                                                          space: self.cgImage!.colorSpace!,
                                                          bitmapInfo: self.cgImage!.bitmapInfo.rawValue)!;
    
            ctx.concatenate(transform)
    
            if ( self.imageOrientation == UIImageOrientation.left ||
                self.imageOrientation == UIImageOrientation.leftMirrored ||
                self.imageOrientation == UIImageOrientation.right ||
                self.imageOrientation == UIImageOrientation.rightMirrored ) {
                ctx.draw(self.cgImage!, in: CGRect(x: 0,y: 0,width: self.size.height,height: self.size.width))
            } else {
                ctx.draw(self.cgImage!, in: CGRect(x: 0,y: 0,width: self.size.width,height: self.size.height))
            }
    
            // And now we just create a new UIImage from the drawing context and return it
            return UIImage(cgImage: ctx.makeImage()!)
        }
    }
    

    Swift 2.0

    //MARK:- Image Orientation fix
    
    extension UIImage {
    
        func fixOrientation() -> UIImage {
    
            // No-op if the orientation is already correct
            if ( self.imageOrientation == UIImageOrientation.Up ) {
                return self;
            }
    
            // We need to calculate the proper transformation to make the image upright.
            // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
            var transform: CGAffineTransform = CGAffineTransformIdentity
    
            if ( self.imageOrientation == UIImageOrientation.Down || self.imageOrientation == UIImageOrientation.DownMirrored ) {
                transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
                transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
            }
    
            if ( self.imageOrientation == UIImageOrientation.Left || self.imageOrientation == UIImageOrientation.LeftMirrored ) {
                transform = CGAffineTransformTranslate(transform, self.size.width, 0)
                transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
            }
    
            if ( self.imageOrientation == UIImageOrientation.Right || self.imageOrientation == UIImageOrientation.RightMirrored ) {
                transform = CGAffineTransformTranslate(transform, 0, self.size.height);
                transform = CGAffineTransformRotate(transform,  CGFloat(-M_PI_2));
            }
    
            if ( self.imageOrientation == UIImageOrientation.UpMirrored || self.imageOrientation == UIImageOrientation.DownMirrored ) {
                transform = CGAffineTransformTranslate(transform, self.size.width, 0)
                transform = CGAffineTransformScale(transform, -1, 1)
            }
    
            if ( self.imageOrientation == UIImageOrientation.LeftMirrored || self.imageOrientation == UIImageOrientation.RightMirrored ) {
                transform = CGAffineTransformTranslate(transform, self.size.height, 0);
                transform = CGAffineTransformScale(transform, -1, 1);
            }
    
            // Now we draw the underlying CGImage into a new context, applying the transform
            // calculated above.
            let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height),
                CGImageGetBitsPerComponent(self.CGImage), 0,
                CGImageGetColorSpace(self.CGImage),
                CGImageGetBitmapInfo(self.CGImage).rawValue)!;
    
            CGContextConcatCTM(ctx, transform)
    
            if ( self.imageOrientation == UIImageOrientation.Left ||
                self.imageOrientation == UIImageOrientation.LeftMirrored ||
                self.imageOrientation == UIImageOrientation.Right ||
                self.imageOrientation == UIImageOrientation.RightMirrored ) {
                    CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage)
            } else {
                CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage)
            }
    
            // And now we just create a new UIImage from the drawing context and return it
            return UIImage(CGImage: CGBitmapContextCreateImage(ctx)!)
        }
    }
    

    在您的代码中使用此 UIImage 扩展:

    让 fixOrientationImage=chosenImage.fixOrientation()

    像这样将它放在图像选择器的委托方法中

    斯威夫特 3.1

    //MARK: Image Picker Delegates
        func imagePickerController(
            _ picker: UIImagePickerController,
            didFinishPickingMediaWithInfo info: [String : Any]){
            let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
            profileImg.contentMode = .scaleAspectFill
            let fixOrientationImage=chosenImage.fixOrientation()
            profileImg.image = fixOrientationImage
    
            dismiss(animated: true, completion: nil)
        }
    

    Swift 2.0

    //MARK: Image Picker Delegates
        func imagePickerController(
            picker: UIImagePickerController,
            didFinishPickingMediaWithInfo info: [String : AnyObject])
        {
            let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
            profileImg.contentMode = .ScaleAspectFill
            **//Fix the image orientation**
             let fixOrientationImage=chosenImage.fixOrientation()
            profileImg.image = fixOrientationImage
    
            dismissViewControllerAnimated(true, completion: nil)
        }
    

    【讨论】:

    • 谢谢,这对我帮助很大。
    • 我有一个 ViewController,我应该把它放在哪里?
    • 更具体地说,我在哪里可以把它放在那里,我需要在哪里调用这个方法?
    • 它的工作。但是我想知道有什么方法可以避免调用CG相关的API,因为这会导致大量的内存分配。只有当我们不再保留 UIImage 时才会释放它。
    • 这在 iOS 10 之前工作正常。在 iOS 11 中执行此操作后,我得到了一个黑色图像作为回报。不过,我做了一个小改动(用 Double.pi 替换了 M_PI)。我正在将 XCode 9 与 Swift 3.2 一起使用。
    【解决方案5】:

    Swift 4.x/5.0 版本@an0 的解决方案:

    extension UIImage {
        func upOrientationImage() -> UIImage? {
            switch imageOrientation {
            case .up:
                return self
            default:
                UIGraphicsBeginImageContextWithOptions(size, false, scale)
                draw(in: CGRect(origin: .zero, size: size))
                let result = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return result
            }
        }
    }
    

    【讨论】:

    • 谢谢你。它的作品完美。最被低估的答案。
    • @VinayakBhor :]
    【解决方案6】:

    迅速;)

    更新 SWIFT 3.0 :D

    func sFunc_imageFixOrientation(img:UIImage) -> UIImage {
    
    
        // No-op if the orientation is already correct
        if (img.imageOrientation == UIImageOrientation.up) {
            return img;
        }
        // We need to calculate the proper transformation to make the image upright.
        // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
        var transform:CGAffineTransform = CGAffineTransform.identity
    
        if (img.imageOrientation == UIImageOrientation.down
            || img.imageOrientation == UIImageOrientation.downMirrored) {
    
            transform = transform.translatedBy(x: img.size.width, y: img.size.height)
            transform = transform.rotated(by: CGFloat(M_PI))
        }
    
        if (img.imageOrientation == UIImageOrientation.left
            || img.imageOrientation == UIImageOrientation.leftMirrored) {
    
            transform = transform.translatedBy(x: img.size.width, y: 0)
            transform = transform.rotated(by: CGFloat(M_PI_2))
        }
    
        if (img.imageOrientation == UIImageOrientation.right
            || img.imageOrientation == UIImageOrientation.rightMirrored) {
    
            transform = transform.translatedBy(x: 0, y: img.size.height);
            transform = transform.rotated(by: CGFloat(-M_PI_2));
        }
    
        if (img.imageOrientation == UIImageOrientation.upMirrored
            || img.imageOrientation == UIImageOrientation.downMirrored) {
    
            transform = transform.translatedBy(x: img.size.width, y: 0)
            transform = transform.scaledBy(x: -1, y: 1)
        }
    
        if (img.imageOrientation == UIImageOrientation.leftMirrored
            || img.imageOrientation == UIImageOrientation.rightMirrored) {
    
            transform = transform.translatedBy(x: img.size.height, y: 0);
            transform = transform.scaledBy(x: -1, y: 1);
        }
    
    
        // Now we draw the underlying CGImage into a new context, applying the transform
        // calculated above.
        let ctx:CGContext = CGContext(data: nil, width: Int(img.size.width), height: Int(img.size.height),
                                      bitsPerComponent: img.cgImage!.bitsPerComponent, bytesPerRow: 0,
                                      space: img.cgImage!.colorSpace!,
                                      bitmapInfo: img.cgImage!.bitmapInfo.rawValue)!
    
        ctx.concatenate(transform)
    
    
        if (img.imageOrientation == UIImageOrientation.left
            || img.imageOrientation == UIImageOrientation.leftMirrored
            || img.imageOrientation == UIImageOrientation.right
            || img.imageOrientation == UIImageOrientation.rightMirrored
            ) {
    
    
            ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.height,height:img.size.width))
    
        } else {
            ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.width,height:img.size.height))
        }
    
    
        // And now we just create a new UIImage from the drawing context
        let cgimg:CGImage = ctx.makeImage()!
        let imgEnd:UIImage = UIImage(cgImage: cgimg)
    
        return imgEnd
    }
    

    【讨论】:

    • 经过数周的努力解决这个问题并尝试了其他几种解决方案,这个解决方案最终完美运行。如果我可以投票+10,我会的。谢谢你。 :)
    • @MetalHeart2003 这种方法极大地增加了我的图像的文件大小,我的图像从 200kb 增加到了 4mb,有什么办法可以阻止这种情况发生吗?
    • @TimWhiting 听起来您是从压缩图像开始的。但是这种方法在没有任何压缩的情况下重绘旋转的图像。之后您可以使用 UIImageJPEGRepresentation() 重新压缩位图图像
    【解决方案7】:

    我在设计我的拍照应用程序时使用了这个页面,我发现以下方法将纠正方向并使用比以前的答案更少的内存和处理器:

    CGImageRef cgRef = image.CGImage;
    image = [[UIImage alloc] initWithCGImage:cgRef scale:1.0 orientation:UIImageOrientationUp];
    

    这基本上只是用新的方向重新包装实际的图像数据。我使用的是@an0 的代码,但它会在内存中生成一个新图像,这可能会对您可能从相机获得的 3264x2448 图像产生负担。

    【讨论】:

    • 我在 iPhone 5s 上使用 iOS 7.1 测试了这个答案,但它不起作用,其中 Windows 机器 [MS-Paint,Win photo Viewer] 和 UIImageView 显示与原始图像呈 90 度方向的图像!请注意,使用默认相机触摸按钮拍摄的图像,而不是提高音量。
    • 似乎这只是改变了方向标志...需要旋转实际位
    【解决方案8】:

    如果您启用编辑,则编辑后的图像(与原始图像相反)将按预期定向:

    UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
    imagePickerController.allowsEditing = YES;
    // set delegate and present controller
    
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
        UIImage *photo = [info valueForKey:UIImagePickerControllerEditedImage];
        // do whatever
    }
    

    启用编辑允许用户在点击“使用照片”之前调整图像大小和移动图像

    【讨论】:

    • 不幸的是,这个解决方案不能水平翻转图像,甚至允许编辑。
    • 有效,但强制用户将图像裁剪为正方形,除非您想添加更多代码以允许可变裁剪尺寸
    【解决方案9】:

    这是我发现的解决方向问题的方法

    UIImage *initialImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    NSData *data = UIImagePNGRepresentation(self.initialImage);
    
    UIImage *tempImage = [UIImage imageWithData:data];
    UIImage *fixedOrientationImage = [UIImage imageWithCGImage:tempImage.CGImage
                                         scale:initialImage.scale
                                   orientation:self.initialImage.imageOrientation];
    initialImage = fixedOrientationImage;
    

    编辑:

    UIImage *initialImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    NSData *data = UIImagePNGRepresentation(self.initialImage);
    
    initialImage = [UIImage imageWithCGImage:[UIImage imageWithData:data].CGImage
                                                         scale:initialImage.scale
                                                   orientation:self.initialImage.imageOrientation];
    

    【讨论】:

    • 图像到 PNG 再到图像之间的转换过多,成本太高。 @an0 答案更好。
    【解决方案10】:

    我通过在下面写几行代码来实现这一点

    extension UIImage {
    
        public func correctlyOrientedImage() -> UIImage {
            guard imageOrientation != .up else { return self }
    
            UIGraphicsBeginImageContextWithOptions(size, false, scale)
            draw(in: CGRect(origin: .zero, size: size))
            let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
    
            return normalizedImage
        }
    }
    

    【讨论】:

      【解决方案11】:

      这是一个不改变原始图像的色彩空间的解决方案。如果您想标准化灰度图像的方向,那么所有基于 UIGraphicsBeginImageContextWithOptions 的解决方案都不走运,因为它会在 RGB 颜色空间中创建上下文。相反,您必须创建一个与原始图像具有相同属性的上下文并进行绘制:

      extension UIImage {
          static let rotatedOrentations: [UIImage.Orientation] = [.left, .leftMirrored, .right, .rightMirrored]
      
          func normalizedImage() -> UIImage {
              if imageOrientation == .up {
                  return self
              }
      
              let image = self.cgImage!
              let swapOrientation = UIImage.rotatedOrentations.contains(imageOrientation)
              let width = swapOrientation ? image.height : image.width
              let height = swapOrientation ? image.width : image.height
              let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: image.bitsPerComponent, bytesPerRow: image.bytesPerRow, space: image.colorSpace!, bitmapInfo: image.bitmapInfo.rawValue)!
              let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height));
              context.concatenate(flipVertical)
              UIGraphicsPushContext(context)
              self.draw(at: .zero)
              UIGraphicsPopContext()
      
              return UIImage(cgImage: context.makeImage()!)
          }
      }
      

      【讨论】:

        【解决方案12】:

        根据Sourabh Sharma 的回答更新 Swift 3.1,并清理代码。

        extension UIImage {
            func fixedOrientation() -> UIImage {
                if imageOrientation == .up { return self }
        
                var transform:CGAffineTransform = .identity
                switch imageOrientation {
                case .down, .downMirrored:
                    transform = transform.translatedBy(x: size.width, y: size.height).rotated(by: .pi)
                case .left, .leftMirrored:
                    transform = transform.translatedBy(x: size.width, y: 0).rotated(by: .pi/2)
                case .right, .rightMirrored:
                    transform = transform.translatedBy(x: 0, y: size.height).rotated(by: -.pi/2)
                default: break
                }
        
                switch imageOrientation {
                case .upMirrored, .downMirrored:
                    transform = transform.translatedBy(x: size.width, y: 0).scaledBy(x: -1, y: 1)
                case .leftMirrored, .rightMirrored:
                    transform = transform.translatedBy(x: size.height, y: 0).scaledBy(x: -1, y: 1)
                default: break
                }
        
                let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height),
                                               bitsPerComponent: cgImage!.bitsPerComponent, bytesPerRow: 0,
                                               space: cgImage!.colorSpace!, bitmapInfo: cgImage!.bitmapInfo.rawValue)!
                ctx.concatenate(transform)
        
                switch imageOrientation {
                case .left, .leftMirrored, .right, .rightMirrored:
                    ctx.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.height,height: size.width))
                default:
                    ctx.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.width,height: size.height))
                }
                return UIImage(cgImage: ctx.makeImage()!)
            }
        }
        

        Picker 委托方法示例:

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
            guard let originalImage = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
            let fixedImage = originalImage.fixedOrientation()
            // do your work
        }
        

        【讨论】:

          【解决方案13】:

          这是 swift 的 UIImage 扩展:

          extension UIImage {
          
              func fixOrientation() -> UIImage {
          
                  // No-op if the orientation is already correct
                  if ( self.imageOrientation == UIImageOrientation.Up ) {
                      return self;
                  }
          
                  // We need to calculate the proper transformation to make the image upright.
                  // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
                  var transform: CGAffineTransform = CGAffineTransformIdentity
          
                  if ( self.imageOrientation == UIImageOrientation.Down || self.imageOrientation == UIImageOrientation.DownMirrored ) {
                      transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
                      transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
                  }
          
                  if ( self.imageOrientation == UIImageOrientation.Left || self.imageOrientation == UIImageOrientation.LeftMirrored ) {
                      transform = CGAffineTransformTranslate(transform, self.size.width, 0)
                      transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
                  }
          
                  if ( self.imageOrientation == UIImageOrientation.Right || self.imageOrientation == UIImageOrientation.RightMirrored ) {
                      transform = CGAffineTransformTranslate(transform, 0, self.size.height);
                      transform = CGAffineTransformRotate(transform,  CGFloat(-M_PI_2));
                  }
          
                  if ( self.imageOrientation == UIImageOrientation.UpMirrored || self.imageOrientation == UIImageOrientation.DownMirrored ) {
                      transform = CGAffineTransformTranslate(transform, self.size.width, 0)
                      transform = CGAffineTransformScale(transform, -1, 1)
                  }
          
                  if ( self.imageOrientation == UIImageOrientation.LeftMirrored || self.imageOrientation == UIImageOrientation.RightMirrored ) {
                      transform = CGAffineTransformTranslate(transform, self.size.height, 0);
                      transform = CGAffineTransformScale(transform, -1, 1);
                  }
          
                  // Now we draw the underlying CGImage into a new context, applying the transform
                  // calculated above.
                  var ctx: CGContextRef = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height),
                      CGImageGetBitsPerComponent(self.CGImage), 0,
                      CGImageGetColorSpace(self.CGImage),
                      CGImageGetBitmapInfo(self.CGImage));
          
                  CGContextConcatCTM(ctx, transform)
          
                  if ( self.imageOrientation == UIImageOrientation.Left ||
                      self.imageOrientation == UIImageOrientation.LeftMirrored ||
                      self.imageOrientation == UIImageOrientation.Right ||
                      self.imageOrientation == UIImageOrientation.RightMirrored ) {
                          CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage)
                  } else {
                      CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage)
                  }
          
                  // And now we just create a new UIImage from the drawing context and return it
                  return UIImage(CGImage: CGBitmapContextCreateImage(ctx))!
              }
          }
          

          基于 MetalHeart2003 的早期作品..

          【讨论】:

            【解决方案14】:

            这是 Swift 2 中的 UIImage 扩展,基于@Anomie 接受的答案。它使用更清晰的开关盒。它还考虑了CGBitmapContextCreateImage() 返回的可选值。

            extension UIImage {
                func rotateImageByOrientation() -> UIImage {
                    // No-op if the orientation is already correct
                    guard self.imageOrientation != .Up else {
                        return self
                    }
            
                    // We need to calculate the proper transformation to make the image upright.
                    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
                    var transform = CGAffineTransformIdentity;
            
                    switch (self.imageOrientation) {
                    case .Down, .DownMirrored:
                        transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
                        transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
            
                    case .Left, .LeftMirrored:
                        transform = CGAffineTransformTranslate(transform, self.size.width, 0)
                        transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
            
                    case .Right, .RightMirrored:
                        transform = CGAffineTransformTranslate(transform, 0, self.size.height)
                        transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
            
                    default:
                        break
                    }
            
                    switch (self.imageOrientation) {
                    case .UpMirrored, .DownMirrored:
                        transform = CGAffineTransformTranslate(transform, self.size.width, 0)
                        transform = CGAffineTransformScale(transform, -1, 1)
            
                    case .LeftMirrored, .RightMirrored:
                        transform = CGAffineTransformTranslate(transform, self.size.height, 0)
                        transform = CGAffineTransformScale(transform, -1, 1)
            
                    default:
                        break
                    }
            
                    // Now we draw the underlying CGImage into a new context, applying the transform
                    // calculated above.
                    let ctx = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height),
                        CGImageGetBitsPerComponent(self.CGImage), 0,
                        CGImageGetColorSpace(self.CGImage),
                        CGImageGetBitmapInfo(self.CGImage).rawValue)
                    CGContextConcatCTM(ctx, transform)
                    switch (self.imageOrientation) {
                    case .Left, .LeftMirrored, .Right, .RightMirrored:
                        CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage)
            
                    default:
                        CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage)
                    }
            
                    // And now we just create a new UIImage from the drawing context
                    if let cgImage = CGBitmapContextCreateImage(ctx) {
                        return UIImage(CGImage: cgImage)
                    } else {
                        return self
                    }
                }
            }
            

            【讨论】:

              【解决方案15】:

              我在使用从相机拍摄的图像或保存在相机胶卷中的图像时遇到了这个问题,这些图像是从相机拍摄的。从 safari 浏览器下载到照片库中的图片在上传时不会旋转。

              我可以通过在上传之前将图像数据设为 JPEG 来解决这个问题。

              let image = info[UIImagePickerControllerOriginalImage] as! UIImage        
              let data = UIImageJPEGRepresentation(image, 1.0)
              

              我们现在可以使用数据进行上传,上传后图像不会旋转。

              希望这会奏效。

              【讨论】:

              • 很奇怪,png数据保持旋转,但使用jpeg数据时旋转得到固定。
              【解决方案16】:

              如果我理解,您想要做的是忽略 UIImage 的方向?如果是这样,那么您可以这样做:-

              //image is your original image
              image = [UIImage imageWithCGImage:[image CGImage]
                                           scale:[image scale]
                                     orientation: UIImageOrientationUp];
              

              或在 Swift 中:-

              image = UIImage(CGImage: image.CGImage!, scale: image.scale, orientation:.Up)
              

              它解决了我的裁剪问题..希望,这就是你要找的..

              【讨论】:

                【解决方案17】:

                基于 @jake1981 的 Swift 3 版本,该版本取自 @MetalHeart2003

                extension UIImage {
                
                    func fixOrientation() -> UIImage {
                
                        // No-op if the orientation is already correct
                        if ( self.imageOrientation == UIImageOrientation.up ) {
                            return self;
                        }
                
                        // We need to calculate the proper transformation to make the image upright.
                        // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
                
                        var transform: CGAffineTransform = CGAffineTransform.identity
                
                        if ( self.imageOrientation == UIImageOrientation.down || self.imageOrientation == UIImageOrientation.downMirrored ) {
                            transform = transform.translatedBy(x: self.size.width, y: self.size.height)
                            transform = transform.rotated(by: CGFloat(M_PI))
                        }
                
                        if ( self.imageOrientation == UIImageOrientation.left || self.imageOrientation == UIImageOrientation.leftMirrored ) {
                            transform = transform.translatedBy(x: self.size.width, y: 0)
                            transform = transform.rotated(by: CGFloat(M_PI_2))
                        }
                
                        if ( self.imageOrientation == UIImageOrientation.right || self.imageOrientation == UIImageOrientation.rightMirrored ) {
                            transform = transform.translatedBy(x: 0, y: self.size.height);
                            transform = transform.rotated(by: CGFloat(-M_PI_2));
                        }
                
                        if ( self.imageOrientation == UIImageOrientation.upMirrored || self.imageOrientation == UIImageOrientation.downMirrored ) {
                            transform = transform.translatedBy(x: self.size.width, y: 0)
                            transform = transform.scaledBy(x: -1, y: 1)
                        }
                
                        if ( self.imageOrientation == UIImageOrientation.leftMirrored || self.imageOrientation == UIImageOrientation.rightMirrored ) {
                            transform = transform.translatedBy(x: self.size.height, y: 0);
                            transform = transform.scaledBy(x: -1, y: 1);
                        }
                
                        // Now we draw the underlying CGImage into a new context, applying the transform
                        // calculated above.
                        let ctx: CGContext = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height),
                                                       bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0,
                                                       space: self.cgImage!.colorSpace!,
                                                       bitmapInfo: self.cgImage!.bitmapInfo.rawValue)!
                        ctx.concatenate(transform)
                
                        if ( self.imageOrientation == UIImageOrientation.left ||
                            self.imageOrientation == UIImageOrientation.leftMirrored ||
                            self.imageOrientation == UIImageOrientation.right ||
                            self.imageOrientation == UIImageOrientation.rightMirrored ) {
                
                            ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: self.size.height, height: self.size.width))
                        } else {
                            ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
                        }
                
                        // And now we just create a new UIImage from the drawing context and return it
                        return UIImage(cgImage: ctx.makeImage()!)
                
                    }
                }
                

                【讨论】:

                  【解决方案18】:
                  @an0, thanks for the answer!
                  The only thing is autoreleasepool: 
                  
                  func fixOrientation(img: UIImage) -> UIImage? {
                  
                      let result: UIImage?
                      if img.imageOrientation == .up {
                          result = img
                      } else {
                  
                          result = autoreleasepool { () -> UIImage? in
                              UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale)
                              let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
                              img.draw(in: rect)
                  
                              let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()
                              UIGraphicsEndImageContext()
                  
                              return normalizedImage
                          }
                      }
                  
                      return result
                  }
                  

                  【讨论】:

                    【解决方案19】:

                    这是用于自动修复图像方向的 Swift-4.2 代码 返回 UIImage

                    func AutofixImageOrientation(_ image: UIImage)->UIImage {
                    
                        UIGraphicsBeginImageContext(image.size)
                    
                        image.draw(at: .zero)
                    
                        let newImage = UIGraphicsGetImageFromCurrentImageContext()
                    
                        UIGraphicsEndImageContext()
                    
                        return newImage ?? image
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      我将其转换为 Xamarin:

                      private static UIImage FixImageOrientation(UIImage image)
                          {
                              if (image.Orientation == UIImageOrientation.Up)
                              {
                                  return image;
                              }
                      
                              var transform = CGAffineTransform.MakeIdentity();
                      
                              float pi = (float)Math.PI;
                      
                              switch (image.Orientation)
                              {
                                  case UIImageOrientation.Down:
                                  case UIImageOrientation.DownMirrored:
                                      transform = CGAffineTransform.Translate(transform, image.Size.Width, image.Size.Height);
                                      transform = CGAffineTransform.Rotate(transform, pi);
                                      break;
                      
                                  case UIImageOrientation.Left:
                                  case UIImageOrientation.LeftMirrored:
                                      transform = CGAffineTransform.Translate(transform, image.Size.Width, 0);
                                      transform = CGAffineTransform.Rotate(transform, pi / 2);
                                      break;
                      
                                  case UIImageOrientation.Right:
                                  case UIImageOrientation.RightMirrored:
                                      transform = CGAffineTransform.Translate(transform, 0, image.Size.Height);
                                      transform = CGAffineTransform.Rotate(transform, -(pi / 2));
                                      break;
                              }
                      
                              switch (image.Orientation)
                              {
                                  case UIImageOrientation.UpMirrored:
                                  case UIImageOrientation.DownMirrored:
                                      transform = CGAffineTransform.Translate(transform, image.Size.Width, 0);
                                      transform = CGAffineTransform.Scale(transform, -1, 1);
                                      break;
                      
                                  case UIImageOrientation.LeftMirrored:
                                  case UIImageOrientation.RightMirrored:
                                      transform = CGAffineTransform.Translate(transform, image.Size.Height, 0);
                                      transform = CGAffineTransform.Scale(transform, -1, 1);
                                      break;
                              }
                      
                              var ctx = new CGBitmapContext(null, (nint)image.Size.Width, (nint)image.Size.Height, image.CGImage.BitsPerComponent,
                                  image.CGImage.BytesPerRow, image.CGImage.ColorSpace, image.CGImage.BitmapInfo);
                      
                              ctx.ConcatCTM(transform);
                      
                              switch (image.Orientation)
                              {
                                  case UIImageOrientation.Left:
                                  case UIImageOrientation.LeftMirrored:
                                  case UIImageOrientation.Right:
                                  case UIImageOrientation.RightMirrored:
                                      ctx.DrawImage(new CGRect(0, 0, image.Size.Height, image.Size.Width), image.CGImage);
                                      break;
                      
                                  default:
                                      ctx.DrawImage(new CGRect(0, 0, image.Size.Width, image.Size.Height), image.CGImage);
                                      break;
                              }
                      
                              var cgimg = ctx.ToImage();
                              var img = new UIImage(cgimg);
                      
                              ctx.Dispose();
                              ctx = null;
                              cgimg.Dispose();
                              cgimg = null;
                      
                              return img;
                          }
                      

                      【讨论】:

                        猜你喜欢
                        • 2013-11-26
                        • 2011-04-13
                        • 2014-04-14
                        • 1970-01-01
                        • 1970-01-01
                        • 2012-03-10
                        • 2011-06-26
                        相关资源
                        最近更新 更多