Domanda

I am creating an NSImage from an unsigned char * of 24bit RGB data like so:

NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
                            initWithBitmapDataPlanes:(unsigned char **)&data
                            pixelsWide:gWidth
                            pixelsHigh:gHeight
                            bitsPerSample:8
                            samplesPerPixel:3
                            hasAlpha:NO
                            isPlanar:NO
                            colorSpaceName:NSCalibratedRGBColorSpace
                            bytesPerRow:gWidth*3
                            bitsPerPixel:24];

NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(gWidth, gHeight)];
[img addRepresentation:bitmap];

The problem I'm having is that I am later writing more stuff to 'data' and I know that NSImage is not making a copy of it. I say that because if I later write all 0s to my data buffer then the image goes all black.

I'm struggling with Objective C so bear with me if this is trivial.

If I make a local copy of 'data' and never free it then things work well, but obviously leaks:

unsigned char *copy_of_data = new unsigned char[len];
memcpy(copy_of_data, data, len);

How can I either:

(1) make the initWithBitmapDataPlanes create its own copy and handle deallocation?

or (2) free the data myself when appropriate after the image no longer needs it?

È stato utile?

Soluzione

It might be simplest to pass NULL for the planes parameter. Then, after the image rep has been allocated and initialized, ask it for its -bitmapData and copy your data into that. This approach is suggested in the docs:

If planes is NULL or an array of NULL pointers, this method allocates enough memory to hold the image described by the other arguments. You can then obtain pointers to this memory (with the getPixel:atX:y: or bitmapData method) and fill in the image data. In this case, the allocated memory will belong to the object and will be freed when it’s freed.

Emphasis added.

Altri suggerimenti

According to the docs here, NSBitmapImageRep won't take ownership of the plane data if it's valid when you pass it in. ("When the object itself is freed, it will not attempt to free the buffers.").

So you're on your own. The simplest way is to keep the pointer to the data around alongside the pointer to the image rep, and when one is released, free the other. (i.e., if they're kept as ivars or are used temporarily.) That may be harder if you're using GC.

Most cleanly, you could also create a small wrapper class that owns both the image rep object and the data pointer, and in the -finalize (or -dealloc) of that object, get rid of the data buffer.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top