I don't get to write much "real-world" Ruby code so I thought I'd ask 
for help from the community. I'd like your advice about the design for 
the RMagick[1] bindings for a part of the ImageMagick API that I have 
never gotten around to surfacing. I apologize for the length of this 
posting but I figure that too much detail is better than too little.

ImageMagick's "stream" API[2] is two C functions, ReadStream and 
WriteStream, that are useful for transferring pixel data from very large 
images without putting all the pixel data in memory at once. (RMagick 
already has Magick::Image#import_pixels[3] and 
Magick::Image#export_pixels[4], but these two methods require that all 
the pixel data be in memory at once, either in an array or in a string.) 
The ReadStream and WriteStream functions transfer pixel data a row (or 
portion of a row) at a time. The pixel data are presented as a C array 
of binary numbers whose size and order (for example "char" and "RGB") 
must be specified by the caller. The stream functions accept a number of 
optional arguments similar to the existing Magick::Image.read[5] and 
Magick::Image#write[6] methods. Where the pixel data are transferred to 
is up to the caller. The ImageMagick stream command[7] always writes the 
data to a file.

I have already decided on some parts of the design. The ReadStream 
function will be surfaced as read_stream, a singleton method in the 
Magick::Image class similar to the read method. Like read, it will 
accept either a filename or an open File object that identifies the 
input image file, and an "optional arguments" block. It will read the 
pixel data from the image file one row at a time and deliver the data to 
the "sink" specified by an argument. (Unlike read, this method does not 
construct an Image object.)

The WriteStream method will be surfaced as write_stream, an instance 
method in the Magick::Image class similar to the write method. Like 
write, it will accept an "optional arguments" block. It will take the 
pixel data from the image object a row at a time and deliver the data to 
the "sink" specified by an argument.

This leaves two (at least) unresolved issues. (1) What is the "sink" and 
how do the methods use it?  (2) what form should the pixel data be when 
passed to the sink?

The obvious (to me, anyway) answers are (1) The sink is an IO object 
that has already been opened for binary output. The methods call 
IO#write. (2) The pixel data are represented as a plain Ruby string.

Am I overlooking something? Are there kinds of sinks that aren't IO 
objects (a proc, for example) and want the pixel data in some other 
form, such as an array? If so, what would the method calls look like? 
Should there be more than two methods?

Thanks in advance for your help. Whatever happens I'll add these methods 
to the next release of RMagick.


[1] http://rmagick.rubyforge.org
[2] http://www.imagemagick.org/api/stream.php
[3] http://www.simplesystems.org/RMagick/doc/image2.html#import_pixels
[4] http://www.simplesystems.org/RMagick/doc/image2.html#export_pixels
[5] http://www.simplesystems.org/RMagick/doc/image1.html#read
[6] http://www.simplesystems.org/RMagick/doc/image3.html#write
[7] http://www.imagemagick.org/script/stream.php