Scripted Image Manipulation

TL;DR

If you’re looking for a way to control JPEG compression quality via sips, here’s an example:

sips -s format jpeg -s formatOptions 60 image.jpg --out new-image.jpg

formatOptions can either be a number from 0–100 or strings that equate to different values (e.g. normal is equal to 50 and high is equal to 60).

The Long Version

My go-to utility for messing with images via the command line has always been ImageMagick. It’s cross-platform and has libraries for just about every language under the sun. This has been imporant to me since the main place I’ve made use of it is for resizing uploaded images in web applications.

Today, however, I was looking for a way to do a bunch of bulk image manipulation in Jekyll from my personal machine. My first reaction was to use ImageMagick but when I went to run it I realized I hadn’t installed it. Since installing utilities like ImageMagick via Homebrew isn’t exactly an instantaneous process, I used the power of Google to see if I had some kind of built in option with OS X.

As it turns out, I did. OS X ships with a command-line utility called sips. In addition to already being installed, a little bit of reading indicates that sips is probably the way to go on OS X over ImageMagick in terms of speed and memory usage.

The idea is to create some kind of process in Jekyll that takes some very high resolution photos (weighing in at 5–6MB) and create a few different sizes for different media queries. sips fits the bill. (I’ll cover the specifics of how I accomplish this in Jekyll in a later post.)

What didn’t fit the bill is that OS X specific command-line tools take options that don’t feel exactly UNIX-y (diskutil, I’m looking at you), particularly in the way they take parameters. sips is no exception. My initial assumption is that there would be an intuative option like --quality and that would be that. Wrong.

What’s worse is that Google has made me an incredibly lazy person and finding a way to modify the compression quality of JPEGs took a little more time than I wanted (i.e. more than one search and more than one page of results). Additionally, there was some experimentation involved to make sure it worked as expected as none of the examples I found used numbers, only values like normal and best.

In an effort to save someone all of a two minutes and empower their own Google-enabled laziness I’ve written the above example.

You’re welcome, even if you probably never read this part!