4

In a Cocoa App I would like to display a 2d array of floats in an NSImageView. To make the code as simple as possible, start off by converting the data from float to NSData:

// dataArray: an Nx by Ny array of floats
NSMutableData *nsdata = [NSMutableData dataWithCapacity:0];
long numPixels = Nx*Ny;
for (int i = 0; i < numPixels; i++) {
    [nsdata appendBytes:&dataArray[i] length:sizeof(float)];
}

and now try to display the data (the display is left blank):

[theNSImageView setImage:[[NSImage alloc] initWithData:nsdata]];

Is this the correct approach? Is a CGContext needed first? I was hoping to accomplish this with NSData.

I have noted the earlier Stack posts: 32 bit data, close but in reverse, almost worked but no NSData, color image data here, but not much luck getting variations on these working. Thanks for any suggestions.

Community
  • 1
  • 1
Bruce Dean
  • 2,798
  • 2
  • 18
  • 30

2 Answers2

2

You can use an NSBitmapImageRep to build up an NSImage float-by-float.

Interestingly, one of its initialisers has the longest method name in all of Cocoa:

- (id)initWithBitmapDataPlanes:(unsigned char **)planes 
                    pixelsWide:(NSInteger)width 
                    pixelsHigh:(NSInteger)height 
                 bitsPerSample:(NSInteger)bps 
               samplesPerPixel:(NSInteger)spp 
                      hasAlpha:(BOOL)alpha 
                      isPlanar:(BOOL)isPlanar 
                colorSpaceName:(NSString *)colorSpaceName 
                  bitmapFormat:(NSBitmapFormat)bitmapFormat 
                   bytesPerRow:(NSInteger)rowBytes 
                  bitsPerPixel:(NSInteger)

It's well documented at least. Once you've built it up by supplying float arrays in planes you can then get the NSImage to put in your view:

NSImage *image = [[NSImage alloc] initWithCGImage:[bitmapImageRep CGImage] size:NSMakeSize(width,height)];

Or, slightly cleaner

NSImage *image = [[[NSImage alloc] init] autorelease];
[im addRepresentation:bitmapImageRep];

There is an initialiser which just uses an NSData container:

+ (id)imageRepWithData:(NSData *)bitmapData

although that depends on your bitmapData containing one of the correct bitmap formats.

Tim
  • 5,024
  • 2
  • 30
  • 58
  • Thanks Tim, as you suggest at the end, I think the problem may be that the "nsdata" defined above is not in one of the correct bitmap formats; how do I make the conversion from float to the "proper" bitmap format? – Bruce Dean Feb 03 '12 at 04:40
0

Ok got it to work. I had tried the NSBitmapImageRep before (thanks Tim) but the part I was missing was in properly converting my floating point data to a byte array. NSData doesn't do that and returns nil. So the solution was not so much in needing to build up an NSImage float-by-float. In fact, one can similarly build up a bitmapContext (using CGBitmapContextCreate (mentioned by HotLicks above)) and that works too, once the floating point data has been represented properly.

Bruce Dean
  • 2,798
  • 2
  • 18
  • 30
  • Could you elaborate on your answer to explain "properly converting my floating point data to a byte array". Showing the code that does that conversion would be great. – rene Dec 14 '17 at 06:08