ios - 如何将 CIImage 保存到 Photos 并保持其 P3 色彩空间完好无损?

标签 ios avfoundation jpeg core-image ciimage

我正在构建一个相机应用程序,它可以捕获 BGRA 格式的照片,并在将其保存到照片应用程序之前对其应用核心图像滤镜。在 iPhone 7 Plus 上,输入照片采用 Display P3 色彩空间,但输出采用 sRGB 色彩空间:

enter image description here

如何防止这种情况发生?

这是我的代码:

let sampleBuffer: CMSampleBuffer = ...
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let metadata = CMCopyDictionaryOfAttachments(nil, self, kCMAttachmentMode_ShouldPropagate)!
let ciImage = CIImage(cvImageBuffer: pixelBuffer,
                      options:[kCIImageProperties: metadata])
NSLog("\(ciImage.colorSpace)")

let context = CIContext()
let data = context.jpegRepresentation(of: ciImage,
                                      colorSpace: ciImage.colorSpace!,
                                      options: [:])!
// Save this using PHPhotoLibrary.

打印:

Optional(<CGColorSpace 0x1c40a8a60> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Display P3))

(在我的实际代码中,我对 CIImage 应用了一个过滤器,这会创建另一个 CIImage,我将其保存。但即使使用原始 CIImage,我也可以重现此问题,因此我消除了过滤器。)

如何将 Core Image 滤镜应用于 P3 图像并将其保存为 P3 图像,而不是 sRGB?

<小时/>

注释:

(1) 这是在运行 iOS 11 的 iPhone 7 Plus 上。

(2) 我使用的是广角摄像头,而不是长焦摄像头、双摄像头或前置摄像头。

(3) 如果我要求 AVFoundation 提供 JPEG 编码的图像而不是 BGRA,并在不涉及 Core Image 的情况下保存它,则不会出现此问题 — 颜色空间不会缩减为 sRGB。

(4) 我尝试使用 kCIImageColorSpace,但没有什么区别:

let p3 = CGColorSpace(name: CGColorSpace.displayP3)!
let ciImage = CIImage(
    cvImageBuffer: pixelBuffer,
    options:[kCIImageProperties: metadata,
             kCIImageColorSpace: p3])

(5) 除了上述之外,我还尝试使用 kCIContextOutputColorSpace 作为创建 CIContext 时的参数,但它再次没有任何区别。

(6) 获取数据并将其保存到 PHPhotoLibrary 的代码不是问题,因为它适用于上面的情况 (2)。

let context = CIContext(options: [kCIContextOutputColorSpace: CGColorSpace.p3])

如何将 Core Image 滤镜应用于 P3 图像并将其保存为 P3 图像,而不是 sRGB?

最佳答案

我遇到了同样的问题,我认为这可能是 context.jpegRepresentation(..) 的错误。

我使用 ImageIO 创建 JPEG 数据取得了更大的成功,如下面的 createJPEGData 函数所示。例如:

let eaglContext = EAGLContext(api: .openGLES2)
let options = [kCIContextWorkingColorSpace: CGColorSpace(name: CGColorSpace.extendedSRGB)!, 
               kCIContextOutputPremultiplied: true, 
               kCIContextUseSoftwareRenderer: false] as [String : Any]

let ciContext = CIContext(eaglContext: eaglContext, options: options)

let colorSpace = CGColorSpace(name: CGColorSpace.displayP3)!
guard let imageData = createJPEGData(from: image, 
                                     jpegQuality: 0.9,                           
                                     outputColorSpace: colorSpace,
                                     context: ciContext) else {
      return
}

PHPhotoLibrary.shared().performChanges({ () -> Void in
    let creationRequest = PHAssetCreationRequest.forAsset()
    creationRequest.addResource(with: .photo,
                                data: imageData,
                                options: nil)
}, completionHandler: { (success: Bool, error : Error?) -> Void in
    // handle errors, etc
})


func createJPEGData(from image: CIImage,
                    jpegQuality: Float,
                    outputColorSpace: CGColorSpace,
                    context: CIContext) -> Data? {

    let jpegData: CFMutableData =  CFDataCreateMutable(nil, 0)

    if let destination = CGImageDestinationCreateWithData(jpegData, kUTTypeJPEG, 1, nil) {
        if let cgImage = context.createCGImage(image,
                                               from: image.extent,
                                               format: kCIFormatRGBA8,
                                               colorSpace: outputColorSpace) {
            CGImageDestinationAddImage(destination, cgImage, image.properties as CFDictionary?)
            if CGImageDestinationFinalize(destination) {
                return jpegData as Data
            }
        }
    }
}

关于ios - 如何将 CIImage 保存到 Photos 并保持其 P3 色彩空间完好无损?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47200791/

相关文章:

ios - iOS 中谷歌翻译 API 的文本解码问题

ios - 从 iOS 应用程序在 youtube 上上传视频?

python - 通过 Picasa API 上传图片时如何防止 JPEG 压缩?

c - 使用 C 查找 JPG/JPEG 图像的高度和宽度

ios - ImageView 动画时的持续时间被忽略

iphone - 路由音频输入以从 iPhone 上的 TOP 麦克风接收

swift avfoundation AVCapturePhotoCaptureDelegate 捕获方法

swift2 - iOS CVPixelBufferCreate在swift 2中泄漏内存

node.js - 在发送到 Node.js 服务器的请求正文中提取二进制数据(jpeg 图像)

ios - 如何在用户看到 ios View 之前加载数据?