From: "Ara.T.Howard" Date: 2005-09-01T13:21:25+09:00 Subject: Re: rmagick question On Thu, 1 Sep 2005, Timothy Hunter wrote: > Actually I was thinking that NArray would meet me half-way. > > Right now #import_pixels calls Kernal.Array on the `pixels' argument. My > reasoning for doing this is that this approach allows the caller to pass any > object that supports #to_ary or #to_a (including NArray objects) to > #import_pixels. (The downside for NArrays, of course, is that NArray > responds to #to_a by constructing a real Ruby array with a zillion > elements.) right. > Now I want to filter out strings and treat them specially. Currently a > string is not a reasonable argument since Kernel.Array simply constructs an > array with the string as its only element. Not too useful for building > images. My notion was to do something like this: > > if pixels.respond_to?(:to_str) > pixel_buffer = pixels.to_str > # pass the buffer directly to ImageMagick > else > pixel_array = Kernel.Array(pixels) > # convert the array to a buffer and pass it to IM > end check. > I can't think of a way this would break existing code, can you? You could > use the return value from NArray#to_s, mmap#to_str, or IO.read as the > `pixels' argument. > > The upside is that for real String objects, #to_str is a no-op. The > downside, at least for NArray objects, is that #to_s makes a copy of the > data in the NArray. sounds good. mmap.to_str is a no-op too : guy's got a lot of voodoo going on under the hood - but it sure works. > I've perused the NArray source code and I didn't find a way to directly > access the NArray data without making a copy. you just have to use my illicit narray extension ;-) works like this: mmap = Mmap::new 'data', 'rw', Mmap::MAP_SHARED memory = mmap.to_str na = NArray::str memory, width, height, NArray::BYTE na += 1 exit and the entire file is incremented by one - no explicit io. however, this is officially (by matz i think) frowned on. i've spoken with masahiro about this a little and he was interested in doing something... in any case it's fair to dump that in the narray camp. right new it calls rb_str_new, which does, in fact, copy data. perhaps something like rb_str_new4, which does not copy data - but i don't know what the rules are for creating shared strings... in any case it would be quite useful now even with a copy since explicit loops would be avoided and it would therefore still be very fast. > One more complication. The ImportImagePixels function in ImageMagick > requires an argument that identifies the type of type of the data in the > pixel buffer as char (8-bit), short (16-bit) or int (32-bit). ImageMagick > will convert the data as necessary to the size it needs. It seems to me that > it would be useful to support the use of data that is not the same size as > the underlying pixel type. That is, you could reasonably want to construct > an image with 8-bit pixel data from an NArray.sint (16-bit) object, or vice > versa. So, I'm thinking that #import_pixels should accept an optional 7th > argument that indicates the type of the incoming data (CharPixel, > ShortPixel, LongPixel enum values, probably). The default would be > CharPixel. This would also make it possible to use the same script with > different configurations of ImageMagick. hmmm. i'm having thoughts of a 'Memory' or 'Data' class. it could be backed by file or not, and could have the notion of a 'quanta' or pixel size. i have some simple mmap'ing c programs that manipulate data in this way : they just apply operators to a line of memory where the memory is assumed to be of certain sized quanta or pixels... but this wouldn't really be required - specifying the type is fine - hopefully ImageMagick doesn't convert when it doesn't need too... all this is probably academic though - i'm sure avoiding loops and loads of ruby object creations will yield a huge boost even with some data copy/conversion so everything you've said makes good sense. > Thoughts? I'll hold off writing any code until we're in agreement. i wouldn't mind some opinions from matz, masahiro, and guy about how sharing memory amoung ruby objects would best be done - obviously this would be slickest with the minimum about of data being moved. cheers. -a -- =============================================================================== | email :: ara [dot] t [dot] howard [at] noaa [dot] gov | phone :: 303.497.6469 | Your life dwells amoung the causes of death | Like a lamp standing in a strong breeze. --Nagarjuna ===============================================================================