Bilder stapelweise skalieren und konvertieren mit ImageMagick
Erstellen Sie für eine responsive Website Versionen jedes Bildes mit 480, 960 und 1.440 Pixeln Breite, jeweils als WebP und JPEG. Dieses Bash-Skript schreibt einen neuen Satz Dateien, ohne die Originale zu ändern. Auf einer kleinen HTML-Seite wählt der Browser dann aus den erzeugten Dateien.
Hier geht es darum, mehrere Größen und ein Ersatzformat für dasselbe Website-Bild vorzubereiten. Für eine einzelne PNG-Kopie pro JPEG, auch in verschachtelten Ordnern, nutzen Sie die Anleitung zur Konvertierung von JPEG in PNG.
Werkzeuge und Eingabeumfang prüfen
Verwenden Sie für diese Anleitung Bash 5.3.15 und ImageMagick 7.1.2-31 unter Linux mit einem
Dateisystem, das Groß- und Kleinschreibung unterscheidet. Führen Sie die Befehlsblöcke in Bash aus.
Installationsoptionen für ImageMagick 7 finden Sie in den
offiziellen Downloads. Ein Paket namens imagemagick
kann Version 6 bereitstellen; diese Anleitung verwendet die ausführbare Datei
magick aus Version 7. Native Windows-Shells und die ältere System-Bash von
macOS werden hier nicht behandelt.
bash --version && magick -version && magick -list format
Suchen Sie in der Formatliste nach rw für JPEG,
PNG und WEBP. Das Skript liest nicht animierte
JPEG-Dateien (.jpg oder .jpeg), PNG- und WebP-Dateien
direkt aus einem Eingabeordner, einschließlich versteckter Dateien und Dateiendungen mit gemischter
Groß- und Kleinschreibung. Es überspringt Unterverzeichnisse und symbolische Links. Jedes Bild muss
nach Anwendung der Ausrichtungsmetadaten mindestens 1.440 Pixel breit sein. Kleinere Bilder werden
abgewiesen, nicht vergrößert. Das Skript weist Sequenzen ab, die der Decoder als solche erkennt,
auch animierte WebP-Dateien. Verwenden Sie nicht animierte PNGs: Wie die
Formathinweise erläutern, liest der PNG-Decoder nur das erste
Einzelbild einer animierten PNG-Datei (APNG).
Dieses Skript erhält keine Animationen.
Die Ausgaben sind deckende 8-Bit-Bilder. Transparente Pixel werden in beiden Formaten auf einen
weißen Hintergrund gesetzt. Die Option
-colorspace sRGB von ImageMagick konvertiert die
decodierten Farben vor dem Compositing. Dies ist eine lokale Anleitung für gewöhnliche Webfotos,
kein ICC-Proofing-Workflow: Bei profilabhängigen Bildern oder Bildern mit großem Farbumfang ist
eine geeignete Konvertierung mit -profile
erforderlich, bevor Profile entfernt werden. Bewahren Sie Ihre Originale dafür auf.
Eine reproduzierbare Eingabe erstellen
Erstellen Sie in einem Arbeitsverzeichnis ein Beispielbild mit einer blauen und einer roten Hälfte.
&& verhindert das Schreiben, wenn input-images bereits
existiert. Sie können dieses Verzeichnis innerhalb eines bestehenden Projekts verwenden; die
Befehle installieren keine Pakete und ändern die Konfiguration dieses Projekts nicht.
mkdir input-images &&
magick -size 2400x1600 xc:steelblue -fill tomato \
-draw 'rectangle 1200,0 2399,1599' -depth 8 jpeg:- > input-images/hero.jpg
Legen Sie für Ihren eigenen Stapel unterstützte Bilder in den Eingabeordner und lassen Sie ihn
unverändert, während das Skript läuft. Verwenden Sie ein anderes Arbeitsverzeichnis, wenn Sie
bereits einen Ordner namens input-images haben.
Das Skript zur Stapelverarbeitung speichern
Speichern Sie Folgendes als neue Datei batch-images.sh neben
input-images. Jede Quelldatei erhält ein Verzeichnis mit ihrem vollständigen
Dateinamen: hero.jpg und hero.png bleiben getrennt.
Die Shell-Umleitung speist die Standardstreams von ImageMagick.
So bleiben Leerzeichen, führende Bindestriche, eckige Klammern und Muster wie
% in Dateinamen unverändert erhalten.
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
shopt -s nullglob dotglob
if (( $# != 2 )); then
printf 'Usage: bash batch-images.sh INPUT_DIR NEW_OUTPUT_DIR\n' >&2
exit 1
fi
# A final slash preserves directory names ending in newlines during command substitution.
input_argument=$1
[[ "$input_argument" == /* ]] || input_argument="./$input_argument"
input=$(cd -P -- "$input_argument" && printf '%s/' "$PWD")
input=${input%/}
output=$2
[[ "$output" == /* ]] || output="./$output"
files=()
for file in "$input"/*; do
[[ -f "$file" && ! -L "$file" ]] || continue
case ${file,,} in
*.jpg|*.jpeg|*.png|*.webp) files+=("$file") ;;
esac
done
if (( ${#files[@]} == 0 )); then
printf 'No supported images in %s\n' "$input" >&2
exit 1
fi
# mkdir refuses existing destinations, including existing symbolic links.
mkdir -- "$output"
stage="$output/.source.miff"
diagnostics="$output/.diagnostics"
trap 'rm -f -- "$stage" "$diagnostics"' EXIT
fail_image() {
printf 'Could not process: %s\n' "$file" >&2
cat -- "$diagnostics" >&2
exit 1
}
for file in "${files[@]}"; do
name=${file##*/}
case ${file,,} in
*.jpg|*.jpeg) coder=jpeg ;;
*.png) coder=png ;;
*.webp) coder=webp ;;
esac
# Normalize once, before resizing or discarding the source metadata.
if ! magick -regard-warnings "$coder:-" -auto-orient -colorspace sRGB \
-background white -alpha remove -alpha off -strip -depth 8 miff:- \
< "$file" 2> "$diagnostics" > "$stage" || [[ -s "$diagnostics" ]]; then
fail_image
fi
if ! dimensions=$(magick -regard-warnings miff:- -format '%n %w %h\n' info: \
< "$stage" 2> "$diagnostics") || [[ -s "$diagnostics" ]]; then
fail_image
fi
if [[ ! "$dimensions" =~ ^1\ ([0-9]+)\ ([0-9]+)$ ]]; then
printf 'Expected one still image: %s\n' "$file" >&2
exit 1
fi
if (( BASH_REMATCH[1] < 1440 )); then
printf 'Image must be at least 1440 pixels wide after orientation: %s\n' "$file" >&2
exit 1
fi
mkdir -- "$output/$name"
for width in 480 960 1440; do
for format in webp jpg; do
target="$output/$name/$width.$format"
if ! magick -regard-warnings miff:- -resize "${width}x>" -quality 82 "$format:-" \
< "$stage" 2> "$diagnostics" > "$target" || [[ -s "$diagnostics" ]]; then
rm -f -- "$target"
fail_image
fi
done
done
printf 'Created six images for %s\n' "$name"
done
printf 'Finished processing %s source image(s) in %s\n' "${#files[@]}" "$output"
Das Skript wendet -auto-orient an,
bevor es die Breite prüft. -resize '480x>'
begrenzt die Breite und bewahrt das Seitenverhältnis; die anderen beiden Größen funktionieren
genauso. Die Mindestbreite der Eingabe stellt sicher, dass alle drei Ausgaben exakt die angegebenen
Breiten haben.
-quality 82 ist eine Encoder-Einstellung,
keine visuelle Qualität von 82 % und keine zugesicherte Reduzierung der Dateigröße. Beide Ausgaben
verwenden verlustbehaftetes Encoding. Vergleichen Sie Aussehen und Byte-Größen der Dateien, bevor
Sie eine Qualitätseinstellung für echte Fotos wählen.
Die Stapelverarbeitung ausführen und Ergebnisse prüfen
bash batch-images.sh input-images web-images
Beim Beispiel wird im Erfolgsfall Created six images for hero.jpg ausgegeben, gefolgt von
Finished processing 1 source image(s) in ./web-images. Das Verzeichnis enthält hero.jpg/480.webp,
hero.jpg/960.webp und hero.jpg/1440.webp sowie die entsprechenden Dateien
mit der Endung .jpg.
Das Original input-images/hero.jpg bleibt unverändert. Ein erneuter Durchlauf lehnt das
bestehende Verzeichnis web-images ab; wählen Sie ein neues Ziel, um einen
weiteren Satz Dateien zu erstellen.
Das Skript verarbeitet Namen in der Sortierreihenfolge der C-Locale, stoppt beim ersten Fehler
und gibt einen Status ungleich null zurück, der die Quelldatei benennt.
Zuvor erfolgreich erzeugte Varianten bleiben erhalten, eine fehlgeschlagene Variante wird
entfernt. Dies ist ein unvollständiger Satz, keine veröffentlichte Version: Prüfen Sie ihn und
korrigieren Sie die Quelle, bevor Sie das Skript mit einem neuen Zielverzeichnis erneut ausführen.
Neben der Statusprüfung behandelt es auch Diagnosemeldungen als Fehler, da
-regard-warnings nur einige Decoder-Warnungen in
Fehler umwandelt. Ein Decoder kann beschädigte Inhalte dennoch ohne Diagnosemeldung wiederherstellen;
eine erfolgreiche Konvertierung beweist nicht, dass eine Eingabe unbeschädigt ist.
Prüfen Sie alle sechs Beispielvarianten, indem Sie ihre Bytes lesen, ohne Dateinamen als Muster interpretieren zu lassen:
(
set -e
for width in 480 960 1440; do
for format in webp jpg; do
file="web-images/hero.jpg/$width.$format"
printf '%s: ' "$file"
magick "$format:-" -format '%m %wx%h\n' info: < "$file"
done
done
)
Erwarten Sie WEBP 480x320 und JPG 480x320, dann dieselben Formate
mit 960x640 und 1440x960.
Öffnen Sie auch die Ausgaben: Vergewissern Sie sich, dass beide farbigen Hälften und die äußeren
Ränder vorhanden sind. Prüfen Sie bei Ihren eigenen Bildern die Ausrichtung, Motive nahe den
Rändern und den weißen Hintergrund an zuvor transparenten Stellen. Die Abmessungen allein können
diese Eigenschaften nicht belegen.
Die erzeugten Dateien auf einer responsiven Seite verwenden
Speichern Sie dieses vollständige Dokument als web-images/preview.html. Es verweist auf die
tatsächlich erzeugten Beispieldateien; öffnen Sie die Datei direkt in Ihrem Browser. Für diese
lokale Bildvorschau ist kein Server nötig.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Responsive image preview</title>
<style>
body { margin: 0; }
img { display: block; width: 100%; max-width: 960px; height: auto; }
</style>
<picture>
<source type="image/webp"
srcset="hero.jpg/480.webp 480w, hero.jpg/960.webp 960w, hero.jpg/1440.webp 1440w"
sizes="(max-width: 960px) 100vw, 960px">
<img src="hero.jpg/960.jpg"
srcset="hero.jpg/480.jpg 480w, hero.jpg/960.jpg 960w, hero.jpg/1440.jpg 1440w"
sizes="(max-width: 960px) 100vw, 960px"
width="1440" height="960" alt="Blue and red halves of a sample image">
</picture>
</html>
Die Regeln für picture und srcset
lassen einen Browser mit WebP-Unterstützung aus der ersten Quelle wählen;
img liefert JPEG-Kandidaten und einen Standardwert für
src. Jeder Deskriptor w gibt die tatsächliche
Pixelbreite der Datei an. sizes beschreibt die angezeigte Breite passend
zur CSS-Begrenzung auf 960 Pixel. Ändern Sie die Pfade, den Alternativtext, das Verhältnis von
width zu height und sizes,
wenn Sie dies an Ihre eigene Seite anpassen. Verwenden Sie URL-Kodierung für Dateinamen mit
Sonderzeichen: Ein Verzeichnis namens photo%03d.jpg benötigt in einer URL
photo%2503d.jpg/480.webp.
Um die ausgewählte Datei zu prüfen, öffnen Sie die Entwicklerkonsole des Browsers und führen Sie Folgendes aus:
document.querySelector('img').currentSrc
Probieren Sie eine frisch geladene Seite mit einem schmalen Viewport aus, dann mit einem breiteren.
Auch das Geräte-Pixelverhältnis und die Auswahlstrategie des Browsers beeinflussen die Auswahl;
beim Ändern der Größe einer bereits geladenen Seite kann ein größeres Bild aus dem Cache erhalten
bleiben. Wenn Sie das Element source in einer temporären Kopie entfernen,
können Sie die JPEG-Auswahl im selben Browser prüfen. Eine defekte WebP-URL führt nicht automatisch
zur Auswahl des JPEG-Ersatzformats.
Halten Sie den vollständigen Satz der Varianten zusammen, wenn Sie das Markup in Ihre Website übernehmen. Die lokale Vorschau demonstriert die Dateierzeugung und die Browserauswahl; messen Sie Ihre tatsächliche Seite, wenn Sie eine Verbesserung der Ladezeit oder des Bandbreitenbedarfs belegen möchten.
