Like t-shirts? Find hundreds of cool Geek T-shirts at Teenormous

I have previously mentioned using the ruby plugin MiniMagick to resize images. However, I recently realized there is a much easier way that only requires ImageMagick and would therefore work for any web development environment including PHP, Ruby, ASP etc. This technique was inspired by the MiniMagick plugin and involves shelling out directly to the ImageMagick command-line utilities.

I will cover two common techniques:

  • resizing an image
  • determining an image’s width and height

Resizing An Image

To resize an image, you can use ImageMagick’s mogrify utility. For example, to resize an image to 100×100 you would type:

mogrify -thumbnail "100x100>" someimage.gif

The > symbol will make mogrify maintain the aspect ratio. To run this command from RubyOnRails, you can just use backticks to execute it from a command shell like so:

`mogrify -thumbnail "100x100>" someimage.gif`

Determining Image Width and Height

To determine the width and height of the image, we can use ImageMagick’s identify utility like so:

identify -format "%w %h" someimage.gif

This will return the width and height separated by a space. So, to parse these from Ruby you could do:

w, h = `identify -format "%w %h" someimage.gif`.split

It’s that easy. One other side benefit is by running this process from the command-line your webapp will not consume the additional memory needed for the resizing. The command shell will allocate and free this memory. For a RubyOnRails application, this is a huge benefit as one of the biggest issues with other techniques such as RMagick is that they typically may consume too much memory and will crash your web application.

19 Responses to “Dead Simple Image Processing with ImageMagick”

  1. Tim Hunter Says:

    Tom, if you know of a memory leak in RMagick _please_ report it to me at rmagick AT rubyforge DOT org. I’d love to have a shot at fixing it. I know of no leaks in the current release of RMagick. I’m not saying there can’t be a leak, just saying nobody’s reported one.

    You may be thinking about the need to run GC.start periodically when you’re using RMagick in a web app, to give ImageMagick a chance to free memory that’s no longer referenced by your script. I’ve written a note about it here: http://rubyforge.org/forum/forum.php?thread_id=1374&forum_id=1618.

    I do agree with you, though, that if your application doesn’t particularly need the functionality that RMagick supplies then MiniMagick and mogrify are good solutions to a lot of image processing problems. Whichever technique you choose, good luck!

  2. tom Says:

    Hi Tim,

    Thanks for your comments. I suppose my comment of “leak” for RMagick may have been a bit harsh so I re-phrased it to “may consume too much memory”. There is a general perception that RMagick leaks memory but I do remember reading that the GC.start technique would fix this. Thanks for the write-up.

    In my case, for simple thumbnail creation I don’t need the overhead and much larger memory footprint of a solution like RMagick. It is nice to know that it is there if I ever do though.

    Tom

  3. Anton Says:

    Hi i am quite new to rails but are you saying here that i can call this

    `mogrify -thumbnail “100×100>” someimage.gif`

    in a controller or a view and it will give me a thumbnail?

  4. tom Says:

    Hi Anton,

    Yes, the backticks just run the command as if you typed it on the command line. I recommend just trying it from the command line first. Then if that works you can put it in backticks from anywhere in your Rails app and it should work.

    A best practice is to put this code into a library or model rather than the controller so you can keep your controller light-weight.

  5. Anton Says:

    Hi Tom

    Thanks for the quick reply, i am playing about with it just now and it seems to be working (something that is not common with my learning of RoR)

    Now the tutorial i did to upload my images (Agile) put them in the database so i guess i would have to change that so they are on the server?

  6. tom Says:

    I like to store my images on the server since it is easy to work with them that way. You could however keep them in the database if you want to and just resize the images in a tmp dir prior to inserting them into the database.

  7. Adrian Says:

    Hello,
    Any ideas why I would get this: Invalid Parameter - “100×100>”
    when I run this in my ruby code?
    `convert -thumbnail “100×100>” img.jpg _img.jpg`

    I’m on WinXP, WEBrick server for development.

    It works great at command prompt (without the backticks, of course).
    I appreciate your help.
    -Adrian

  8. tom Says:

    Hi Adrian,

    I haven’t used the convert command before. Do you get an error if you just use mogrify instead like this:

    `mogrify -thumbnail “100×100>” someimage.gif`

    Also, I would recommend removing the webserver out of the equation and just putting your code in a ruby .rb file and running it that way until you get this sorted out.

    Good luck.

    Tom

  9. nguma Says:

    Tom,
    I LOVE YOU!!!!

    It’s been three days i am hopping from blog to forum to wiki in the hope to solve my resizing problem, and then… i ended up here, on your blog.

    I really appreciate the simplicity and directness of your post. You made one of the rare complexity of ruby as easy as A B C.

    In other words, THANK YOU… very much.

    Nguma

  10. tom Says:

    Hi Nguma,

    I’m glad you found this article useful. Thanks for your feedback.

    Tom

  11. Adrian Says:

    This is probably a dumb question, but how do you get this:
    `mogrify -thumbnail “100×100>” someimage.gif`

    to find an image in another directory, for example /public/photos/temp/someimage.gif ?

    I’ve tried passing in a variable with the complete path, that currently works with imagemagick
    but this doesn’t work.

    Any help is appreciated.
    Thanks,
    Adrian

  12. Tom Says:

    Hi Adrian,

    I suspect your path is wrong. By putting in a forward slash you are saying that your public folder is at the root of your drive. If you are on a unixy system, I would guess it would be relative to /var/www/html or something. You should either specify the full path or use relative paths based on the “current dir” your webapp command line starts in. The safest is to just use the full path.

    Also, don’t forget to make sure your webapp can read/write to your image directory.

    Good luck,
    Tom

  13. Adrian Says:

    I’ve been trying to use the full path by doing this:
    (I’ve converted forward slashes to underscores below to get around the preconditions on this post.)

    temppath = “#{RAILS_ROOT}_public_photos_temps_” + basename

    temppath equates to:
    ._script_.._config_.._public_photos_temps_test.jpg

    I get this error trying to use convert (almost identical to mogrify):
    convert: missing an image filename `._script_.._config_.._public_photos_temps_test.jpg’.
    Here’s the convert line:
    `convert -thumbnail “100×100>” #{temppath}`

    If I pass this same variable path to rmagick, rmagick resizes it.
    Any thoughts?

  14. Pål Brattberg Says:

    For those of you getting stuck with the error message Invalid Parameter - “100×100>”, note that when copying the command line you get a funky version of x.

    Try and write the command line yourself instead of copying and all should be well.

  15. mahesh Says:

    hi i am new to ruby, i have developed an simple application in ror by image upload functionality, in order to display the image i want to resize the image to thumbnail size, how can i do it, i have to use Rmagic or imagemagic ?

    please respond for it

  16. tom Says:

    Hi Mahesh,

    Rmagick is just a ruby library that wraps around ImageMagick. If you are just doing a simple resize, all you need is ImageMagick and the technique I show in this article.

    Good luck,
    Tom

  17. mona Says:

    i m new to ruby. I have uploaded images in a directory and saved the file information in a table. Now i want that when i click the image it can be viewed enlaged. what should i do?
    If i want to create thumbnail where should i pet the code and how?

  18. Tom Says:

    Hi Mona,

    Welcome to ruby. Typically I will just create a thumbnail of the image when it is uploaded. You can store the thumbnail path in your database as well. Then start off by showing just the thumbnail and when they click you can show the full-size image either using javascript or in a popup.

    Good luck,
    Tom

  19. Femtalks Says:

    Thanks a lot for this tip. This is SO useful. KEEP it DRY and simple. :)

Leave a Reply