Thumbnailing Images

Credit: Antonio Cangiano

Problem

Given an image, you want to create a smaller image to serve as a thumbnail.

Solution

Use RMagick, available from the rmagick or rmagick-win32 gems. Its Magick module gives you a simple but versatile way to manipulate images. The class Magick::Image lets you resize images four different ways: with resize, scale, sample, or thumbnail.

All four methods accept a pair integer values, corresponding to the width and height in pixels of the thumbnail you want. Heres an example that uses resize: it takes the file myimage.jpg and makes a thumbnail of it 100 pixels wide by 100 pixels tall:

	require 
ubygems
	require RMagick

	img = 
Magick::Image.read(myimage.jpg).first
	width, height = 100, 100
	thumb = img.resize(width, height)
	thumb.write(mythumbnail.jpg)

Discussion

The class method Image.read, used in the Solution, receives an image filename as an argument and returns an array of Image objects.[1] You obtain the first (and, usually, only) element through Array#first.

[1] Why an array? Because you can pass in an animated GIF or a multilayered image file to Image.read. If you do, the array will contain an Image object for each image in the animated GIF, or for each layer in the multilayered file.

The code given in the Solution produces a thumbnail that is 100 pixels by 100, no matter what dimensions the original image had. If the original image was a square, its proportions will be maintained. But if the initial image was a rectangle, squishing it into a 100 x 100 box will distort it.

If all your thumbnails need to be the same size, you might be willing to live with this distortion. But to maintain the proportions between the longest and shortest dimensions, you should define your thumbnails width and height in terms of the original images aspect ratio. You can get the images original width and height by using its accessor methods, Magick:: Image#columns and Magick:: Image#rows.

A simpler solution is to pass resize a floating-point number as a scaling factor. This changes the images size without altering the aspect ratio. Heres how to generate an image that is 15% the size of the original:

	scale_factor = 0.15
	thumb = img.resize(scale_factor)
	thumb.write("mythumbnail.jpg")

To impose a maximum size on an image without altering its aspect ratio, use change_geometry:

	def thumb_no_bigger_than(img, width, height)
	 img.change_geometry("#{width}x#{height}") do |cols, rows, img|
	 img. 
resize(cols, rows)
	 end
	end

	img.rows # => 470
	img.columns # => 892
	thumb = thumb_no_bigger_than(img, 100, 100)
	thumb.rows # => 53
	thumb.columns # => 100

There are other ways of getting a thumbnail besides using resize. All of the following lines give you some kind of thumbnail. The methods used below also have equivalent methods (like scale!) that modify an Image object in place:

	thumb = img.scale(width, height)
	thumb = img.scale(scale_factor)
	thumb = img.sample(width, height)
	thumb = img.sample(scale_factor)
	thumb = img.thumbnail(width, height)
	thumb = img.thumbnail(scale_factor)

You might also want to generate a thumbnail by cropping an image, rather than resizing it. The following code extracts an 80 x 100 pixel rectangle taken from the center of the image:

	thumb = img.crop(Magick::CenterGravity, 80, 100)

Which of these methods should you use? Magick::Image#resize is the most advanced method, because it accepts two optional arguments: filter and blur. When you specify a filter, you alter the resizing algorithms tradeoff between speed and quality. Refer to the RMagick guide for a complete list of available filters.

The second optional argument, blur, is a floating-point number that can be used to blur (values greater than 1) or sharpen (values less than 1) your image as its resized. Blurring an image is a way to hide visual artifacts created by the thumbnailing process.

The scale method is simpler than resize, because it accepts only a width and height pair, or a scale factor. When you want to generate a thumbnail thats 10% the size of your original image or smaller, thumbnail is faster than resize.

Finally, sample scales images with pixel sampling. Unlike the other methods, it doesn introduce any new colors through interpolation.

The best advice is to try these methods out with your images. Through trial and error, you can determine what works best for your application.

Using crop means approaching the problem in a different way. crop only includes a portion of the original image in the thumbnail. crop has several signatures, each of which requires the output images width and height:

	# With an x, y offset relative to the upper-left corner:
	thumb = img.crop(x, y, width, height)
	# With a GravityType and the x, y offset:
	thumb = img.crop(Magick::WestGravity, x, y, width, height)

	# With a GravityType:
	thumb = img.crop(Magick::EastGravity, width, height)

GravityType is a constant that lets you specify the position of the region that needs to be cropped. The available options are quite self-explanatory.

Be aware that the x and y offset passed to the method crop(gravity, x, y, width, height) are not always calculated from the upper-left corner, but that they depend on the GravityType being used. Refer to the crop documentation for specific details.

You may also want to enforce rules on your list of images so that they all match. For example, you may require all your thumbnails to be smaller than 80 x 100 pixels, or you might want them to all have an equal width of 120 pixels. You may even decide that all images smaller than a certain limit should not be resized at all. For details on techniques for this, see the RMagick documentation of the Image#change_geometry method.

See Also

  • This chapters introduction discusses installing RMagick


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net