用相机拍照将asset.fullScreenImage旋转90度?

Posted

技术标签:

【中文标题】用相机拍照将asset.fullScreenImage旋转90度?【英文标题】:Taking pictures with camera rotates asset.fullScreenImage 90 degrees? 【发布时间】:2015-08-29 07:52:15 【问题描述】:

我有一个用户从他们的相机胶卷中挑选一张图片进行裁剪。我将所有这些图片显示为缩略图供用户按下。

我使用UIImage(CGImage: asset.fullScreenImage!.CGImage!, scale: scale, orientation: UIImageOrientation.Up) 来确保我的图像在缩略图中保持不变。使用 asset.fullResolutionImage! 这不起作用。

现在是奇怪的部分。当我用 iPhone 相机拍照时,然后前往我的裁剪视图控制器,图像旋转了 90 度!我不知道为什么。

如果我离开我的应用,用相机正常拍照,保存到我的相机胶卷,然后像我做其他照片一样从缩略图列表中选择它,它工作得很好。

这是什么原因?如何解决?

编辑:下面发布了两种解决方案。一个是 Objective-C,另一个是翻译成 Swift 的副本。

【问题讨论】:

【参考方案1】:

你可以尝试使用这个分类:

UIImage+FixOrientation.h

UIImage+FixOrientation.m

它是用Objective-C构建的,那么你可以使用bridging header来结合ObjCSwift,或者你可以看看了解如何解决这个问题。

使用示例:

UIImage *image = <image from camera image>
image = [image fixOrientation];

【讨论】:

嗯,解决了它,但为什么会发生这种情况?这是ios 8的错误吗?此解决方案是否适用于 iOS 4-7 等?另外,也许这只是我的眼睛,但看起来我最后得到的图像,虽然方向正确,但质量略低。 不,这不是一个真正的问题。当你拍照时,它需要设备方向(这就是我的想法,不是 100% 确定它是正确的),所以这是修复我从 iOS 6 开始使用的那个的解决方案。嗯,质量不应该像他们那样低不缩放,只旋转。 是的,我拍了更多照片,我很确定我的眼睛在欺骗我:P。好的。万分感谢!那么从 iOS 6 开始就一直在发生这种情况? 可能在 iOS 6 之前就已经发生了。正如我在 *** 中看到的那样,人们从 2011 年开始就面临着这个问题。我认为这是非常罕见的问题。这甚至都不是问题,这只是相机的工作原理。 :) 顺便说一句,我发布了另一个答案,基本上是你的代码,但在 Swift 中。随意看看。【参考方案2】:

这个答案是对gontovnik的回答的补充。

我采用了他的 Objective-C 解决方案并用 Swift 编写。将此功能放在需要的地方。只需传入有问题的 UIImage。

也就是说,您可以将其设为 UIImage 类函数。打电话给UIImage.fixOrientation(image: imageInQuestion)真的会很好。

func fixOrientation(image: UIImage) -> UIImage 
    // No-op if the orientation is already correct
    if (image.imageOrientation == UIImageOrientation.Up)  return image; 

    println(image.imageOrientation)

    // 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 (image.imageOrientation) 
        case .Down, .DownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
            break
        case .Left, .LeftMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
            break        
        case .Right, .RightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, image.size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
            break            
        case .Up, .UpMirrored:
                break
    

    switch (image.imageOrientation) 
        case .UpMirrored, .DownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0)
            transform = CGAffineTransformScale(transform, -1, 1)
            break       
        case .LeftMirrored, .RightMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.height, 0)
            transform = CGAffineTransformScale(transform, -1, 1)
            break
        case .Up, .Down, .Left, .Right:
            break
    

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.

    var ctx = CGBitmapContextCreate(nil, Int(image.size.width), Int(image.size.height), CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage))

    CGContextConcatCTM(ctx, transform);

    switch (image.imageOrientation) 
        case .Left, .LeftMirrored, .Right, .RightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.height, image.size.width), image.CGImage)
            break

        default:
            CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage)
            break
    

    // And now we just create a new UIImage from the drawing context
        var cgimg = CGBitmapContextCreateImage(ctx)
        var img = UIImage(CGImage: cgimg)

        return img!

【讨论】:

我唯一推荐的就是将它设为 UIImage extension 而不是函数。 是的,我同意。写在上面的代码 sn-p :)【参考方案3】:

Swift 3 版本

func fixOrientation(image: UIImage) -> UIImage 
    // No-op if the orientation is already correct
    if (image.imageOrientation == UIImageOrientation.up)  return image; 

    print(image.imageOrientation)

    // 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.identity

    switch (image.imageOrientation) 
    case .down, .downMirrored:
      transform = transform.translatedBy(x: image.size.width, y: image.size.height)
      transform = transform.rotated(by: CGFloat(M_PI))
      break
    case .left, .leftMirrored:
      transform = transform.translatedBy(x: image.size.width, y: 0)
      transform = transform.rotated(by: CGFloat(M_PI_2))
      break
    case .right, .rightMirrored:
      transform = transform.translatedBy(x: 0, y: image.size.height)
      transform = transform.rotated(by: CGFloat(-M_PI_2))
      break
    case .up, .upMirrored:
      break
    

    switch (image.imageOrientation) 
    case .upMirrored, .downMirrored:
      transform = transform.translatedBy(x: image.size.width, y: 0)
      transform = transform.scaledBy(x: -1, y: 1)
      break
    case .leftMirrored, .rightMirrored:
      transform = transform.translatedBy(x: image.size.height, y: 0)
      transform = transform.scaledBy(x: -1, y: 1)
      break
    case .up, .down, .left, .right:
      break
    

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.

    let ctx = CGContext(data: nil, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: image.cgImage!.bitsPerComponent, bytesPerRow: 0, space: image.cgImage!.colorSpace!, bitmapInfo: image.cgImage!.bitmapInfo.rawValue)

    ctx!.concatenate(transform);

    switch (image.imageOrientation) 
    case .left, .leftMirrored, .right, .rightMirrored:
      // Grr...
      ctx?.draw(image.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: image.size.height, height: image.size.width)))

      break

    default:
      ctx?.draw(image.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: image.size.width, height: image.size.height)))
      break
    

    // And now we just create a new UIImage from the drawing context
    let cgimg = ctx!.makeImage()
    let img = UIImage(cgImage: cgimg!)

    return img
  

【讨论】:

以上是关于用相机拍照将asset.fullScreenImage旋转90度?的主要内容,如果未能解决你的问题,请参考以下文章

用/相机意图拍照并在imageView和textView中显示?

用世博相机拍照

用AVFoundation自定义相机拍照

用相机拍照并获取图片路径android

苹果7plus相机和美颜相机拍照正常,但微信拍照拍好后变成横的照片怎么回事?

用相机意图拍照以肖像模式android旋转图片