views:

114

answers:

3

I'm implementing my own NSBitmapImageRep (to draw PBM image files). To draw them, I'm using NSDrawBitmap() and passing it the NSCalibratedBlackColorSpace (as the bits are 1 for black, 0 for white).

Trouble is, I get the following warning:

warning: 'NSCalibratedBlackColorSpace' is deprecated

However, I couldn't find a good replacement for it. NSCalibratedWhiteColorSpace gives me an inverted image, and there seems to be no way to get NSDrawBitmap() to use a CGColorSpaceRef or NSColorSpace that I could create as a custom equivalent to NSCalibratedBlackColorSpace.

I've found a (hacky) way to shut up the warning (so I can still build warning-free until a replacement becomes available) by just passing @"NSCalibratedBlackColorSpace" instead of the symbolic constant, but I'd rather apply a correct fix.

Anybody have an idea?


OK, so I tried

NSData*     pixelData = [[NSData alloc] initWithBytes: bytes +imgOffset length: [theData length] -imgOffset];
CGFloat     black[3] = { 0, 0, 0 };
CGFloat     white[3] = { 100, 100, 100 };
CGColorSpaceRef calibratedBlackCS = CGColorSpaceCreateCalibratedGray( white, black, 1.8 );
CGDataProviderRef provider = CGDataProviderCreateWithCFData( UKNSToCFData(pixelData) );
mImage = CGImageCreate( size.width, size.height, 1, 1, rowBytes, calibratedBlackCS, kCGImageAlphaNone,
                        provider, NULL, false, kCGRenderingIntentDefault );
CGColorSpaceRelease( calibratedBlackCS );

but it's still inverted. I also tried swapping black/white above, didn't change a thing. Am I misinterpreting the CIE tristimulus color value thing? Most docs seem to assume you know what it is or are willing to transform a piece of matrix maths to figure out what color is what. Or something.

I'd kinda like to avoid having to touch all the data once and invert it, but right now it seems like the best choice (/me unpacks his loops and xor operators).

+1  A: 

It seems to have just been removed with no replacement. The fix is probably to just invert all the bits and use NSCalibratedWhiteColorSpace.

Donal Fellows
Realizing I was replacing ten lines of perfectly working code with 50 just because Apple thinks I shouldn't be using their black color space anymore, that's what I eventually did. A quick ^= 0xff later, everything's warning-free. Thanks!
uliwitness
It would be very interesting to hear what Apple's reasoning is for deprecating the color space, as it seems like it would be straightforward to maintain. I guess we'll never know...
Rob Keniger
Indeed, the idea is to just stop using black-is-one. At the Cocoa level, the point to deprecating this is that CG has never supported black-is-one colorspaces, and any use of black-is-one has incurred performance issues because Cocoa has to insulate you from CG's lack of support. At the CG level, the thought in general is that no one really needs both black-is-one and black-is-zero. Having both around just means more stuff has impedance matching problems and such. Just use black-is-zero. One of the goals in 10.6 was to align Cocoa and CG - less insulation.
Ken
That said, the easiest way to deal with data that already in black-is-one is to use a normal gray colorspace, but use the decode matrix parameter of CGImageCreate. This allows sort of a preprocess step that goes before the colorspace interpretation of the data. Cocoa itself does something bizarre to make a colorspace that is truly black-is-one because it has some tight compat constraints, but I don't suggest you copy this.
Ken
NSDrawBitmap is not a particularly efficient function, by the way. It just instantiates an NSBitmapImageRep, draws with it, and immediately destroys it. The first rule of image performance is to hold onto your images. See the NSImage talk from WWDC2009.
Ken
+1  A: 

I'd create a calibrated gray CGColorSpace with the white and black points exchanged, then create a CGImage with the raster data and that color space. If you want a bitmap image rep, it's easy to create one of those around the CGImage.

Peter Hosey
Couldn't really figure out how to do this. Maybe I'm just to stupid to google for CIE tristimulus color values, but neither passing 100,100,100 or 0,0,0 or 1,1,1 as the white/black point worked.
uliwitness
+1  A: 

Another way (since you need to support planar data and you can require 10.6) would be to create an NSBitmapImageRep in the usual way in the NSCalibaratedWhiteColorSpace, and then replace its color space with an NSColorSpace created with the CGColorSpace whose creation I suggested in my other answer.

Peter Hosey
I'm implementing an NSImageRep, so it feels kinda odd to create another image rep just for that. But it sounds like a good suggestion for other cases, thank you.
uliwitness