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 ""