当我将MTKView的内容捕获到UIImage中时,生成的图像看起来质量不同,如下所示:
我用来生成UIImage的代码如下:
let kciOptions = [kCIContextWorkingColorSpace: CGColorSpace(name: CGColorSpace.sRGB)!,
kCIContextOutputPremultiplied: true,
kCIContextUseSoftwareRenderer: false] as [String : Any]
let lastDrawableDisplayed = self.currentDrawable! // needed to hold the last drawable presented to screen
drawingUIView.image = UIImage(ciImage: CIImage(mtlTexture: lastDrawableDisplayed.texture, options: kciOptions)!)
由于我没有修改ciImage方向(.oriented(CGImagePropertyOrientation.downMirrored)),因此生成的图像是颠倒的,如上图所示。我保持镜像方向不变,因此我可以指出两个图像捕获之间的颜色差异。
无论我如何更改kciOptions参数,(甚至将颜色空间更改为灰度),我都没有看到所产生的UIImage发生任何变化,这种变化看起来比原始颜色更暗淡/不饱和。有没有人对如何准确捕捉我在MTKView上绘制UIImage的内容有任何建议?任何建议都会非常感激。
以下是我可能证明相关的MTKView设置:
let renderPipelineDescriptor = MTLRenderPipelineDescriptor()
renderPipelineDescriptor.vertexFunction = vertexProgram
renderPipelineDescriptor.sampleCount = self.sampleCount
renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat.bgra8Unorm
renderPipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
renderPipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
renderPipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
self.isOpaque = false // makes MTKView bg transparent
答案 0 :(得分:2)
您的CGColorSpace
为.sRGB
,但您的renderPipelineDescriptor的pixelFormat为.bgra8Unorm
。尝试将该行更改为:
renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat.bgra8Unorm_srgb
答案 1 :(得分:2)
我已经在几篇文章中看到了这个问题,但没有明确的答案。这是我发现的:
对于初学者,
var serverData = data[0];
实际上应该只设置为MTKView的本机像素格式
renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat.bgra8Unorm
第二,当我设置CIImage的选项时:
renderPipelineDescriptor.colorAttachments[0].pixelFormat = self.colorPixelFormat
将 kCIContextWorkingColorSpace 设置为什么无关紧要,无论使用什么,我都看不到任何视觉差异。我真正需要设置的属性称为 KCIImageColorSpace 。因此,更新后的kciOptions看起来像:
let kciOptions = [kCIContextWorkingColorSpace: CGColorSpace(name: CGColorSpace.sRGB)!,
kCIContextOutputPremultiplied: true,
kCIContextUseSoftwareRenderer: false] as [String : Any]
以类似的方式使用视图的本机像素格式,调用CGColorSpaceCreateDeviceRGB()会创建特定于所使用设备的RGB颜色空间。
答案 2 :(得分:1)
let context = CIContext()
let texture = metalView.currentDrawable!.texture
let cImg = CIImage(mtlTexture: texture, options: nil)!
let cgImg = context.createCGImage(cImg, from: cImg.extent)!
let uiImg = UIImage(cgImage: cgImg)