Automating image resizing and format conversion with ImageMagick
Use ImageMagick to fit JPEGs inside an 800 × 600 box and save PNG copies while keeping the originals. Start with a flat folder, then use the Bash script below to process nested folders without losing files that share a name. Each example creates a new output directory and refuses to reuse it.
PNG is useful when the next step in your workflow needs lossless image storage. Converting a JPEG to PNG does not recover detail already lost to JPEG compression or guarantee a smaller file. If your goal is smaller photographs for a website, see the JPEG recipe.
Set up ImageMagick 7
These examples require Bash, find, and ImageMagick 7 with JPEG and PNG support. They were tested
on macOS with ImageMagick 7.1.2-31 and Bash 3.2.57 and 5.3.20. Run the command blocks in Bash;
macOS Terminal may otherwise start a different shell.
With Homebrew installed, use ImageMagick’s macOS installation instructions:
brew install imagemagick
On Linux, check your distribution’s version before installing. For example,
Ubuntu 24.04’s imagemagick package provides version 6.
These commands require version 7; consult the official downloads
if your package does not provide it.
ImageMagick also has a Windows installer, but this walkthrough does not cover PowerShell or Command Prompt. A Windows installation alone does not provide the Bash environment used here.
Check the installed version and available formats:
magick -version && magick -list format
Look for ImageMagick 7 in the version line and rw in the mode column for both JPEG and PNG.
If magick is missing, fix the installation or PATH before continuing.
Resize and convert a flat folder
In your working directory, create an input folder and put a few JPEGs in it. This setup command also accepts an existing input directory and does not change its contents:
mkdir -p input_images
The short commands process non-hidden, lowercase .jpg files directly inside input_images.
For nested folders, other JPEG extensions, or names containing brackets or wildcard characters,
use the recursive script instead.
mogrify normally overwrites its input files.
Here, -path directs the PNG copies into a new directory. The && prevents conversion if that
directory already exists or cannot be created:
mkdir resized_png &&
magick mogrify -regard-warnings -define registry:filename:literal=true \
-auto-orient -resize '800x600>' -format png -path resized_png ./input_images/*.jpg
-auto-orient applies the JPEG’s EXIF orientation before resizing.
-regard-warnings makes warnings
such as a truncated JPEG fail the command. A failure can leave partial output; inspect it before
using the batch. Fix the input and choose a new output directory for another run.
The literal filename setting stops output
names such as photo%03d.png from becoming photo000.png. Quoting shell arguments alone does not
disable ImageMagick’s filename formatting.
The resize geometry 800x600> preserves
aspect ratio and only shrinks images that exceed the box. Quote it so Bash does not interpret >
as output redirection. To limit width alone, use '800x>' instead.
| Input dimensions | Output dimensions with 800x600> |
|---|---|
| 1600 × 900 | 800 × 450 |
| 1200 × 1600 | 450 × 600 |
| 320 × 240 | 320 × 240 |
Check what was written:
magick identify -format '%f: %m %wx%h\n' ./resized_png/*.png
For example, a 1600 × 900 wide.jpg produces wide.png: PNG 800x450. The bounding box is a limit,
so the output need not be exactly 800 × 600.
Automate nested folders
A recursive find followed by mogrify -path would flatten the directory tree: trip/photo.jpg
and work/photo.jpg could overwrite each other. This script preserves subdirectories and appends
.png to the complete source filename, keeping photo.jpg and photo.jpeg distinct too.
Save this as a new file named process_images.sh beside input_images. Keep the output directory
outside the input tree. It must not already exist.
#!/usr/bin/env bash
set -euo pipefail
INPUT_DIR="input_images"
OUTPUT_DIR="output_images"
if [[ ! -d "$INPUT_DIR" ]]; then
printf 'Input directory not found: %s\n' "$INPUT_DIR" >&2
exit 1
fi
mkdir "$OUTPUT_DIR"
find "$INPUT_DIR" -type f \( -iname '*.jpg' -o -iname '*.jpeg' \) -print0 |
(
found=false
while IFS= read -r -d '' file; do
found=true
relative=${file#"$INPUT_DIR"/}
output="$OUTPUT_DIR/$relative.png"
mkdir -p "${output%/*}"
# Capture diagnostics separately from PNG bytes; warnings also reject the image.
if ! diagnostics=$(magick -regard-warnings jpeg:- -auto-orient -resize '800x600>' png:- \
< "$file" 2>&1 > "$output") || [[ -n "$diagnostics" ]]; then
rm -f "$output"
printf 'Could not convert: %s\n%s\n' "$file" "$diagnostics" >&2
exit 1
fi
done
if [[ "$found" == false ]]; then
printf 'No JPEG files found in %s\n' "$INPUT_DIR" >&2
exit 1
fi
)
printf 'Images have been resized and converted into %s\n' "$OUTPUT_DIR"
Run it from the directory containing the script and input_images:
bash process_images.sh
For example, input_images/trip/photo.jpg becomes output_images/trip/photo.jpg.png.
The script accepts .jpg and .jpeg in any letter case. find -print0 and read -d '' preserve
spaces and line breaks, while shell redirection keeps names such as -cover.jpg and
photo%03d.jpg literal on both input and output. ImageMagick’s
standard streams carry the JPEG and PNG bytes.
The script checks conversion diagnostics as well as exit status, so it rejects a truncated JPEG
even if ImageMagick only prints a warning. It reports completion only after the whole pipeline
succeeds. pipefail also catches an unreadable directory reported by find. A missing input
directory, no matching JPEGs, or a failed conversion returns a nonzero status. The failed image’s
output is removed; earlier successful outputs remain. Review a failed batch and choose a new
OUTPUT_DIR before retrying. Use this workflow for local batches of ordinary still JPEGs.
Adapt the output for your website
These two optional commands use the same flat input_images folder as the first example. Each
requires its own new destination and leaves the originals alone. A failed command can leave a
partial batch, just as with resized_png.
Creating thumbnails
For square thumbnails, fill the square with '150x150^', then crop from the center using
-gravity center -extent 150x150. This can enlarge small images and crop away subjects near an edge:
mkdir thumbnails &&
magick mogrify -regard-warnings -define registry:filename:literal=true \
-auto-orient -resize '150x150^' -gravity center -extent 150x150 \
-format jpg -path thumbnails ./input_images/*.jpg
Optimizing images for the web
To keep photographs as JPEGs, combine the bounding box with a JPEG quality setting:
mkdir optimized &&
magick mogrify -regard-warnings -define registry:filename:literal=true \
-auto-orient -resize '800x600>' -quality 85 -path optimized ./input_images/*.jpg
-quality 85 is an encoder setting on the
JPEG quality scale, not a promise of 85% visual quality or a particular file-size reduction.
Re-encoding JPEGs is lossy. Compare the resulting bytes and appearance with your originals before
choosing a setting; a source that is already heavily compressed may become larger.
If the output looks wrong, check orientation metadata first, then confirm whether you wanted a bounding box or a square crop. If a command refuses to run again, check its destination: these examples deliberately require a new output directory to protect the previous result.
