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:
The above scenario will properly render the DisplayP3 image, and the uRGB image. The “Test RGB” image fails:
If I do not override the CIRenderDestination.colorSpace with a value from the tagged image, then the “Test RGB” image succeeds, but the “uRGB” image fails to render properly:
Question: Do I have everything hooked up correctly and, if so, why does one image fail, and the other succeed?
Link to sample project:
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.