Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

What good is NSBitmapFormatAlphaNonpremultiplied?

If I create a bitmap image and then try to get ready to draw into it, like so:

NSBitmapImageRep* newRep = [[NSBitmapImageRep alloc]
    initWithBitmapDataPlanes: nullptr
    pixelsWide: 128
    pixelsHigh: 128
    bitsPerSample: 8
    samplesPerPixel: 4
    hasAlpha: YES
    isPlanar: NO
    colorSpaceName: NSDeviceRGBColorSpace
    bitmapFormat: NSBitmapFormatAlphaNonpremultiplied |
        NSBitmapFormatThirtyTwoBitBigEndian
    bytesPerRow: 4 * 128
    bitsPerPixel: 32];

[NSGraphicsContext setCurrentContext:
    [NSGraphicsContext graphicsContextWithBitmapImageRep: newRep]];

then the log shows this error:

CGBitmapContextCreate: unsupported parameter combination:
 	RGB 
	8 bits/component, integer
 	512 bytes/row
	kCGImageAlphaLast
	kCGImageByteOrderDefault
	kCGImagePixelFormatPacked
	Valid parameters for RGB color space model are:
	16  bits per pixel,		 5  bits per component,		 kCGImageAlphaNoneSkipFirst
	32  bits per pixel,		 8  bits per component,		 kCGImageAlphaNoneSkipFirst
	32  bits per pixel,		 8  bits per component,		 kCGImageAlphaNoneSkipLast
	32  bits per pixel,		 8  bits per component,		 kCGImageAlphaPremultipliedFirst
	32  bits per pixel,		 8  bits per component,		 kCGImageAlphaPremultipliedLast
	32  bits per pixel,		 10 bits per component,		 kCGImageAlphaNone|kCGImagePixelFormatRGBCIF10|kCGImageByteOrder16Little
	64  bits per pixel,		 16 bits per component,		 kCGImageAlphaPremultipliedLast
	64  bits per pixel,		 16 bits per component,		 kCGImageAlphaNoneSkipLast
	64  bits per pixel,		 16 bits per component,		 kCGImageAlphaPremultipliedLast|kCGBitmapFloatComponents|kCGImageByteOrder16Little
	64  bits per pixel,		 16 bits per component,		 kCGImageAlphaNoneSkipLast|kCGBitmapFloatComponents|kCGImageByteOrder16Little
	128 bits per pixel,		 32 bits per component,		 kCGImageAlphaPremultipliedLast|kCGBitmapFloatComponents
	128 bits per pixel,		 32 bits per component,		 kCGImageAlphaNoneSkipLast|kCGBitmapFloatComponents
See Quartz 2D Programming Guide (available online) for more information.

If I don't use NSBitmapFormatAlphaNonpremultiplied as part of the format, I don't get the error message. My question is, why does the constant NSBitmapFormatAlphaNonpremultiplied exist if you can't use it like this?

If you're wondering why I wanted to do this: I want to extract the RGBA pixel data from an image, which might have non-premultiplied alpha. And elsewhere online, I saw advice that if you want to look at the pixels of an image, draw it into a bitmap whose format you know and look at those pixels. And I don't want the process of drawing to premultiply my alpha.

Answered by DTS Engineer in 844462022

Interesting question. I did a search through the system sources and this format is not supported by the NS* APIs as a working format because it does not map to any of the bitmap formats supported by Core Graphics. However, it is used for NSBitmapImageRep storage by routines reading and writing some image file formats. Perhaps you may be able to get at the data you're interested in by extracting the NSBitmapImageRep from your NSImage and accessing the data you want in there.

If you need to work with nonpremultiplied pixel data, perhaps check out the vImage routines such as vImagePremultiplyData_ARGB8888() and vImageUnpremultiplyData_ARGB8888() that you can use for converting pixel formats from premultiplied to nonpremultiplied (and vice versa).

Interesting question. I did a search through the system sources and this format is not supported by the NS* APIs as a working format because it does not map to any of the bitmap formats supported by Core Graphics. However, it is used for NSBitmapImageRep storage by routines reading and writing some image file formats. Perhaps you may be able to get at the data you're interested in by extracting the NSBitmapImageRep from your NSImage and accessing the data you want in there.

If you need to work with nonpremultiplied pixel data, perhaps check out the vImage routines such as vImagePremultiplyData_ARGB8888() and vImageUnpremultiplyData_ARGB8888() that you can use for converting pixel formats from premultiplied to nonpremultiplied (and vice versa).

Perhaps you may be able to get at the data you're interested in by extracting the NSBitmapImageRep from your NSImage and accessing the data you want in there.

Yes, I can do that, but then I'm not sure whether I'm dealing with big-endian or little-endian data, whether alpha is first or last, maybe even whether the data is 16 bit or floating-point, so it's a pain.

The trouble with vImageUnpremultiplyData_ARGB8888 is that unpremultiplying is a lossy operation. In the extreme case, if the alpha value is zero, you have no idea what the original RGB values were.

What good is NSBitmapFormatAlphaNonpremultiplied?
 
 
Q