Home About

Dumb Shell Tricks no.2 Imagemagick

Created //

Tags // shell, scripts, bash, imagemagick

Imagemagick

If you do any image manipulation on the command line, you'll want to use ImageMagick.

That means: format conversion, cropping, resizing, stripping metadata (exif), etc.

It's your swiss army knife for image manipulation. It's not a new tool -- it's a solid utility that's been around for 30+ years.

Installation

On MacOS, it's easiest with homebrew. (And if you don't have homebrew installed, you definitely should! For linux people, think of it as apt-get for MacOS.)

$ brew install imagemagick

Documentation

You can find the ImageMagick documentation here. However, note that the example program name shown there is "magick". Depending on the version you install, it may be "convert" or it may be "magick".

Everything here will use "convert". If you have "magick", just replace "convert" with "magick".

My use cases

Convert png files to webp

$ convert image.png image.webp

It's that simple. Let's say you wanted to convert to jpeg instead:

$ convert image.png image.jpg

It handles pretty much any image format you can think of if.

It'll also do PDF as well, but there are some extra nuances to consider there such as flattening the image, and properly setting the DPI so the quality is good.

Convert png files to webp, and change the compression quality to 80%

$ convert -quality 80 image.png image.webp

Strip the exif data from a JPG file

E.g., strip the EXIF and other metadata, to reduce the file size without affecting the quality.

$ convert -strip image.jpg image-without-metadata.jpg

Convert a folder of png files to webp

This uses a linux "for loop" to iterate over all the png files in the current directory, and convert them to webp.

$ for file in *.png; do convert "$file" "${file%.png}.webp"; done

Show the entire metadata for an image

$ identify -verbose image.webp

You'll get something like this...

Image:
  Filename: image.jpg
  Permissions: rw-r--r--
  Format: WEBP (WebP Image Format)
  Mime type: image/webp
  Class: DirectClass
  Geometry: 896x896+0+0
  Units: Undefined
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianness: Undefined
  Depth: 8-bit
  Channels: 3.0
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
  Channel statistics:
    Pixels: 802816
    Red:
      min: 0  (0)
      max: 250 (0.980392)
...

Show just the EXIF metadata for an image

$ identify -format "%[EXIF:*]" image.jpg

You'll get something like this...

exif:ApertureValue=17/10
exif:BrightnessValue=74/25
exif:ComponentsConfiguration=...
exif:Contrast=0
exif:CustomRendered=1
exif:DateTime=2020:06:28 13:24:50
exif:DateTimeDigitized=2020:06:28 13:24:50
exif:DateTimeOriginal=2020:06:28 13:24:50
exif:DigitalZoomRatio=0/1
exif:ExifOffset=210
...

Or, instead of having to remember that command, you could just filter the results with grep.

$ identify -verbose image.jpg | grep exif

Find the width and height of an image

$ identify -format "%wx%h" image.jpg

You'll get something like this:

4032x3024

Or, just use identify without any options, and pick out the width and height from the output:

$ identify image.jpg

The output will be something like:

image.jpg JPEG 4032x3024 4032x3024+0+0 8-bit sRGB 4.90978MiB 0.000u 0:00.000

Resize an image and maintain the current aspect ratio

Let's say we have an image, and we want to resize it down so it's only 600px wide (but maintain the correct proportional height).

$ convert image.jpg -resize 600 image-600px-wide.jpg

Automate generating thumbnail images for a folder

Assume my source images are in a folder named ~/images/source.

Assume I want the thumbnails to be in a folder named ~/images/thumbnails.

I want the thumbnails to all be 100px wide. I want the filename and type to stay the same.

Assuming both of these folders exist...

$ cd ~/images/source
$ for file in *.jpg; do convert "${file}" -resize 100 ~/images/thumbnails/"${file}"; done

If I want the file type to change (e.g., to webp), we just have to make a small change.

$ cd ~/images/source
$ for file in *.jpg; do convert "${file}" -resize 100 ~/images/thumbnails/"${file%.jpg}.webp"; done

Resize the image to a square, and keep the aspect ratio, and fill the background with black

In this case, it doesn't matter if my original image is portrait or landscape, it's going to be resized to fit into a 100x100px square correctly.

$ convert image.jpg -resize 100x100 -background black -gravity center -extent 100x100 image-100x100.jpg

We can do the same thing for a folder of images like before. Assume the source images are in ~/images/source, and the thumbnails should go in ~/images/thumbnails:

$ cd ~/images/source
$ for file in *.jpg; do convert "${file}" -resize 100x100 -background black -gravity center -extent 100x100 ~/images/thumbnails/"${file}"; done

And that's it for now...

Again, short and sweet. Definitely learn imagemagick -- batch automation of image conversion is fantastic!

As for learning the shell, there are lots of resources available online.

You could start here.

// ka

You might also be interested in...