J.D*_*Doe 5 nsview ios swift metal
我正在尝试使用MTKTextureLoader加载CGImage作为纹理。这是原始图片
但是,当我将该CGImage转换为MTLTexture并将该纹理转换回CGImage时,它看起来很可怕,如下所示:
这是代码中正在发生的事情。
图像作为CGImage加载(我已经检查过了,该图像确实具有完整的视觉质量)
我有一个功能view(),可以通过在CALayer中使用它来查看NSImage,如下所示:
func view() {
.....
imageView!.layer = CALayer()
imageView!.layer!.contentsGravity = kCAGravityResizeAspectFill
imageView!.layer!.contents = img
imageView!.wantsLayer = true
Run Code Online (Sandbox Code Playgroud)
所以我做了以下
let cg = CoolImage()
let ns = NSImage(cgImage: cg, size: Size(width: cg.width, height: cg.height))
view(image: ns)
Run Code Online (Sandbox Code Playgroud)
并检查是否足够具有完整的视觉保真度。
因此,我将cg图像加载到MTLTexture中,如下所示
let textureLoader = MTKTextureLoader(device: metalState.sharedDevice!)
let options = [
MTKTextureLoader.Option.textureUsage: NSNumber(value: MTLTextureUsage.shaderRead.rawValue | MTLTextureUsage.shaderWrite.rawValue | MTLTextureUsage.renderTarget.rawValue),
MTKTextureLoader.Option.SRGB: false
]
return ensure(try textureLoader.newTexture(cgImage: cg, options: options))
Run Code Online (Sandbox Code Playgroud)
然后,我将MTLTexture转换回UIImage,如下所示:
let texture = self
let width = texture.width
let height = texture.height
let bytesPerRow = width * 4
let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)
defer {
data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)
}
let region = MTLRegionMake2D(0, 0, width, height)
texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)
var buffer = vImage_Buffer(data: data, height: UInt(height), width: UInt(width), rowBytes: bytesPerRow)
var map: [UInt8] = [0, 1, 2, 3]
if (pixelFormat == .bgra8Unorm) {
map = [2, 1, 0, 3]
}
vImagePermuteChannels_ARGB8888(&buffer, &buffer, map, 0)
guard let colorSpace = CGColorSpace(name: CGColorSpace.genericRGBLinear) else { return nil }
guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) else { return nil }
guard let cgImage = context.makeImage() else { return nil }
return NSImage(cgImage: cgImage, size: Size(width: width, height: height))
Run Code Online (Sandbox Code Playgroud)
并查看它。
生成的图像相当饱和,我相信这是因为CGImage到MTLTexture的转换是我过去相当成功的。
请注意,此纹理从未被渲染过。
您可能想知道为什么我要使用所有这些转换,所以这很重要。我的实际管道无法像这样工作,但是它确实要求每个转换组件都能够正常工作。这不是我的实际用例,只是表明问题所在。
这里的问题不是从CGImage到的转换MTLTexture。问题是您假设源图像的色彩空间是线性的。更有可能的是,图像数据实际上是 sRGB 编码的,因此通过创建具有通用线性颜色空间的位图上下文,您错误地告诉 CG 它应该在显示之前对图像数据进行伽马编码,这会导致去饱和度你在看。
您可以通过使用原始颜色空间来解决此问题CGImage,或者考虑到您的图像数据是 sRGB 编码的事实。
| 归档时间: |
|
| 查看次数: |
641 次 |
| 最近记录: |