metalmetalkitmtkview

The Three-Image Problem: How do I set tagged color data in MTKView and CIContext to properly display all three images?


I have provided a link to a UIKit test app which displays three different images, side by side, each inside a separate MTKView. Each image is tagged with a different color profile:

I set up default values for all color spaces and formats. I then check if the image is tagged and, if so, I override those values with state from the tagged color space.

The variables I am setting:

The “colorSpace” default value = CGColorSpaceCreateDeviceRGB()

I also set “pixelFormat” in CIRenderDestination with the MTKView.colorPixelFormat.

If the image is tagged, I override the following values with the tagged colorSpace:

If the tagged colorSpace.isWideGamutRGB = true, then I set the CIRenderDestination.colorSpace to extendedSRGB, ignoring the color space in the tagged wide gamut color space, as well as set the colorPixelFormat = bgr10_xr

Results:

Question: Do I have everything hooked up correctly and, if so, why does one image fail, and the other succeed?

Link to sample project:

https://www.dropbox.com/scl/fi/57u2fcrgdvys7jtzykzxt/ColorSpaceTest.zip?rlkey=unjeeiu7mi0wx9wfpylt78nwd&dl=0


Solution

  • I think I solved it. I set the colorspace on the underlying CAMetalLayer of the MTKView (iOS/Catalyst does not let you set this directly on MTKView):

    Add the following code at the end of the init method in MTKImageView.swift:

    if let taggedColorSpace = image.colorSpace,
       let metalLayer = self.layer as? CAMetalLayer {
           metalLayer.colorspace = isWideGamutRGB ? CGColorSpace(name: CGColorSpace.extendedSRGB) : taggedColorSpace
    }
    

    Note: If the colorspace supports wideGamut, then I set the colorspace in CAMetalLayer to extendedSRGB instead of the tagged colorspace.

    All three images now properly display for me: enter image description here