From: Timothy Hunter Date: 2006-12-31T05:00:33+09:00 Subject: Need help designing a pair of RMagick methods 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