用UIGraphicsImageRenderer的jpegData替换UIImageJPEGRepresentation

Jor*_*n H 6 uikit cgcontext ios cgcontextdrawimage

我正在努力当用户需要从相机中的照片添加宽彩色照片在iOS的10支持,我需要使用支持新的色彩空间来保存照片数据的新API - UIGraphicsImageRendererjpegData替代UIImageJPEGRepresentation.

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

旧API:

let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageData = UIImageJPEGRepresentation(image, 1)
Run Code Online (Sandbox Code Playgroud)

新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 
 })
Run Code Online (Sandbox Code Playgroud)

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

Eug*_*nyk 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;
    } 
 })
Run Code Online (Sandbox Code Playgroud)

基于UIImage+fixOrientation的答案