Whenever I need to convert, merge, or combine images or PDF files, I pull out my Terminal and attempt doing it first with CLI (command line interface) commands. Over time I’ve built an arsenal of CLI commands that 9/10 times does the trick faster than any other program.
Prerequisites
Most of the image manipulation commands require imagemagick and the PDF ones require poppler. Both of which are just a homebrew install away for macOS:
# image utilities
brew install "imagemagick"
# pdf utilities
brew install "poppler"
Merging
Merge images horizontally/vertically
# convert ships with imagemagick
## horizontal
convert +append image_1.png image_2.png merged
## vertical
convert -append image_1.png image_2.png merged // vertical
# using montage
# slightly better as it maintains transparency within images
## horizontal
montage 0_index.png 1_post.png -background none -tile 2x1 -geometry +0+0 PNG32:out.png
## vertical
montage 0_index.png 1_post.png -background none -tile 1x2 -geometry +0+0 PNG32:out.png
Merge images and PDFs
# convert ships with imagemagick
convert 1.png 2.pdf merged.pdf
Merge PDFs
# pdfunite ships with poppler
pdfunite output-1.pdf output-2.pdf output-3.pdf merged-1-3.pdf
pdfunite output-4.pdf output-5.pdf merged-4-5.pdf
# using native tools that comes with the macOS
"/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py" -o merged.pdf source1.pdf source2.pdf
# using ghostscript [also works with encrypted PDFs]
gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=merged.pdf source1.pdf source2.pdf source3.pdf
Splitting
Split multi-page PDF into single page PDFs
# pdfseparate & pdfunite ship with poppler
# split input.pdf into output-1.pdf output-2.pdf ... etc.
pdfseparate input.pdf output-%d.pdf
# split input.pdf from page 2 till the end
pdfseparate -f 2 input.pdf output-%d.pdf
Replacing single pages in PDF
A common usecase is to swap out a single page in a pdf. poppler
doesn’t have a
readymade command for this, instead i just use pdfseparate
+ pdfunite
for
this:
# input has 10 pages; special has 3 pages
# replace pages 5,6,7 in input with special pages
pdfseparate input.pdf input-%d.pdf
pdfseparate special.pdf special-%d.pdf
# using fish shell
for i in (seq 1 4)
pdfunite input-$i
end
Resizing/Compression
By % or boundary
# convert ships with imagemagick
convert -resize 60% src_img.png src_img_reduced.png
convert -resize 128x128 src_img.gif src_img_reduced.gif
- Doesn’t overwrite
- 60% is good for documents
- 75% is acceptable image quality (though you probably want higher)
By keeping aspect ratio & max dimension
sips -Z 800 input.png --out output.png
# Z maintain aspect ratio
# 800 max height and width to be used
In directory
# resize all images in directory
for f in *.jpeg
do
convert -resize 60% "$f" dest/src_img_reduced.png
done
Converting
DNG → JPG
# sips ships natively with macOS
sips -Z 3072 -s format jpeg input.dng --out output.jpg
# Z maintain aspect ratio
# -s format jpeg
- Overwrites
- Aggressively reduces
PNG → JPG
# sips ships natively with macOS
sips -s format png input.jpg --out output.jpeg
HEIC → JPG
# sips ships natively with macOS
sips -s format jpeg input.heic --out output.jpeg
PDF → JPG
# convert ships with imagemagick
convert -density 150 -quality 100 -flatten -sharpen 0x1.0 -trim input.pdf output.jpg
# 3rd page of pdf
convert input.pdf[2] output.jpg
# convert all pages (2 means 2 digits will show on page count)
convert input.pdf output-%02d.jpg
# pdftoppm ships with poppler
# output is a prefix
# 150 is DPI
pdftoppm -jpeg -r 150 input.pdf output
JPG → PDF
# convert ships with imagemagick
convert 1.jpg 2.jpg merged.pdf
JPG → (A4 paper size) PDF
convert -density 80 input.jpeg -background white \
-page a4 # -page Letter
output.pdf
JPG → PNG
# sips ships natively with macOS
sips -s format png input.jpg --out output.png
PNG → WEBP
# install webp utility
brew install webp
cwebp input.png -o output.webp
cwebp -q 75 input.png -o output.webp
# -q 75 refers to the compression rate.
SVG → WEBP
# convert ships with imagemagick
convert -background none -density 200 input.svg output.webp
SVG → PNG
# convert ships with imagemagick
convert -background none -density 1000 -resize 48x is_logo_location.svg is_logo_location.png
PNG → GIF
# convert ships with imagemagick
convert -delay 5 -loop 0 *.png output.gif
MOV/MP4 → GIF
# convert ships with imagemagick
mkdir frames
# mov or m4v
# ffmpeg -i input.mov -vf scale=320:-1,format=rgb8,format=rgb24 -r 10 frames/ffout%3d.png
ffmpeg -i input.mov -vf scale=320:-1 -r 10 frames/ffout%3d.png
convert -delay 8 -loop 0 frames/ffout*.png frames/output.gif
# scale [width in px]:-1
# r framerate
Manipulating
Remove transparency
# flattens png to a solid color
# mogrify ships with imagemagick
mogrify -background white -flatten input*.png
Get information from image
Is image transparent?
# identify ships with imagemagick
identify -format '%[channels]' foo.png
List image dimensions
identify -format '"%w %h' foo.png
I’ll keep adding more as I discover new use cases.