In this article, I am going to walk you through a simple technique for resizing images on the server in your Ruby On Rails app using MiniMagick. I have previously written about a technique for resizing images using javascript on the client, but I prefer the server method when possible.

MiniMagick is a ruby gem/plugin that is a wrapper around a great ruby image library called ImageMagick. There is also another well known library called RMagick that wraps ImageMagick that includes a lot more features. I chose MiniMagick for my case since I am on a shared host and the memory footprint is much smaller for MiniMagick since it basically just wraps the ImageMagick command line utilities.

Prerequisites

So, before we get started, make sure you have ImageMagick installed on your machine.

MiniMagick comes as both a gem and a plugin. Choose the one that makes sense for your project and install it. In my case, I chose the plugin since I wanted to keep MiniMagick checked in with my code in subversion.

To install the MiniMagick plugin, just download the plugin zip and extract it into your vendor/plugins directory. Please read up on the NOTES at the bottom of this article before you go for a few bugs I found with the plugin and how to fix them.

Usage

In my case, I decided to create a separate Image model for managing my images. In my Image model, I added this resize method:

def self.resize(path)
  image = MiniMagick::Image.new(path)
  w, h = image['%w %h'].split
  w = w.to_f
  h = h.to_f
  @@max_size = 100
  if (w > @@max_size || h > @@max_size)
    if (w > h)
      h = (h*(@@max_size/w)).to_i
      w = @@max_size
    else
      w = (w*(@@max_size/h)).to_i
      h = @@max_size
    end
    image.thumbnail "#{w}x#{h}"
  end
end

Now, let’s break down some of the more interesting parts:

image = MiniMagick::Image.new(path)

The above line is used to create a new MiniMagick Image object. By using the new method, I will be manipulating the actual image file on disk rather than working on a copy. If you wanted to work on a copy without modifying the original image you could the MiniMagick::Image.from_file(path) instead. When working on a copy, you would also have to use the MiniMagick::Image.write(path) method to save your image after the manipulations.

w, h = image['%w %h'].split

This line is used to grab the image width and height. The array ([]) syntax of the MiniMagick::Image class is really just a wrapper around the identify utility in ImageMagick. For a full list of options, refer to this documentation.

The remainder of that method up until the line below is just an algorithm for resizing the image to no larger than 100px on its largest side. It maintains the aspect ratio as well.

image.thumbnail "#{w}x#{h}"

The line is used to actually resize the image based on our new computed width and height. The MiniMagick::Image library exposes all of the options provided by the ImageMagick mogrify utility. For a full list of options for mogrify refer to this documentation. If you chose to create your image using the MiniMagick::Image.from_file(path) method, here is where you would write your image back to disk.

And that’s it! You should be happily resizing images using MiniMagick in no time.

NOTES: At the time of this posting, the MiniMagick plugin had a few bugs, which I have logged:

  1. In the init.rb, change this line:
    require 'mini-magic'
    

    to:

    require 'mini_magic'
    
  2. If you are using the MiniMagick::Image.write method, you will need to add the “rb” (read binary) option to the open statement within it. The final write method should read as follows:
    def write(output_path)
      open(output_path, "wb") do |output_file|
        open(@path, "rb") do |image_file|
          output_file.write(image_file.read)
        end
      end
    end
    

8 Responses to “Resizing Images With MiniMagick”

  1. atom thoughts » Blog Archive » Dead Simple Image Processing with ImageMagick Says:

    […] 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. […]

  2. Brandon Martinez Says:

    Couldn’t you just use the geometry function to constrain to a dimension instead of reprogramming that function? http://www.imagemagick.org/script/command-line-options.php#geometry

  3. Brandon Martinez Says:

    I take that back, if you just do thumbnail “100×100″ it will be no larger than 100. Unless you don’t want to scale small images. Oh well, idk :P

  4. tom Says:

    Hi Brandon,

    The main reason for that function was to maintain the aspect ratio. However, since I wrote that article I found that just by adding a ‘>’ to the command it will maintain the aspect ratio like:

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

    Tom

  5. Marek Says:

    dang it, why are there so many rails and ruby stuffs that are badly documented. buggy (stupid bugs some more). memory leaks (rmagick, typo). yuck.

    thanks for this tutorial. saves a lot of souls.

  6. sandy Says:

    Hi….

    i got following error while uploadin image

    ImageMagick command (identify C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/minimagic4892-0 ) failed: Error Given 256

    what will be reason for that ..please reply me as soon as possible…thax

  7. Mike Says:

    Sandy, I get the same error. I can create a username on gullery, but I get this error when I upload. I’m running it on windows vista.

    Anyone please help!

  8. Tom Davies Says:

    Hi Sandy and Mike,

    I did a quick search and it looks like Error Code 256 means ImageMagick is not installed properly. I would try reinstalling it if you are able. To troubleshoot, I would recommend using ImageMagick directly from the command line like so:

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

    That should hopefully give you the same error you are seeing.

    Good luck,
    Tom

Leave a Reply