generate-responsive-images.sh
1#!/usr/bin/env bash
2set -euo pipefail
3
4# Generate responsive image variants (WebP + JPEG) for HTML <picture> elements.
5# Requires ImageMagick 7+ (magick command).
6
7# ---------------------------------------------------------------------------
8# Defaults
9# ---------------------------------------------------------------------------
10QUALITY=80
11WIDTHS=(320 640 960 1280 1920 2560)
12
13# ---------------------------------------------------------------------------
14# Helpers
15# ---------------------------------------------------------------------------
16usage() {
17 cat <<EOF
18Usage: $(basename "$0") --input <path> --output-dir <dir> [--base-url <url>]
19
20Generate responsive WebP and JPEG image variants for HTML srcset usage.
21
22Required:
23 --input <path> Path to the high-resolution source image.
24 --output-dir <dir> Directory to write generated images (created if missing).
25
26Optional:
27 --base-url <url> Fully-qualified domain to prepend to image URLs in the
28 generated HTML snippet. Include trailing slash if desired.
29 Example: https://cdn.example.com/images/
30 --help Show this help message.
31
32Example:
33 $(basename "$0") --input ./photo.jpg --output-dir ./out --base-url https://example.com/
34EOF
35}
36
37die() {
38 echo "Error: $1" >&2
39 exit 1
40}
41
42# ---------------------------------------------------------------------------
43# Parse arguments
44# ---------------------------------------------------------------------------
45INPUT=""
46OUTPUT_DIR=""
47BASE_URL=""
48
49while [[ $# -gt 0 ]]; do
50 case "$1" in
51 --input)
52 INPUT="${2:-}"
53 shift 2
54 ;;
55 --output-dir)
56 OUTPUT_DIR="${2:-}"
57 shift 2
58 ;;
59 --base-url)
60 BASE_URL="${2:-}"
61 shift 2
62 ;;
63 --help)
64 usage
65 exit 0
66 ;;
67 *)
68 die "Unknown option: $1"
69 ;;
70 esac
71done
72
73# ---------------------------------------------------------------------------
74# Validate
75# ---------------------------------------------------------------------------
76[[ -z "$INPUT" ]] && die "Missing required flag: --input"
77[[ -z "$OUTPUT_DIR" ]] && die "Missing required flag: --output-dir"
78
79if ! command -v magick &>/dev/null; then
80 die "ImageMagick (magick) is not installed or not in PATH."
81fi
82
83if [[ ! -f "$INPUT" ]]; then
84 die "Input file not found: $INPUT"
85fi
86
87# ---------------------------------------------------------------------------
88# Prepare output directory
89# ---------------------------------------------------------------------------
90mkdir -p "$OUTPUT_DIR"
91
92BASENAME=$(basename "$INPUT" | sed 's/\.[^.]*$//')
93
94echo "Generating responsive images from: $INPUT"
95echo "Output directory: $OUTPUT_DIR"
96echo ""
97
98# ---------------------------------------------------------------------------
99# Generate images
100# ---------------------------------------------------------------------------
101for w in "${WIDTHS[@]}"; do
102 echo " -> ${w}px …"
103
104 magick "$INPUT" -resize "${w}x" -quality "$QUALITY" -strip \
105 "${OUTPUT_DIR}/${BASENAME}-${w}w.webp"
106
107 magick "$INPUT" -resize "${w}x" -quality "$QUALITY" -strip \
108 "${OUTPUT_DIR}/${BASENAME}-${w}w.jpg"
109done
110
111echo ""
112echo "Done. Generated ${#WIDTHS[@]} WebP + ${#WIDTHS[@]} JPEG images."
113echo ""
114
115# ---------------------------------------------------------------------------
116# Build srcset strings
117# ---------------------------------------------------------------------------
118WEBP_SRCSET=""
119JPEG_SRCSET=""
120
121for w in "${WIDTHS[@]}"; do
122 WEBP_SRCSET="${WEBP_SRCSET}${BASE_URL}${BASENAME}-${w}w.webp ${w}w, "
123 JPEG_SRCSET="${JPEG_SRCSET}${BASE_URL}${BASENAME}-${w}w.jpg ${w}w, "
124done
125
126# Trim trailing comma and space
127WEBP_SRCSET="${WEBP_SRCSET%, }"
128JPEG_SRCSET="${JPEG_SRCSET%, }"
129
130# ---------------------------------------------------------------------------
131# Output HTML snippet
132# ---------------------------------------------------------------------------
133cat <<EOF
134<!-- Copy and paste the following into your HTML -->
135
136<picture>
137 <source
138 type="image/webp"
139 srcset="$WEBP_SRCSET"
140 sizes="(max-width: 600px) 90vw, (max-width: 1200px) 50vw, 800px"
141 >
142 <img
143 src="${BASE_URL}${BASENAME}-640w.jpg"
144 srcset="$JPEG_SRCSET"
145 sizes="(max-width: 600px) 90vw, (max-width: 1200px) 50vw, 800px"
146 alt="${BASENAME}"
147 loading="lazy"
148 >
149</picture>
150EOF
151
152echo ""