Saving space with sips

Do you know about sips, the “scriptable image processing system”? It’s a Mac-specific tool for querying and modifying images, the command-line sibling of the AppleScript Image Events library. I use it in snapftp, my screenshot/upload utility, but probably haven’t used it as much as I should directly in the Terminal. For simple manipulations, especially resizing, it’s much faster than firing up Preview or Acorn or the like.

This morning, for example, I finished up a report for a client that included 28 photographs. Each of the photos was taken with my Canon G10 at the highest resolution, so they were all 4416×3312 pixels, averaging 5-6 megabytes apiece. At that resolution, the PDF of my report would weigh in at around 150 MB, far too big to be emailed. This is where sips comes in.

First, a little background. As I write my reports, I gather all the components into a single folder, cleverly named report, inside the project folder. So the report folder has a copy of every photo that will appear in the report. That’s where pdflatex looks to get the JPEGs it incorporates into the output. About a month ago, in Part 3.5 of my slowly developing “Text files and me” series, I showed the LaTeX code that puts photos into my reports. Here’s a snippet:

\begin{plate}
\begin{center}
\includegraphics[height=3.25in]{20110408-001.jpg}
\caption{Beatles album glasses.}
\label{p20110408-001}
\end{center}
\end{plate}

\begin{plate}
\begin{center}
\begin{minipage}[c]{0.55\linewidth}
\includegraphics[height=4.25in]{20110408-002.jpg}
\end{minipage}\hfill
\begin{minipage}[c]{0.40\linewidth}
\caption{Beatles matryoshka.}
\label{pp20110408-002}
\end{minipage}
\end{center}
\end{plate}

The first stanza is for a horizontal (landscape) photo; the second is for a vertical (portrait) photo. Note the output sizes: 3.25″ high for horizontal and 4.25″ high for vertical. If I used the full resolution of my photos from the G10, they’d be

[\frac{4416}{4.25} = 1039.1]

and

[\frac{3312}{3.25} = 1019.1]

pixels per inch in the output, which is way too dense. The client isn’t interested in that level of detail and can’t print it out even if she were.1 All I really need is 800×600 images, which will be output at

[\frac{800}{4.25} = 188.24]

and

[\frac{600}{3.25} = 184.62]

pixels per inch. That’s dense enough to print well and can also be zoomed a bit when viewing onscreen.

The sips command I use to resize all the images in one shot is

sips -Z 800 *.jpg

The -Z 800 option sets the larger of the two dimensions to 800 pixels and resizes proportionally in the other direction.2 This single command resizes every JPEG in the folder. Boom. I don’t have to worry about which photos are horizontal and which are vertical; sips takes care of that automatically.

With the resized images, my report is only 3.8 MB, about one-fortieth the size it would have been and no trouble at all to mail.

Another use for sips is resizing screenshots from my iPhone for posting here in the blog. The original iPhone’s resolution of 320×480 was a perfect fit, but the iPhone 4’s Retina Display makes images that are too big. So I run them through

sips -Z 480 iphone.png

before posting. Yes, some detail is lost, but they look the right size on the lower-resolution computer screen.

There are a surprising number of Mac-specific command-line tools like sips. There’s ditto, for example, and pmset. If you’re reasonably familiar with the usual complement of Unix tools, scanning Section 1 of the OS X man pages can yield some interesting finds.


  1. On those rare occasions when the client is interested in the detail, I ship out a disk with all my photos at full resolution. 

  2. Frankly, I could probably get away with -Z 640. That would set the images to about 150 ppi in the output. Good enough for printing, but maybe a little small for onscreen viewing. 


2 Responses to “Saving space with sips”

  1. Lri says:

    Some other examples from my nv://shell:

    sips -s format png 1.icns -o 1.png
    for v in `find *.png`; do sips -s format jpeg -s formatOptions best `echo ${v%.*}.png` -o `echo ${v%.*}.jpg`; done
    sips -r 90 1.png
    sips -f horizontal 1.png
    sips -g profile 1.jpg
    

    -Z without upscaling:

    size=200;
    for v in `find *.jpg`; do
        h=`sips -g pixelHeight $v | tail -1 | sed "s/.* //"`
        w=`sips -g pixelWidth $v | tail -1 | sed "s/.* //"`
        if [[ $h -gt $size || $w -gt $size ]]; then
        sips -Z $size $v
        fi
    done
    
  2. Dr. Drang says:

    Lri,

    A nice set of examples. The downsizer is especially clever, and shows why I always go to Perl or Python when I need to do looping and branching. Never got the hang of the shell’s use of ; and [[ ]].

    Fortunately, I never have to worry about upscaling and can use -Z with impunity.