【问题标题】:Pixel colors change as I save MTLTexture to CGImage?当我将 MTLTexture 保存到 CGImage 时,像素颜色会发生变化?
【发布时间】:2018-09-17 16:12:29
【问题描述】:

我需要将金属纹理保存并加载到文件中。下面的示例代码如下。我注意到 RGB 值在保存和重新加载时发生了变化。

metal texture pixel: RGBA: 42,79,12,95  
after save and reload:     66,88,37,95

那变得更亮更灰了。下次保存它开始变暗。我在 iPad Pro 上,所以想知道这是否是色彩空间问题。关于为什么会发生这种情况以及如何解决它的任何指示?

在下面保存cgImage 的行中,我可以检查原始像素数据并看到RGBA 为66、88、37。

// saving...
let ciCtx = CIContext()
let ciImage = CIImage(mtlTexture: metalTexture, options: [:])
// [ … transfrom to flip y-coordinate …]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let cgImage = ciCtx.createCGImage(ciImage, from: fullRect, format: kCIFormatRGBA8, colorSpace: colorSpace)!
let imageDest = CGImageDestinationCreateWithData(mData, kUTTypePNG, 1, nil)!
CGImageDestinationAddImage(imageDest, cgImage, nil)
CGImageDestinationFinalize(imageDest)

// loading...
let src = CGImageSourceCreateWithData(imgData, nil)
let img = CGImageSourceCreateImageAtIndex(src, 0, nil)
let loader = MTKTextureLoader(device: self.metalDevice)
let texture = try! loader.newTexture(cgImage: img, options: [:])

【问题讨论】:

  • 一般来说,PNG 数据是以 sRGB 编码存储的,但您告诉 Core Image 将纹理数据视为在设备的颜色空间中,这可能是 Display P3(您可以通过打印colorspace 来确定这一点)。无论如何,设备色彩空间很少是您想要的。将 sRGB 颜色空间 (CGColorSpace(name: CGColorSpace.sRGB)) 提供给 CI 可能是有意义的。当纹理加载器加载图像时,它应该推断出图像数据是 sRGB,你应该会看到更好的结果。
  • 当我打印 colorSpace 对象时,它给出:<CGColorSpace 0x1c40af360> (kCGColorSpaceDeviceRGB),这似乎不是 Display P3。我刚刚尝试使用 .sRGB 和 .displayP3 来创建该色彩空间,并且在我保存和重新加载时都会导致颜色发生变化。必须有办法保存像素图并取回相同的 RGB 值。

标签: ios ios11 metal cgimage color-space


【解决方案1】:

我遇到了一个非常相似的问题。我认为如果您将一些选项传递给 CIImage() 而不是不进行颜色空间管理,即“选项:[:]”,您将摆脱颜色偏移问题。

let kciOptions = [kCIImageColorSpace: CGColorSpaceCreateDeviceRGB(),
                      kCIContextOutputPremultiplied: true,
                      kCIContextUseSoftwareRenderer: false] as [String : Any]
let ciImage = CIImage(mtlTexture: metalTexture, options: kciOptions)

当我遇到this 问题时,上述方法对我有用。

【讨论】:

  • 谢谢@Plutovman!你碰巧知道 Objective C 代码中的等价物吗? NSDictionary 对象不会接受 CGColorSpaceRef 作为值。
  • 很遗憾我没有,因为我的 Objective-C 知识非常少。我相信你很快就会找到自己的路。最好的。
  • 目标 c 使用:@{kCIImageColorSpace:(__bridge_transfer id)CGColorSpaceCreateDeviceRGB()}
猜你喜欢
  • 1970-01-01
  • 2022-08-21
  • 2012-06-13
  • 2020-10-10
  • 1970-01-01
  • 2019-12-04
  • 2014-07-22
  • 2014-09-04
  • 1970-01-01
相关资源
最近更新 更多