Converting One Image Format to Another

Credit: Antonio Cangiano

Problem

You want to convert an image to a different format.

Solution

With RMagick, you can just read in the file and write it out with a different extension. This code converts a PNG file to JPEG format:

require ubygems require RMagick img = Magick::Image.read(myimage.png).first img.write(myimage.jpg)

Discussion

As seen in the previous two recipes, Magick::Image.read receives the PNG image and returns an array of Image objects, from which we select the first and only image.

RMagick lets us convert the file into a JPEG by simply changing the filenames extension when we call the write method.

The underlying C library, ImageMagick or GraphicsMagick, has three ways of determining the format of image files:

Although the format prefix takes precedence over the magic number, RMagick won be fooled by an incorrect prefix. Eventually it will have to parse the image file, and the format mismatch will be revealed:

Magick::Image.read("JPG:myimage.png") # Magick::ImageMagickError: Not a JPEG file: starts with 0x89 0x50 `myimage.png:

When you write an image to an output file, you can choose the output format by specifying a file extension or a prefix.

img = Magick::Image.read("myimage.png").first img.write("myimage.jpg") # Writes a JPEG img.write("myimage.gif") # Writes a GIF img.write("JPG:myimage") # Writes a JPEG img.write("JPG:myimage.gif") # Writes a JPEG

You can also get or set the file format of an image by calling the Image#format or Image#format= methods:

img.format # => "PNG" img.format = "GIF" img.format # => "GIF"

Of course, RMagick can read to and write from every graphical file format in existence. How can you tell whether your version of RMagick knows how to write a particular file format?

You can query RMagicks capabilities by calling Magick. formats. This method returns a hash that maps an image format to a four-character code:

Magick. formats["GIF"] # => "*rw+" Magick.formats["JPG"] # => "*rw-" Magick.formats["AVI"] # => "*r--" Magick.formats["PS"] # => " rw+"

The code represents the things that RMagick can do with that file format:

Heres a little bit of metaprogramming that adds four predicate methods to Magick, one for each element of the four-character code. You can use these methods instead of parsing the code string:

module Magick [["native_blob?", ?*], ["readable?", ?r], ["writable?", ?w], ["multi_image?", ?+]].each_with_index do |m, i| define_method(m[0]) do |format| code = formats[format] return code && code[i] == m[1] end module_function(m[0]) end end

This code demonstrates that the GIF file format supports multi-image files, but the JPG format doesn :

Magick.multi_image? GIF # => true Magick.multi_image? JPG # => false

ImageMagick and GraphicsMagick support the most common image formats (over 90 in total). However, they delegate support for many of these formats to external libraries or programs, which you may need to install separately. For instance, to read or write Postscript files, youll need to have the Ghostscript program installed.

See Also

Категории