This is a rough outline rewrite the internals of MiniMagick - a ruby gem for using ImageMagick and GraphicsMagick from ruby scripts. MiniMagick's most prominent feature is creating appropriate shell commands which are run as subprocesses - thereby making the gem less fragile w.r.t. the graphics libraries and changes to the *Magick routines.
The MiniMagick image class does too much. I propose that the Image class should be responsible for the image files only and not be involved in running *Magick commands.
Image#new(path = nil)
If path is nil, creates a temporary file using
I think we can avoid issues with Tempfile for temporary files by creating our own files and creating a finalizer (via ObjectSpace#define_finalizer(image, proc)) which removes the file upon reference count exhaustion. We also need to 'write(path)' method which:
- if Image is temporary, does a move and calls ObjectSpace#undefine_finalizer on self.
- if Image is not a temporary image, then does a copy to the new path.
Attributes should track the stuff which comes from 'identify'. It's reasonable to lazy load them, but it's a tradeoff. The most reliable values should come from parsing the 'identify' return string from querying the image file. We probably should do some sort of simple modification time checking to see if the image has been updated since updates are out of programatic control.
MiniMagick::CommandBuilder is pretty good, but rather than being used by the Image class 'run' method, it should work better the other way around.
I propose:
which is pretty much the class defined in MiniMagick except that is should have a 'call' (or 'run') method which raises an exception of it is called.
All the descendents of CommandBuilder will take an optional block as an argument can be used to initialize the command stack
for example:
Morgify#new [&block] - will create a Mogify instance and assemble any
commands passed in the block.
which runs the 'morgify' command. It will delegate command building to CommandBuilder.
Morgify#call(image-file-or-path)
will run the assembled commands. Returns the modified Image object.
same as Morgify, except that the call method creates a copy of the passed in image.
Identify#call(image-file-or-path)
returns an Image object which can be queried for image parameters
Convert#call(input-file-or-Image = nil[, output-path-or-Image = nil])
converts input to output. Returns an Image object. If input-file-or-Image is nil, then creates image w/o input. If output-path-or-Image is nil, the returned Image is a temporary object.
Composite#call(*input-files-or-Images-mixed[, :output_path = nil)
composites the input and returns an Image object. If output path is nil or not specified, the returned object is temporary.
This is really interesting and about what I was hoping we could do. I'm not confident I have enough experience to do it just right on my own but would definitely be interested in pursuing it as a collaboration.