从 CIImage 创建的 UIImage 创建的 JPG 3x 太大

JPG created from UIImage created from CIImage 3x too large

我有一堆 CIFilter 最终将大图像(从 iPhone 相机)缩放和裁剪为 1080x1920 CIImage

然后我想将图像保存为 JPG:

var outputFilter: CIFilter?
...
if let ciImage = outputFilter?.outputImage {
    let outputImage = UIImage(ciImage: ciImage)
    let data = outputImage?.jpegData(compressionQuality: 0.8)
    ...
}

ciImage.extent是1080x1920,outputImage.size也是1080x1920,outputImage.scale是1.0。

但是保存到磁盘的图像是原来的 3 倍大:3240x5760。

我错过了什么?

这将return 一个基于您的屏幕比例的图像。如果您检查屏幕比例,结果将是 3 倍。您需要用屏幕比例初始化您的 uiimage:

let outputImage = UIImage(ciImage: ciImage, scale: UIScreen.main.scale, orientation: .up)

要渲染图像,您可以使用 UIGraphicsImageRenderer:

extension CIImage {
    var rendered: UIImage {
        let cgImage = CIContext(options: nil).createCGImage(self, from: extent)!
        let size = extent.size
        let format = UIGraphicsImageRendererFormat.default()
        format.opaque = false
        return UIGraphicsImageRenderer(size: size, format: format).image { ctx in
            var transform = CGAffineTransform(scaleX: 1, y: -1)
            transform = transform.translatedBy(x: 0, y: -size.height)
            ctx.cgContext.concatenate(transform)
            ctx.cgContext.draw(cgImage, in: CGRect(origin: .zero, size: size))
        }
    }
}

我需要执行以下操作以获得正确的大小并避免渲染不佳(如 中所述)。

private func renderImage(ciImage: CIImage) -> UIImage?
{
    var outputImage: UIImage?

    UIGraphicsBeginImageContext(CGSize(width: 1080, height: 1920))
    if let context = UIGraphicsGetCurrentContext()
    {
        context.interpolationQuality = .high
        context.setShouldAntialias(true)

        let inputImage = UIImage(ciImage: ciImage)
        inputImage.draw(in: CGRect(x: 0, y: 0, width: 1080, height: 1920))

        outputImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()
    }

    return outputImage
}