One thing ImageMagick (and thus RMagick) seemed to be missing was to be able to give a desired width and height to an image, and have it resized to exactly that width and height – without distortion. If you use resize, it will give you the correct sized image, but it will be distorted unless the aspect ratio before/after is the same.
The solution to this is to use change_geometry to get dimensions that won’t distort, but then you are no longer getting exactly the width/height you wanted… which can be a problem with thumbnails.
To solve this I created a crop_resized method which takes the width and height, resizes based on the smaller edge, and then crops the excess. This way your image will always be the desired size, without distortion. This works great for when you are creating thumbnails for photo sites or anything else that requires undistorted images all the same size, and is what I used on this site for the photography stuff. I found myself copying this code for a couple different things I was using it on, and then I saw somebody ask how to accomplish this on a mailing list, so I sent this over to Tim (developer of RMagick) and after passing it back and forth a couple times we arrived at an even better solution which now accepts a third paramater, an ImageMagick gravity constant which instructs it where to crop from (NorthWestGravity, CenterGravity, etc.).
Tim has already put this new method into cvs, so the next version of RMagick will contain crop_resized(width,height,gravity) and crop_resized!
module Magick class Image def crop_resized(ncols, nrows, gravity=CenterGravity) copy.crop_resized!(ncols, nrows, gravity) end def crop_resized!(ncols, nrows, gravity=CenterGravity) if ncols != columns || nrows != rows scale = [ncols/columns.to_f, nrows/rows.to_f].max resize!(scale*(columns+0.5), scale*(rows+0.5)) end crop!(gravity, ncols, nrows, true) if ncols != columns || nrows != rows self end end end