BSD

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • filling NSImage with binary data from NSData

    10 answers - 951 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    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 | | 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.2 | | 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.3 | | 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.4 | | 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.5 | | 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.6 | | 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.7 | | 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.8 | | 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.9 | | 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.10 | | 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-

Re: filling NSImage with binary data from NSData


max 4000 letters.
Your nickname that display:
In order to stop the spam: 2 + 1 =
QUESTION ON "BSD"

EMSDN.COM