4

First off: I want to use NSBezierPath to draw some simple button artwork in my app, so I figure I should create an NSBitmapImageRep, get the CGImage, create an NSImage from that, and then call setImage: on the button. Correct me if I'm wrong.

So I went to see how to create an NSBitmapImage and found this: **initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:**

Whoa.

Keeping in mind what I was looking for was something along the lines of an initWithSize:, what should I put in for those values?

cacau
  • 3,606
  • 3
  • 21
  • 42
PopKernel
  • 4,110
  • 5
  • 29
  • 51

3 Answers3

3

You don't need to allocate space for the data planes. Below is a call to create an empty 32-bit NSBitmapImageRep with an alpha component.

NSBitmapImageRep *newRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                   pixelsWide:pixelsWide
                                                                   pixelsHigh:pixelsHigh
                                                                bitsPerSample:8
                                                              samplesPerPixel:4
                                                                     hasAlpha:YES
                                                                     isPlanar:NO
                                                               colorSpaceName:NSDeviceRGBColorSpace
                                                                   bytesPerRow:4 * pixelsWide
                                                                  bitsPerPixel:32];
Alex Zielenski
  • 3,591
  • 1
  • 26
  • 44
1

Any particular reason you're not simply creating a new NSImage and drawing into it by bracketing your drawing code with focus locking like

NSImage* anImage = [[NSImage alloc] initWithSize:NSMakeSize(100.0,  100.0)];
[anImage lockFocus];

// Do your drawing here...

[anImage unlockFocus];

(The Cocoa Drawing Guide is your friend, btw)

cacau
  • 3,606
  • 3
  • 21
  • 42
  • I didn't realize you could do that. I have skimmed the Cocoa Drawing Guide but I must have missed it. – PopKernel Aug 05 '14 at 16:15
  • @PopKernel You're welcome. Yeah, just creating an image w/o any particular constraints is really straight-forward – cacau Aug 06 '14 at 05:55
0

The documentation explains it pretty well.

The planes parameter is a little confusing. It's basically a pointer to the pointer to the pixels. So if you have your pixels in an array pointed to by a variable named "pixels", like this:

unsigned char* pixels = malloc (width * height * 4); // assumes ARGB 8-bit pixels
NSBitmapImageRep* myImageRep = [[NSBitmapImageRep alloc] initWithDataPlanes:&pixels
... etc...];

The rest of the parameters are pretty straightforward. pixelWidth and pixelHeight are just what you'd expect. The other values all correspond to how your data is arranged. Are you using ARGB data at 8 bits per channel? Or is it RGBA at 32-bits per channel?

NSDeviceRGBColorSpace is probably sufficient for your uses for the color space.

The isPlanar channel should be NO if you're passing in a single pointer to your image data.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • I should mention that part of the reason I found myself scratching my head is that my knowledge of bitmap image terminology is a little… a la carte. For example, the documentation tells me that for the bps argument "All components … have the same bits per sample. bps should be one of these values: 1, 2, 4, 8, 12, or 16." but I'm not sure what the benefit is of giving more bits to each sample. – PopKernel Aug 05 '14 at 02:05
  • That's understandable. (And they also leave out that 32 is a valid value.) Your eye will not be able to detect anything above 8 in most cases. But the extra bits (if you go above 8) may be useful if you're going to do many passes of image processing on the result. In your case, as you've described it, 8 is probably just fine. – user1118321 Aug 05 '14 at 02:57
  • 1
    You don't actually have to allocate those pixels and instead pass NULL for the dataPlanes. I posted an answer with all of the appropriate parameters you'd want for a standard empty `NSBitmapImageRep` – Alex Zielenski Aug 05 '14 at 06:12
  • Fair enough. In my use, I tend to need to allocate the buffer first, put some data into it using some other method, such as creating a CGBitmapContext out of it, or whatever, and then turn it into an NSBitmapImageRep. I also tend to need to keep track of the buffer so want to control its lifetime manually. But you're right, you don't need to do it that way. – user1118321 Aug 05 '14 at 15:34