Very weird behavior, but I have narrowed the problem down as far as I can go I think
I have a NSImage
, let's call it inputImage
. It is represented by a NSBitmapImageRep
in a CGColorSpaceCreateDeviceGray
, if that matters
I want to create a CGImageRef
from it, but with inverted colors.
NSData *data = [inputImage TIFFRepresentation];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
NSBitmapImageRep *maskedRep = (NSBitmapImageRep*)[inputImage representations][0];
CGFloat decode[] = {0.0, 1.0};
maskRef = CGImageMaskCreate(maskedRep.pixelsWide,
maskedRep.pixelsHigh,
8,
maskedRep.bitsPerPixel,
maskedRep.bytesPerRow,
provider,
decode,
false);
NSImage *testImage = [[NSImage alloc] initWithCGImage:maskRef size:NSMakeSize(1280,1185)]; //the size of the image, hard-coded for testing
NSLog(@"testimage: %@", testImage);
The problem is when I look at testImage
, all of the pixels are slightly offset to the right from the original image.
It's much easier to see if you save the pictures off, but you'll notice that everything in testImage
is offset to the right by about 5 pixels or so. You'll see a white gap to the left of the black content in testImage
Somewhere in my 5 lines of code I am somehow moving my image over. Does anybody have any idea how this could be happening? I'm currently suspecting TIFFRepresentation
The data provider you pass to CGImageMaskCreate()
is supposed to be raw pixels in the form specified by the other parameters, not an image file format. You shouldn't be passing TIFF data. Frankly, I'm surprised you got anything remotely resembling your original image, rather than noise/garbage. I'm guessing the TIFF data wasn't compressed, by sheer chance. You can actually see a bit of noise, which is the TIFF header interpreted as pixels, at the upper-left of your mask.
Probably, your best bet is to create a CGImage
from your inputImage
(or, depending on how inputImage
was created, skip NSImage
and create the CGImage
directly from a file using the CGImageSource
API or CGImageCreateWith{JPEG,PNG}DataProvider()
). To get a CGImage
from an NSImage
, use -CGImageForProposedRect:context:hints:
.
Then, get the data provider from that CGImage
and create the mask CGImage
from that, using the various properties (width, height, bpp, etc.) queried from the first CGImage
using the various CGImageGet...
functions.