I'm trying to draw 2 images into the same canvas and for some images I see a slight color distortion in the resulting UIImage, the image "brightens up" a little bit and I can't figure-out the reason.
Here's a simplified code I use which produces color distortion even if drawing a single image:
// originalImageURI is a local path
guard let originalImage = normalizedImageOrientation(image: originalImageURI) else { ... }
UIGraphicsBeginImageContext(originalImage.size)
originalImage.draw(at: .zero)
let combinedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
And in this example, combinedImage
has color distortion.
I tried using https://github.com/MetalPetal/MetalPetal but doing the same: import and render the original image produces color distortion as well:
let mtiImage = MTIImage(cgImage: originalImage.cgImage!)
let options = MTIContextOptions()
guard let device = MTLCreateSystemDefaultDevice(), let context = try? MTIContext(device: device, options: options) else { ... }
let combinedImage = try context.makeCGImage(from: mtiImage)
let resultImage = UIImage(cgImage: combinedImage)
And in this example, result image has color distortion.
Example of how color distortion look for the stock simulator image:
Any advice on how to approach this problem?
Thank you!
Unfortunately, there are several factors that can yield this sort of shift (e.g., color spaces, rendering intents, pixel interpolation if resized, etc.). It’s all very complicated.
I would recommend retiring the deprecated UIGraphicsBeginImageContext
and instead use the contemporary UIGraphicsImageRenderer
. And I recommend specifying the format
when instantiating it, supplying it the original image’s imageRendererFormat
, to minimize these issues. E.g.:
let rect = CGRect(origin: .zero, size: size)
let newImage = UIGraphicsImageRenderer(bounds: rect, format: originalImage.imageRendererFormat).image { _ in
originalImage.draw(in: rect)
}
In this screen snapshot, the top image is the original, the bottom is the one generated by UIGraphicsImageRenderer
with a common format
, and I compare the same pixel on the two images and they do not appear to suffer any color shift: