[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