[Openmcl-devel] Advice needed: best way to fram a Lisp array into an ns-image
R. Matthew Emerson
rme at clozure.com
Fri Jan 18 18:50:49 PST 2008
On Jan 18, 2008, at 8:15 PM, Ron Garret wrote:
> What is the easiest way to fram a Lisp array of numbers representing
> pixel data into an ns-image object? The best I've been able to come
> up with is:
>
> 1. Create the NSImage and initialize it with initWithSize
>
> 2. Create an NSData object and stick the pixel data into it.
>
> 2. Create an NSBitMapImageRep and initialize it with (deep breath)...
> initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel
>
> (Whew!)
>
> 3. Add the NSBitMapImageRep to the NSImage using addRepresentation:
>
> But that seems horribly clunky compared to how easy everything else
> having to do with images is turning out to be. Is there a better way
> to do this?
>
>
> (BTW, the only reason I really need to do this is that getPixel:atX:y:
> and setPixel:atX:y:: are gawdawful slow, like a thousand times slower
> than an aref. If there's a fast way to access pixels directly from a
> NSBitMapImageRep then I can just use that. But it seems like there's
> not.)
When using that really long initWithBitmapDataPlanes:... method, you
have two options. You can pass NULL as the first argument, and memory
for the bitmap will be allocated and owned by the NSBitmapImageRep
instance. You can get a reference to the bitmap with the bitmapData
method, and read/modify the data with CCL's foreign memory accessors
(%get-unsigned-byte, whatever...)
http://doc.clozure.com/doku.php/doc/openmcl/ffi#referencing_and_using_foreign_memory_addresses
Alternatively, if you already have the image data somewhere, you can
pass initWithBitmapDataPlanes:... a pointer to it. However, you must
ensure that the data sticks around as long as the NSBitmapImageRep
instance does. But, if you've got a regular lisp array with the image
data in it, there's no way to pass a pointer to said array to foreign
code.
There is a function called CCL:MAKE-HEAP-IVECTOR that might be useful
in this circumstance. MAKE-HEAP-IVECTOR returns both a macptr and a
(one-dimensional) lisp array which share the same memory. (I don't
know offhand what, if any, performance price there would be to pay if
you made a 2-D array displaced to the 1-D heap ivector.) The GC won't
move the heap ivector around, so it's safe to reference from foreign
code. On the other hand, you have to call DISPOSE-HEAP-IVECTOR to
free it.
http://doc.clozure.com/doku.php/doc/openmcl/ffi#tutorialallocating_foreign_data_on_the_lisp_heap
Maybe something I wrote here will give you an idea.
More information about the Openmcl-devel
mailing list