Subject: Re: [Q] Convert PixMapHandle to NSBitmapImageRep




On Mar 24, 2009, at 6:12 PM, Eric Gorr wrote:


On Mar 24, 2009, at 6:04 PM, Quincey Morris wrote:

On Mar 24, 2009, at 14:48, Eric Gorr wrote:

While I should be able to use:

- (id)initWithBitmapDataPlanes:(unsigned char **)planes pixelsWide: (NSInteger)widthpixelsHigh:(NSInteger)height bitsPerSample: (NSInteger)bps samplesPerPixel:(NSInteger)spphasAlpha:(BOOL)alpha isPlanar:(BOOL)isPlanar colorSpaceName:(NSString *)colorSpaceNamebitmapFormat:(NSBitmapFormat)bitmapFormat bytesPerRow:(NSInteger)rowBytesbitsPerPixel:(NSInteger)pixelBits

and pass in the appropriate values from my PixMapHandle, I was hoping that

PixMapHandle previewPixMap = GetGWorldPixMap( previewGWorld );
LockPixels( previewPixMap );
[NSBitmapImageRep imageRepWithData:[NSData dataWithBytes:*previewPixMap length:GetHandleSize( (Handle)previewPixMap )]];
UnlockPixels( previewPixMap );

would have worked, but it doesn't (wasn't really expecting it to).

Before I went ahead and use the init method, I wanted to find it if there was something simple that I was missing.

Yes. 'imageRepWithData' is expects the data to be an image in a known format (TIFF, JPEG, PNG, PICT, etc). All you have is a pixel array, so of course you're going to have to specify the pixel format and all the other stuff in the 'init...' method.

Are you certain?

It should actually be fairly straightforward to take a GWorld, create a PICT from the GWorld, and then use imageRepWithData.

This is the kind of simpler thing I was thinking I might have been missing and it avoids the init method. Although, it may not be very efficient.

Of course, I've forgotten how to convert a GWorld into a PICT...

Well, this, of course, wasn't to difficult to figure out...

PicHandle GWorldToPICT( GWorldPtr theWorld )
{
GrafPtr oldPort;
GDHandle oldDevice;

::GetGWorld( &oldPort, &oldDevice );
SetGWorld( theWorld, nil );

PicHandle thePict;
PixMapHandle theMap;
Rect bounds;

GetPortBounds( theWorld, &bounds );

theMap = ::GetGWorldPixMap(theWorld);

::LockPixels(theMap);

thePict = OpenPicture( &bounds );

::ForeColor(blackColor);
::BackColor(whiteColor);
::CopyBits( GetPortBitMapForCopyBits(theWorld),
GetPortBitMapForCopyBits(theWorld),
&bounds,
&bounds,
srcCopy,
nil );

::ClosePicture();

::UnlockPixels( theMap );

::SetGWorld(oldPort, oldDevice);

return thePict;
}


and then once one has a PICT, creating a NSBitmapImageRep is trivial:

NSBitmapImageRep = [[[NSBitmapImageRep alloc] initWithData:[NSData dataWithBytes:*pict length:GetHandleSize( (Handle)pict )]] autorelease];


I was able to get the NSBitmapImageRep method to work as well, but the solution isn't nearly as clean. The primary problem was that my PixMap had a pixelFormat of k32BGRAPixelFormat, which is not directly handled by NSBitmapImageRep and resulted in the wrong image until I swapped the bytes around to make it k32ARGBPixelFormat. It would take a lot more code to handle all of the various pixelFormat's one might encounter.

The other problem which required even more code to write is that NSBitmapImageRep's init method does not copy the pixel data. I understand the reason why, but it does mean that more code needs to be written to handle this situation which would either involve tracking the the pixel data buffer or copying in the pixel data myself.

Ultimately, I like less code when efficiency isn't a primary concern (and I'm not even sure the PICT method is slower).




_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@xxxxxxxxxxxxxxx)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/maillists%40codeha.us

This email sent to maillists@xxxxxxxxx



Privacy