ios `kCMPhotoError_UnsupportedPixelFormat`使用`ImageRenderer`创建的图片时

xvw2m8pv  于 2023-05-08  发布在  iOS
关注(0)|答案(1)|浏览(123)

我使用ImageRenderer将SwiftUI视图渲染到UIImage。我能够使用pngData()成功地渲染PNG。但是如果我调用jpegData(),我会得到以下错误:
writeImageAtIndex:867:***CMPphotoCompressionSessionAddImage:err = kCMPhotoError_UnsupportedPixelFormat [-16995](编解码器:'jpeg')
如果我将UIImage示例发送到UIActivityViewController并选择Messages(并且Messages不会在其UI中显示图像),我会在日志中收到相同的错误。如果我选择“邮件”,它会使进程崩溃
-[MFMailComposeInternalViewController addAttachmentData:mimeType:fileName:]附件不能为nil。
问题似乎是渲染图像与JPEG编码器不兼容。但是,如果我使用AirDrop共享此图像,它会发送带有perfectly-normal-seeming attributes的jpeg文件。
我还尝试渲染到CGImage并从中创建UIImage,我得到了相同的结果。

mf98qq94

mf98qq941#

这似乎是特定于在模拟器中的实际设备上运行的,我无法重现该问题。
“不支持的像素格式”的原因原来是渲染图像中的24位颜色深度,也可能是alpha层的存在。jpeg编码器需要8位色深,没有透明度(尽管我希望UIImage实现自动转换色深)。
以下代码将颜色深度转换为8位:

extension View {
    @MainActor func uiImageSnapshot() -> UIImage? {
        let renderer = ImageRenderer(content: self)

        // jpeg encoder requires that the image not have an alpha layer
        renderer.isOpaque = true

        guard let image = renderer.uiImage else { return nil }

        // jpeg encoder requires an 8-bit color depth (including the encoder used in Mail, Messages, etc.)
        return image.convertedToColorDepth(8)
    }
}

extension UIImage {
    func convertedToColorDepth(_ colorDepth: Int) -> UIImage? {
        guard let cgImage else {
            return nil
        }

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)

        guard let context = CGContext(data: nil, width: cgImage.width, height: cgImage.height, bitsPerComponent: colorDepth, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) else {
            return nil
        }

        let rect = CGRect(x: 0, y: 0, width: cgImage.width, height: cgImage.height)
        context.draw(cgImage, in: rect)

        guard let newCGImage = context.makeImage() else {
            return nil
        }

        return UIImage(cgImage: newCGImage)
    }
}

相关问题