www.emsdn.com
Class Profile: Home »» BSD [BSD] under "BSD" »»» filling NSImage with binary data from NSData
filling NSImage with binary data from NSData
5/7/06, Ricky Sharp <rsharp (AT) mac (DOT) comwrote:
--
Here's at least one problem. You should be calling an appropriate
init method here. For example:
NSImage* producedNSImage = [[[NSImage alloc] initWithSize:NSMakeSize
(256, 256)] autorelease];
Thanks.
Both should be autoreleased; see code snippet above with the
initWithSize:
--
Finally, I've not yet worked with planar images, so there could be
additional bugs in what you have.
I still get a segfault. thing I've noted however is that this
*only* happens when the data in plane contains nonzero values (e.g.,
some slices are empty, and I get a completely black image just fine,
but when I switch to a plane that contains values 0, bad things
happen). So I am still doing something wrong.
Is there perhaps a smarter way to show an array of bytes on an NSImage
than how I'm doing it here?
-Marc-
No. 1# | By Developer Tags User at [2008-5-4] | size: 3121 bytes
May 7, 2006, at 2:37 PM, marc joanisse wrote:
Hi,
I'm working on a cocoa app that visualizes part of a 3D dataset (MRI
images) as a discrete 2D "slice". I am using NSImage to show the
image. The user chooses a slice of the array (a 256 x 256 grid) to
show in an NSImageView.
The hard part here is the data file format, which is a binary file
consisting of an 8-bit header followed by a 256*256*256 array of
bytes. Each byte specifies a grayscale value.
I have hucked together some code based on other postings and replies
on this list, but I've hit a dead end. Here's where I am at:
I load this data file into an NSData object (declared with global
scope) as follows
vmrData = [NSData dataWithCFile:fileName];
>
>From what I can tell, this seems to do the right thing.
>
Then I trigger the following procedure that actually loads the desired
portion of the data into the NSImage using an NSBitmapImageRep:
- (void)drawXImage:(int)xSlice
{
NSBitmapImageRep* imageRep;
// a pointer to the portion of vmrData containing the desired slice
unsigned char *plane;
// pointer to the part of the dataset we want to visualize
// note vmrData has global scope
plane = (unsigned char*)[vmrData bytes]+8+(256 * 256 * xSlice);
// init the NSBitmapImageRep
imageRep=[[[NSBitmapImageRep alloc]
pixelsWide:256
pixelsHigh:256
bitsPerSample:8
samplesPerPixel:1
hasAlpha:N
isPlanar:YES
bytesPerRow:0
bitsPerPixel:0] autorelease];
// create an NSImage and show it in the window
//n.b. imageView is my delegate for the NSImageView I want to
// show the image in.
NSImage *producedNSImage;
producedNSImage = [NSImage alloc];
Here's at least one problem. You should be calling an appropriate
init method here. For example:
NSImage* producedNSImage = [[[NSImage alloc] initWithSize:NSMakeSize
(256, 256)] autorelease];
[producedNSImage addRepresentation:imageRep];
[imageView setImage:producedNSImage];
}
The procedure produces a segfault when I run it, but not till after it
returns. I suspect the problem ahs to do with how I am setting the
"plane" pointer or how I'm telling the NSBitmapImageRep about it.
As a sidenote: I am also unclear whether I should be releasing
producedNSImage and imageRep at the end of the procedure, or whether
the view needs this to be retained.
Both should be autoreleased; see code snippet above with the
initWithSize:
Finally, I've not yet worked with planar images, so there could be
additional bugs in what you have.
Ricky A. Sharp mailto:rsharp (AT) instantinteractive (DOT) com
Instant Interactive(tm)
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (Cocoa-dev (AT) lists (DOT) apple.com)
Help/Unsubscribe/Update your Subscription:
%40developershed.com
This email sent to bsdarchive (AT) developershed (DOT) com
No. 1# | By Developer Tags User at [2008-5-4] | size: 2346 bytes
Hi,
I'm working on a cocoa app that visualizes part of a 3D dataset (MRI
images) as a discrete 2D "slice". I am using NSImage to show the
image. The user chooses a slice of the array (a 256 x 256 grid) to
show in an NSImageView.
The hard part here is the data file format, which is a binary file
consisting of an 8-bit header followed by a 256*256*256 array of
bytes. Each byte specifies a grayscale value.
I have hucked together some code based on other postings and replies
on this list, but I've hit a dead end. Here's where I am at:
I load this data file into an NSData object (declared with global
scope) as follows
vmrData = [NSData dataWithCFile:fileName];
>From what I can tell, this seems to do the right thing.
Then I trigger the following procedure that actually loads the desired
portion of the data into the NSImage using an NSBitmapImageRep:
- (void)drawXImage:(int)xSlice
{
NSBitmapImageRep* imageRep;
// a pointer to the portion of vmrData containing the desired slice
unsigned char *plane;
// pointer to the part of the dataset we want to visualize
// note vmrData has global scope
plane = (unsigned char*)[vmrData bytes]+8+(256 * 256 * xSlice);
// init the NSBitmapImageRep
imageRep=[[[NSBitmapImageRep alloc]
pixelsWide:256
pixelsHigh:256
bitsPerSample:8
samplesPerPixel:1
hasAlpha:N
isPlanar:YES
bytesPerRow:0
bitsPerPixel:0] autorelease];
// create an NSImage and show it in the window
//n.b. imageView is my delegate for the NSImageView I want to
// show the image in.
NSImage *producedNSImage;
producedNSImage = [NSImage alloc];
[producedNSImage addRepresentation:imageRep];
[imageView setImage:producedNSImage];
}
The procedure produces a segfault when I run it, but not till after it
returns. I suspect the problem ahs to do with how I am setting the
"plane" pointer or how I'm telling the NSBitmapImageRep about it.
As a sidenote: I am also unclear whether I should be releasing
producedNSImage and imageRep at the end of the procedure, or whether
the view needs this to be retained.
Thanks for whatever help you can give me on this,
-Marc-
No. 1# | By Developer Tags User at [2008-5-4] | size: 3259 bytes
major problem is that the plane parameter has to be a pointer an array
of pointers to the image data - and not a pointer to the image data itself.
Each pointer in this array points to a different plane of the image. But
being a grayscale image, there should be only one pointer present in this
array.
Alternately, the program could pass NULL for the plane parameter. In that
case the NSBitmageImageRep object would allocate enough memory to hold the
image data based on the image's other measurements. The program would then
copy the image data into the address returned by calling bitmapData on the
bitmap image rep object.
Greg
Message
From: "marc joanisse" <marc.joanisse (AT) gmail (DOT) com>
To: <cocoa-dev (AT) lists (DOT) apple.com>
Sent: Sunday, May 07, 2006 12:37 PM
Subject: filling NSImage with binary data from NSData
Hi,
I'm working on a cocoa app that visualizes part of a 3D dataset (MRI
images) as a discrete 2D "slice". I am using NSImage to show the
image. The user chooses a slice of the array (a 256 x 256 grid) to
show in an NSImageView.
The hard part here is the data file format, which is a binary file
consisting of an 8-bit header followed by a 256*256*256 array of
bytes. Each byte specifies a grayscale value.
I have hucked together some code based on other postings and replies
on this list, but I've hit a dead end. Here's where I am at:
I load this data file into an NSData object (declared with global
scope) as follows
vmrData = [NSData dataWithCFile:fileName];
>From what I can tell, this seems to do the right thing.
Then I trigger the following procedure that actually loads the desired
portion of the data into the NSImage using an NSBitmapImageRep:
- (void)drawXImage:(int)xSlice
{
NSBitmapImageRep* imageRep;
// a pointer to the portion of vmrData containing the desired slice
unsigned char *plane;
// pointer to the part of the dataset we want to visualize
// note vmrData has global scope
plane = (unsigned char*)[vmrData bytes]+8+(256 * 256 * xSlice);
// init the NSBitmapImageRep
imageRep=[[[NSBitmapImageRep alloc]
pixelsWide:256
pixelsHigh:256
bitsPerSample:8
samplesPerPixel:1
hasAlpha:N
isPlanar:YES
bytesPerRow:0
bitsPerPixel:0] autorelease];
// create an NSImage and show it in the window
//n.b. imageView is my delegate for the NSImageView I want to
// show the image in.
NSImage *producedNSImage;
producedNSImage = [NSImage alloc];
[producedNSImage addRepresentation:imageRep];
[imageView setImage:producedNSImage];
}
The procedure produces a segfault when I run it, but not till after it
returns. I suspect the problem ahs to do with how I am setting the
"plane" pointer or how I'm telling the NSBitmapImageRep about it.
As a sidenote: I am also unclear whether I should be releasing
producedNSImage and imageRep at the end of the procedure, or whether
the view needs this to be retained.
Thanks for whatever help you can give me on this,
-Marc-
No. 1# | By Developer Tags User at [2008-5-4] | size: 862 bytes
Am 07.05.2006 um 21:37 schrieb marc joanisse:
vmrData = [NSData dataWithCFile:fileName];
I may be misremembering here, but aren't you supposed to retain the
data you pass to initWithBitmapDataPlanes: ? What happens right now
is that you're passing a pointer to a part of vmrData to your
NSBitmapImageRep and then autorelease the NSData. Which means as soon
as the pool is collected, your imagerep accesses stale memory because
NSBitmapImageRep doesn't copy the data you give it.
Cheers,
-- M. Uli Kusterer
http://www.zathras.de
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (Cocoa-dev (AT) lists (DOT) apple.com)
Help/Unsubscribe/Update your Subscription:
%40developershed.com
This email sent to bsdarchive (AT) developershed (DOT) com
No. 1# | By Developer Tags User at [2008-5-4] | size: 1012 bytes
Am 07.05.2006 um 23:56 schrieb Greg Herlihy:
major problem is that the plane parameter has to be a pointer
an array of pointers to the image data - and not a pointer to the
image data itself. Each pointer in this array points to a different
plane of the image. But being a grayscale image, there should be
only one pointer present in this array.
He's doing that correctly. It's no difference whether you say:
char*foo[1];
foo[0] = myPointer;
[[NSFoo alloc] init: foo];
or
char*bar;
bar = myPointer;
[[NSFoo alloc] init: &bar];
you get a pointer to a pointer each time. He's doing the latter.
Cheers,
-- M. Uli Kusterer
http://www.zathras.de
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (Cocoa-dev (AT) lists (DOT) apple.com)
Help/Unsubscribe/Update your Subscription:
%40developershed.com
This email sent to bsdarchive (AT) developershed (DOT) com
No. 1# | By Developer Tags User at [2008-5-4] | size: 1747 bytes
Hi,
5/7/06, Greg Herlihy <greghe (AT) pacbell (DOT) netwrote:
Alternately, the program could pass NULL for the plane parameter. In that
case the NSBitmageImageRep object would allocate enough memory to hold the
image data based on the image's other measurements. The program would then
copy the image data into the address returned by calling bitmapData on the
bitmap image rep object.
Aha! Yes, this does work well (sort of) - I can copy the bytes I want
to the pointer to bitmapData and it draws it perfectly. *Except*:
when I call the procedure a second time, (e.g., to set a different
xSlice, thus changing the data to be displayed) it segfaults.
Here's the code so far. It works once but fails when called a second time.
- (void)drawXImage:(int)xSlice
{
NSBitmapImageRep* imageRep;
unsigned char *plane;
int i,j;
imageRep=[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
pixelsWide:256
pixelsHigh:256
bitsPerSample:8
samplesPerPixel:1
hasAlpha:N
isPlanar:YES
bytesPerRow:256
bitsPerPixel:0] autorelease];
NSImage* producedNSImage = [[[NSImage alloc]
initWithSize:NSMakeSize(256, 256)] autorelease];
[producedNSImage addRepresentation:imageRep];
// pointer to the bitmapData
unsigned char *data = [imageRep bitmapData];
// pointer to the portion of vmrData (an NSData object) I want to show
// segfault happens here!
plane = (unsigned char*) [vmrData bytes]+8+(256*256*xSlice);
// copy bytes from *data to *plane
for (i=0;i<256;i++){
for (j=0;j<256;j++){
*dataplane++;
}
}
[imageView setImage:producedNSImage];
}
Any hints are appreciated.
No. 1# | By Developer Tags User at [2008-5-4] | size: 1568 bytes
08/05/2006, at 1:24 PM, marc joanisse wrote:
Here's the code so far. It works once but fails when called a second
time.
- (void)drawXImage:(int)xSlice
{
NSBitmapImageRep* imageRep;
unsigned char *plane;
int i,j;
imageRep=[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
pixelsWide:256
pixelsHigh:256
bitsPerSample:8
samplesPerPixel:1
hasAlpha:N
isPlanar:YES
bytesPerRow:256
bitsPerPixel:0]
autorelease];
NSImage* producedNSImage = [[[NSImage alloc]
initWithSize:NSMakeSize(256, 256)] autorelease];
[producedNSImage addRepresentation:imageRep];
// pointer to the bitmapData
unsigned char *data = [imageRep bitmapData];
// pointer to the portion of vmrData (an NSData object) I want
to show
// segfault happens here!
The seg fault happens because the image is not planar. Substitute
"isPlanar:N" because according to the manual:
The isPlanar argument should be YES if the data components are laid
out in a series of separate planes or channels (planar
configuration) and N if component values are interwoven in a single
channel (meshed configuration).
Since you have a grayscale image, there is only a single channel.
Regards,
Lester
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (Cocoa-dev (AT) lists (DOT) apple.com)
Help/Unsubscribe/Update your Subscription:
%40developershed.com
This email sent to bsdarchive (AT) developershed (DOT) com
No. 1# | By Developer Tags User at [2008-5-4] | size: 1956 bytes
Lester Dowling wrote:
08/05/2006, at 1:24 PM, marc joanisse wrote:
>
>Here's the code so far. It works once but fails when called a second
>time.
>>
>- (void)drawXImage:(int)xSlice
>{
>NSBitmapImageRep* imageRep;
>unsigned char *plane;
>int i,j;
>
>imageRep=[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
>pixelsWide:256
>pixelsHigh:256
>bitsPerSample:8
>samplesPerPixel:1
>hasAlpha:N
>isPlanar:YES
>
>
>bytesPerRow:256
>bitsPerPixel:0]
>autorelease];
>>
>NSImage* producedNSImage = [[[NSImage alloc]
>initWithSize:NSMakeSize(256, 256)] autorelease];
>>
>[producedNSImage addRepresentation:imageRep];
>// pointer to the bitmapData
>unsigned char *data = [imageRep bitmapData];
>// pointer to the portion of vmrData (an NSData object) I want
>to show
>// segfault happens here!
>>
>
The seg fault happens because the image is not planar. Substitute
"isPlanar:N" because according to the manual:
The isPlanar argument should be YES if the data components
are laid out in a series of separate planes or channels (planar
configuration) and N if component values are interwoven in a single
channel (meshed configuration).
Since you have a grayscale image, there is only a single channel.
I would think that a grayscale image could be considered either planar
or non-planar.
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (Cocoa-dev (AT) lists (DOT) apple.com)
Help/Unsubscribe/Update your Subscription:
%40developershed.com
This email sent to bsdarchive (AT) developershed (DOT) com
No. 1# | By Developer Tags User at [2008-5-4] | size: 1379 bytes
08/05/2006, at 2:10 PM, John Stiles wrote:
Lester Dowling wrote:
>>
>The seg fault happens because the image is not planar. Substitute
>"isPlanar:N" because according to the manual:
>>
I would think that a grayscale image could be considered either planar
or non-planar.
That's what I used to think, too -- it's just what I found to work
reliably in my applications. In this case, you're right though because
I found the seg fault doesn't happen because of the planar setting.
From the P, the data file is loaded into a global variable, vmrData,
with:
vmrData = [NSData dataWithCFile:fileName];
These factory methods return an object marked for auto-release. So,
the seg fault happens because the program dereferences this global
object when it has already been auto-released. The problem is fixed by
substituting this line:
vmrData = [[NSData dataWithCFile:fileName] retain];
Regards,
Lester
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (Cocoa-dev (AT) lists (DOT) apple.com)
Help/Unsubscribe/Update your Subscription:
%40developershed.com
This email sent to bsdarchive (AT) developershed (DOT) com
No. 1# | By Developer Tags User at [2008-5-4] | size: 694 bytes
5/8/06, Lester Dowling <lesterdowling (AT) bigpond (DOT) comwrote:
That's what I used to think, too -- it's just what I found to work
reliably in my applications. In this case, you're right though because
I found the seg fault doesn't happen because of the planar setting.
I've tried it both ways and apparently it doesn't matter, at least in my app.
object when it has already been auto-released. The problem is fixed by
substituting this line:
vmrData = [[NSData dataWithCFile:fileName] retain];
Yes, of course. Thanks for the help everyone. It works swimmingly now.
Thanks to everyone for their help,
-Marc-
BSD Hot!
BSD New!
Copyright © 2008 www.emsdn.com • All rights reserved • CMS Theme by www.emsdn.com - 0.328