
Responsive Images — Erstellung
Veröffentlicht am von Philipp Weyer in Querbeet
Für eine Webseite ist es sinnvoll, dass Bilder in verschiedenen Auflösungen bereitgestellt werden, um die Nutzererfahrung so positiv wie möglich zu gestalten. Kleine Anzeige, kleines Bild laden, große Anzeige, großes Bild laden. Gerade für mobile Nutzer ist es wieder wichtig, auf die Gesamt-Download-Größe der Seite zu achten und Bilder haben daran nun mal den größten Anteil.
Hier nun meine Art, diese Bilder möglichst bequem zu generieren.
Rahmenbedingungen
Ich arbeite auf einem System mit Windows 10 und habe von meinem Vorgehen nach Foto-Touren einen Ordner mit aus Lightroom exportierten Fotos im JPEG-Format. Sie haben je nach Beschnitt völlig unterschiedliche Größen und liegen im Hoch- oder Querformat vor.
Das Ziel
Im Explorer markierte Objekte (Ordner oder Dateien) sollen über das Kontextmenü mit „Senden an“ zu einem Skript gereicht werden, welches dann alle *.jp(e)g
-Dateien in die angegebenen Größen konvertiert. Dabei wird nur die Breite vorgegeben, die Höhe passt sich so an, dass das Seitenverhältnis beibehalten wird.
Der eigentliche Vorgang der Konvertierung wird mit imageMagick bzw. dessen Tool convert
durchgeführt. Bei einem Seitenverhältnis von 3 : 2 sind folgende Auflösungen gewünscht: 1200 × 795, 800 × 530 und 400 × 265. Dabei ist darauf zu achten, dass die Bilder im Hoch- bzw. Querformat bleiben.
Das Programm
Für Ungeduldige gibt es hier eine Abkürzung zum Download.
Parameter sortieren
Da über das „Senden an“-Menü sowohl Ordner als auch Dateien geschickt werden können, müssen wir gleich zu Beginn die erste Kontrolle einbauen (und die erste Einschränkung hinnehmen). Liegt ein Ordner oder ein Bild vor? Entscheidend ist hierbei ausschließlich der erste Parameter, der übergeben wird. Bei gemischten Angaben werden beim Durchlauf des Skripts Fehler (wegen falschen Aufrufs von imageMagick) ausgegeben.
Der Funktion :MKRESDIR
zum Anlegen eines neuen, eindeutigen Ordners für die konvertierten Bilder wird mit dem aktuellen Pfad des Bildes (%~dp1
) aufgerufen.
Das Konstrukt :LOOP
, …, SHIFT
, goto :LOOP
sorgt dafür, dass alles dazwischen stehende nacheinander für jeden Parameter (jede/r Datei/Ordner) durchgeführt wird. Ist der letzte Parameter verarbeitet, schlägt die erste Kontrolle an und wir springen zum Ende der Datei mit goto :END
.
Im sich wiederholenden Block wird mit %~x1
die Dateiendung auf Gleichheit mit JP(E)G geprüft, mit %~dp1
der Pfad des Bildes gesetzt und die Funktion :DECIDE
mit dem kompletten Dateinamen (%~nx1
) aufgerufen.
1if not exist %1\NUL (
2 call :MKRESDIR %~dp1
3 :LOOP
4 if "%1" == "" (
5 goto :END
6 )
7 if "%~x1" == ".jpg" (
8 set pathnow=%~dp1
9 call :DECIDE %~nx1
10 )
11 if "%~x1" == ".jpeg" (
12 set pathnow=%~dp1
13 call :DECIDE %~nx1
14 )
15 SHIFT
16 goto :LOOP
17)
Sind Ordnerpfade bei der Batch-Datei angekommen, kümmert sich der folgende Code darum, dass für jedes JP(E)G im Ordner die Funktion :DECIDE
aufgerufen wird. Die eingesetzte for
-Schleife generiert mit dem dir
-Befehl zunächst eine Liste aller Dateien mit der Endung .jp*g
und arbeitet diese Liste dann ab.
1 else (
2 :LOOP2
3 if "%1" == "" (
4 goto :END
5 )
6 set pathnow=%1
7 call :MKRESDIR %1
8 for /f %%f in ('dir /b %1\*.jp*g') do (
9 call :DECIDE %%f
10 )
11 SHIFT
12 goto :LOOP2
13)
14goto :END
Damit sind alle Parameter verarbeitet, geht es mit goto :END
an die entsprechende Sprungmarke am Ende der Datei.
Was machen aber nun die Funktionen? Werfen wir einen Blick darauf!
Ordner anlegen
Versuchen wir es zunächst mit einem Standard-Namen (hier resize
) für den Ziel-Ordner. Existiert ein solcher Ordner bereits, erstellen wir einen anderen Ordner, der über die aktuelle Zeit einen eindeutigen Namen hat (und damit noch nicht existieren sollte): resize-HH-MM-SS
.
Für den Fall, dass auch dieser Ordner schon existieren sollte, wird er dennoch verwendet und ggf. vorhandene Dateien überschrieben. Mit der letzten Zeile goto :EOF
geht es zurück an die Stelle, welche die Funktion aufgerufen hat.
1:MKRESDIR
2 if not exist "%1\resize" (
3 mkdir %1\resize
4 set resdir=resize
5 ) else (
6 set resdir=resize-%time:~0,2%_%time:~3,2%_%time:~6,2%
7 mkdir %1\!resdir!
8 )
9 goto :EOF
Die Entscheidung
Jetzt informieren wir den Nutzer darüber, welche Datei gerade bearbeitet wird und setzen zwei Variablen, die Höhe und die Breite des Bildes in Pixeln. Die lange Konstruktion ist notwendig, da ein einfaches set height=indentify...
nicht funktioniert - Batch ist alt!
Wenn die Höhe geringer oder gleich der Breite ist, handelt es sich um ein Bild im Querformat (engl. landscape), sonst um ein Hochformat (engl. portrait). Je nachdem, welche Format vorliegt, wird die Funktion :CONIMGS
dreimal mit den entsprechenden Parametern aufgerufen. Zuerst der Pfad, dann die Breite der Ausgabe in Pixeln und dann das an den Dateinamen angehängte Suffix.
1:DECIDE
2 echo Working on file %1...
3 for /f "delims=" %%a in ('identify -format %%h %pathnow%\%1') do @set height=%%a
4 for /f "delims=" %%a in ('identify -format %%w %pathnow%\%1') do @set width=%%a
5 if !height! LEQ !width! (
6 call :CONIMGS %pathnow%\%1 %landsmall% small
7 call :CONIMGS %pathnow%\%1 %landmedium% medium
8 call :CONIMGS %pathnow%\%1 %landlarge% large
9 echo.
10 ) else (
11 call :CONIMGS %pathnow%\%1 %portsmall% small
12 call :CONIMGS %pathnow%\%1 %portmedium% medium
13 call :CONIMGS %pathnow%\%1 %portlarge% large
14 echo.
15 )
16 goto :EOF
Nach dem dreimaligen Aufruf wird mit echo.
ein Zeilenumbruch in der Ausgabe erzeugt.
Aufruf von imageMagick
Beim Aufruf der Funktion :CONIMGS
wird der Nutzer darüber informiert, welche Auflösung gerade gerendert wird und welches Suffix die Datei erhalten wird. Mit dem Konstrukt echo|set /p d=TEXT
wird der Text ohne abschließenden Zeilenumbruch ausgegeben.
Anschließend wird der convert
-Befehl von imageMagick aufgerufen. Ein wesentlich kürzerer Aufruf wäre möglich mit convert INPUTFILE -thumbnail BREITE OUTPUTFILE
, die hinzugefügten Bilder sorgen jedoch für eine minimale Dateigröße, was ja unter anderem ein Grund für dieses ganze Skript ist — wer will schon mehrere 5 MB große Bilder für einen Artikel laden?
1:CONIMGS
2 echo|set /p dummy=%2 (%3) px...
3 convert %1 -filter Triangle -define filter:support=2 -thumbnail %2 -unsharp 0.25x0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -interlace none -colorspace sRGB %~dp1%resdir%\%~n1-%3%~x1
4 goto :EOF
convert
Meta-Daten
Die Option -thumbnail
sorgt dafür, dass auch sämtliche Meta-Daten (z. B. EXIF und IPTC) der Bilder entfernt werden. Für Vorschauen sind diese Daten auch unnötig. Möchte man diese Daten aber behalten, weil man dem interessierten Betrachter die Möglichkeit geben will sie zu studieren, so ersetze -thumbnail
mit -resize
— weitere Änderungen sind nicht nötig. Die Dateien sind dann jedoch nach meinen Erfahrung bis zu 30 KB größer als vorher.
Der Code, komplett
Nachdem mit den Code-Schnipseln von oben noch immer einiges an Copy & Paste-Arbeit zu erledigen wäre, hier das komplette Skript zum Download. Es wird ein eindeutiger Unterordner angelegt, dorthin werden die Bilder konvertiert und mit der Namenserweiterung -small
(400/265 Pixel), -medium
(800/530 Pixel) bzw. -large
(1200/795 Pixel) angelegt.
Einbau in das Kontextmenü
Speichere eine oder beide Skripte an einem geeignet erscheinenden Ort und lege jeweils eine Verknüpfung an. Wähle den Namen der Verknüpfung mit Bedacht — das ist der angezeigte Eintrag im „Senden an“-Menü. Dazu öffne ein Explorer-Fenster und gib in die Adresszeile shell:sendto
ein und bestätige mit Enter
. Kopiere die Verknüpfung(en) in den sich öffnenden Ordner. Fertig.
Quellen
Auf die Parameter zum Aufruf von imageMagick
bin ich nicht selbst gekommen, das smashingmagazine hat da hervorragende Vorarbeit geleistet und verdammt viele Parameter durchprobiert und die Ergebnisse verglichen.
Viel Erfolg beim nachmachen!