HuaTham
HuaTham

Reputation: 7596

UIGraphicsImageRenderer: pngData for grayscale image

I have enjoyed using the newer APIs from UIGraphicsImageRenderer introduced since iOS 10, but now I'm wondering if it's possible at all to get a grayscale Data from its pngData method.

Say I have an input image called "mask.png", a grayscale image. I have verified that it loads up as grayscale by looking at UIImage's underlying colorspace. The older API UIImagePNGRepresentation seems to be able to detect the colorspace and encode its returned Data properly. However, the pngData function introduced since iOS 10 seems to convert my Data to RGB colorspace.

extension UIImage {
    public func pngData_olderAPI() -> Data? {
        return UIImagePNGRepresentation(self)
    }

    public func pngData() -> Data {
        let renderedSize = CGSize(width: size.width, height: size.height)
        let renderer = UIGraphicsImageRenderer(size: renderedSize, format: UIGraphicsImageRendererFormat())
        return renderer.pngData { (rendererContext) in
            let rect = CGRect(x: 0, y: 0, width: renderedSize.width, height: renderedSize.height)
            self.draw(in: rect)
        }
    }
}

let mask = UIImage(named: "mask.png")
print(mask?.cgImage?.colorSpace.debugDescription)

let data = mask?.pngData_olderAPI()
let unwrappedMask = UIImage(data: data!)
print(unwrappedMask?.cgImage?.colorSpace.debugDescription)

let data2 = mask?.pngData()
let unwrappedMask2 = UIImage(data: data2!)
print(unwrappedMask2?.cgImage?.colorSpace.debugDescription)

Here's the (simplified) output:

...kCGColorSpaceModelMonochrome; Dot Gain 20%))")
...kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Dot Gain 20%))")
...kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1))")

I don't see how I can set the colorspace in the newer API. Is it possible to save a grayscale image with the new API?

Upvotes: 3

Views: 1666

Answers (1)

Jordan H
Jordan H

Reputation: 55705

As of iOS 12, UIGraphicsImageRender will automatically select the right color space based on the drawing performed. In my case, it automatically created the image with the grayscale color space.

<CGColorSpace 0x280d869a0> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Gamma 2.2 Profile)

This was explained in the iOS Memory Deep Dive session at WWDC 2018.

There isn't a way to manually specify a color space with this API. Related to this however, you can set the preferredRange on UIGraphicsImageRendererFormat, but there's not an option for preferring monochrome.

Upvotes: 4

Related Questions