6

我正在努力在 iOS 10 中添加对广色域照片的支持。当用户从相机拍摄照片时,我需要使用支持新色彩空间的新 API 来保存照片数据 - UIGraphicsImageRenderer'sjpegData而不是UIImageJPEGRepresentation.

我在图像方向上遇到了一些麻烦。在我的 iPad 上以纵向拍摄照片,图像未正确绘制。请参阅以下评论:

旧 API:

let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageData = UIImageJPEGRepresentation(image, 1)

新 API:

let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let cgImage = image.cgImage!
let ciImage = CIImage(cgImage: cgImage)

let format = UIGraphicsImageRendererFormat()
format.scale = 1
format.prefersExtendedRange = true

let renderer = UIGraphicsImageRenderer(bounds: ciImage.extent, format: format)
let imageData = renderer.jpegData(withCompressionQuality: 1, actions: { context in
    context.cgContext.draw(cgImage, in: ciImage.extent) //draws flipped horizontally
    //image.draw(at: .zero) //draws rotated 90 degrees leaving black at bottom
    //image.draw(in: ciImage.extent) //draws rotated 90 degrees stretching and compressing the image to fill the rect 
 })

UIImageJPEGRepresentationUIGraphicsImageRenderer's替换的正确方法是jpegData什么?

4

2 回答 2

3

UIImage根据相机旋转可以有不同的方向。您可以根据该方向动态解析需要应用于图像的转换,如下所示:

let renderer = UIGraphicsImageRenderer(size: image.size, format: format)
let imageData = renderer.jpegData(withCompressionQuality: 1, actions: { context in
    var workSize = image.size;
    workSize.width = floor(workSize.width / image.scale)
    workSize.height = floor(workSize.height / image.scale)
    // No-op if the orientation is already correct
    // if image.imageOrientation == .up { draw image }

    // 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: workSize.width, y: workSize.height)
            transform = transform.rotated(by: CGFloat(Double.pi))
            break

        case .left, .leftMirrored:
            transform = transform.translatedBy(x: workSize.width, y: 0.0)
            transform = transform.rotated(by: CGFloat(Double.pi / 2.0))
            break

        case .right, .rightMirrored:
            transform = transform.translatedBy(x: 0.0, y: workSize.height)
            transform = transform.rotated(by: CGFloat(-Double.pi / 2.0))
            break

        case .up, .upMirrored:
            break
    }

    switch image.imageOrientation
    {
        case .upMirrored, .downMirrored:
            transform = transform.translatedBy(x: workSize.width, y: 0.0)
            transform = transform.scaledBy(x: -1.0, y: 1.0)
            break

        case .leftMirrored, .rightMirrored:
            transform = transform.translatedBy(x: workSize.height, y: 0.0);
            transform = transform.scaledBy(x: -1.0, y: 1.0);
            break

        case .up, .down, .left, .right:
            break
    }

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

    let ctx = context.cgContext

    ctx.concatenate(transform)

    switch image.imageOrientation {
        case .left, .leftMirrored, .right, .rightMirrored:
            ctx.draw(image.cgImage!, in: CGRect(x: 0.0, y:0.0, width: workSize.height, height: workSize.width))
            break;

        default:
            ctx.draw(image.cgImage!, in: CGRect(origin: .zero, size: workSize))
            break;
    } 
 })

基于UIImage+fixOrientation的回答

于 2017-06-21T22:05:02.863 回答
0

image.draw()方法应自动为您更正方向:

此方法在当前图形上下文中绘制整个图像,尊重图像的方向设置。在默认坐标系中,图像位于指定矩形原点的右下方。但是,此方法尊重应用于当前图形上下文的任何变换。

我不确定你为什么需要使用ci.extent. 这extent似乎是(我不声称自己是核心图像 API 方面的专家)“原始”图像数据的尺寸,它在没有任何图像方向校正的情况下存储。如果您的原始数据需要旋转(非向上方向,如Left, Right),范围仍将是存储数据的原始矩形。

我将以下代码用于图像,imageOrientation.rawValue = 3并且在重新加载时,我的数据在正确的尺寸下非常好,并且“已纠正” imageOrientation.rawValue = 0

let imageSize = image.Size
let renderer = UIGraphicsImageRenderer(size: renderedSize, format: UIGraphicsImageRendererFormat())
return renderer.jpegData(withCompressionQuality: 0.95) { (rendererContext) in
    let rect = CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height)
    image.draw(in: rect)
}

考虑到图像方向,我的输入图像使用我的代码正确“呈现”其数据。在右边,我使用draw(in: extent). 图像没有旋转。只是伸了个懒腰。

在此处输入图像描述

于 2018-01-21T04:44:25.740 回答