Edgar Pino

Resizing Images In Elixir with Mogrify

April 08, 2018

I’ve been working on a simple Elixir and Phoenix web app that extracts text found in images and I ran into a problem, people were uploading large images. I only needed images that were around 1200x1200 pixels.

I did some Googling around and I stumbled across Mogrify, a simple Elixir library to process images. Under the hood it uses ImageMagick, a commandline tool for displaying, converting, and editing raster image and vector image files.

Using Mogrify

Mogrify is simple and easy to use and the only requirement is to have ImageMagick installed on your computer. See installation instructions for more info.

  1. Add {:mogrify, "~> 0.5.6"} to your mix.exs file and run mix deps.get.

  2. Import it on the module you intend to use it on. Here’s how my module looks like:

    defmodule ImgToTxt.Utils.Image do
     import Mogrify
    
     @doc """
     Resize images given imagePath, width, height, and optional Mogrify opts
     """
     def resize(imagePath, width, height, opts \\ []) do
       # Continue reading
     end
    end
  3. To resize images you first open the file by give it the path to the image. When calling open, it should return something like:

    iex(3)> Mogrify.open("test/assets/test.png")
    %Mogrify.Image{
     animated: false,
     dirty: %{},
     ext: ".png",
     format: nil,
     frame_count: 1,
     height: nil,
     operations: [],
     path: "img_to_txt/test/assets/test.png",
     width: nil
    }

    Now, let’s add that to our function

    def resize(imagePath, width, height, opts \\ []) do
       open(imagePath)
    end
  4. Now that we have our file opened, let’s resize it. Mogrify provides the following functions to resize images: resize, resize_to_fill, and resize_to_limit. I choose the resize_to_limit because it will resize the image to fit within the specified dimensions while retaining the original aspect ratio. It will also only resize the image if it is larger than the specified dimensions. Let’s add that to our function:

    def resize(imagePath, width, height, opts \\ []) do
       open(imagePath)
       |> resize_to_limit(~s(#{width}x#{height}))
    end
  5. The last thing is to save our resized image by using the save function. Mogrify will save the image on a temporary file. You can change that by passing in the path as an option. See docs for more info. Lets add that to our function:

    def resize(imagePath, width, height, opts \\ []) do
      open(imagePath)
      |> resize_to_limit(~s(#{width}x#{height}))
      |> save(opts)
    end

We are done, I hope this was helpful and feel free to comment.


Edgar Pino

Software Engineer @Pluralsight. Interested in distributed systems, machine learning, and the web. Follow me on Twitter.