14. Januar 2018
Digitalbilder müssen in einer möglichst hohen Auflösung vorliegen, damit das maximale Maß an Informationen bewahrt wird, also alle Bilddetails, Farben und Schattierungen. Für viele Verwendungen ist die maximale Auflösung hingegen nicht nötig, es genügt eine verkleinerte Fassung beispielsweise als komprimierte Bilddatei im PNG- oder JPEG-Format.
Viele Programme zum Umgang mit Bildern enthalten Funktionen zur Verkleinerung von Bildern. Für eine größere Menge von Bildern auf einmal ist es aber umständlich, mit Hilfe eines Bildbearbeitungsprogrammes jedes Bild von Hand einzeln nacheinander zu verkleinern. Ein Automatismus ist wünschenswert und einige Programme haben auch solche Möglichkeiten, zum Beispiel durch Skript-Fähigkeiten oder Programmschnittstellen.
Allerdings sind solche Automatisierungsmöglichkeiten an das jeweilige Programm gebunden. Eine automatisierte Funktion zum Verkleinern für größere Mengen von Bildern sollte möglichst eigenständig funktionieren und in möglichst vielen verschiedenen Arten verwendbar sein. Dieser Praxistipp stellt deshalb eine universell verwendbare Lösung auf der Grundlage von Java-Code vor.
Übersicht
Allgemeine Beschreibung
Annahmen
Einrichten der Lösung
Verkleinern von Bildern
Vorteile
Alternativen
Fazit
Das Skript zum Verkleinern von Bildern liest Bilder im JPEG-Format aus einem Eingangsordner und wandelt sie in kleinere Bilder um. Deren verkleinerte Version schreibt das Skript in einen Ausgangsordner. Eingangs- und Ausgangsverzeichnis, gewünschte Verkleinerung und Qualität sind als Parameter frei wählbar.
Das Skript zum Verkleinern von Bildern wird zusammen mit einem Skript zum vereinfachten Aufruf in einer Ablaufumgebung für Docker hinterlegt, wie sie beispielsweise im Artikel Docker auf Core OS und VirtualBox beschrieben ist.
Zum Verkleinern einer Gruppe von Bildern genügt anschließend ein einzelnes Kommando.
Für diesen Tipp wird davon ausgegangen, dass eine per SSH erreichbare Maschine names zielrechner
besteht, die eine virtuelle Maschine namens CoreOS-Groovy
enthält. Für die virtuelle Maschine wird angenommen, dass sie angelegt wurde, wie es der zuvor erwähnte Artikel beschreibt. Ferner ist die Annahme, dass derzielrechner
einen Benutzer namens ulrich
kennt.
Die folgenden Schritte müssen nur einmal ausgeführt werden. Mit ihnen wird auf einem zentralen Rechner eine wiederverwendbare Funktion zum Verkleinern von Bildern eingerichtet.
ssh -l ulrich zielrechner
VBoxManage modifyvm "CoreOS-Groovy" --natpf1 "ssh,tcp,,3022,,22"
VBoxManage startvm "CoreOS-Groovy" --type headless
ssh -p 3022 -l ulrich zielrechner
in
und out
anlegenmkdir in
mkdir out
kleiner.sh
und bilder.groovy
vom lokalen Rechner ins Arbeitsverzeichnis der virtuellen Maschine kopierenscp -P 3022 kleiner.sh ulrich@zielrechner:.
scp -P 3022 bilder.groovy ulrich@zielrechner:.
exit
sudo shutdown -P now
exit
exit
Im Beispiel oben wird die virtuelle Maschine zur Verkleinerung von Bildern von einer Maschine namens zielrechner
bereitgestellt. Damit bei der Kommunikation via SSH die Kommandos an die virtuelle Maschine nicht mit denen an den zielrechner
vermischt werden, wird für die virtuelle Maschine eine Portweiterleitung eingerichtet. Anfragen an die virtuelle Maschine werden so über Port 3022
entgegengenommen und geraten nicht in Konflikt mit Anfragen an den zielrechner
, die standardmäßig über Port 22
laufen.
Die volle Stärke entfaltet Docker mit der Verwendung eines Dockerfiles denn es automatisiert wesentliche Teile des obigen Ablaufs. Grob gesagt werden dazu die beiden Skripte zusammen mit einem Dockerfile in ein Archiv gepackt. Dann reicht anstelle einiger der Schritte oben ein einfaches docker build
Kommando. In diesem Beitrag wurde auf diese Vorgehensweise verzeichtet, weil dies die für eine Installation erforderlichen Schritte verschleiert hätte.
Wie eine Installation wie die obige mit einem Dockerfile automatisiert wird, ist insofern eher etwas für einen weiteren Praxistipp.
Ist die Einrichtung wie oben erfolgt genügen für die Verkleinerung von Bildern die folgenden Schritte. Annahme für das Beispiel ist, dass die zu verkleinernden Bilder auf der lokalen Maschine im Ordner work/bilder/gross
des aktuellen Arbeitsverzeichnisses liegen und dass es dort einen Ordner work/bilder/klein
gibt.
ssh -l ulrich zielrechner
VBoxManage startvm "CoreOS-Groovy" --type headless
scp -P 3022 work/bilder/gross/* ulrich@zielrechner:./in
./kleiner.sh 1920 0.75 /scripts/in /scripts/out
scp -P 3022 ulrich@zielrechner:./out/* work/bilder/klein
exit
rm in/*
rm out/*
sudo shutdown -P now
exit
exit
Diese Schritte lassen sich abermals mit einem Skript automatisieren. Zuguterletzt werden einfach da, wo gerade Bilder zum Verkleinern liegen, diese in einen Bearbeitungsordner kopiert, ein Ausgangsordner für das Ergebnis angelegt und ein Skript ausgeführt, das die obigen Schritte auf diese Ordner anwendet.
Bei der ersten Ausführung lädt Docker automatisch die passenden Ablaufumgebungen für Java und Groovy ins lokale Docker-Repository der virtuellen Maschine. Die erste Ausführung dauert deshalb länger.
Auf der Maschine, die zum Ablauf der Funktion verwendet wird, muss nur VirtualBox installiert sein und nicht weiter ins System eingegriffen werden. Alle Konfigurationen sind deklarativ und Teil einer virtuellen Maschine, was die Abhängigkeit von einer bestimmten Plattform aufhebt und zudem eine wiederverwendbare und auf die jeweilige Lösung abgestimmte Ablaufumgebung schafft.
Die Verkleinerungsfunktion wird mit Java ausgeführt und benötigt über Java hinaus keine anderen Hilfsmittel wie etwa besondere Bildbearbeitungsprogramme.
Der Kern der Lösung besteht aus dem Kopieren der Bilder an einen Beabreitungsort sowie das Kommando zum Verkleinern (kleiner.sh
usw.). Es muss keine Anwendung installiert werden bzw. wird alles erforderliche von Docker zu Beginn selbsttätig geladen und bleibt im Docker-Repository der virtuellen Maschine wiederverwendbar hinterlegt. Werden zwischenzeitlich Teile dieser Ablaufumgebung, also Java oder Groovy aktualisiert, lädt Docker die aktuellen Fassungen bei der nächsten Ausführung abermals selbsttätig.
Die Einrichtung innerhalb einer virtuellen Maschine ermöglicht es, diese sehr einfach zwischen verschiedenen Maschinen zu transportieren. Die Nutzung der virtuellen Maschine und mithin die Verkleinerung von Bildern gelingt dabei komplett isoliert und unabhängig vom System der jeweiligen 'Gastgeber'-Maschine.
Durch die Verwendung von Java, VirtualBox und Docker lassen sich viele unterschiedliche andere Varianten denken, in denen die hier vorgestellte Lösung eingesetzt werden kann. Nachfolgend ein paar Ideen, die die Flexibilität des Ansatzes zeigen sollen.
Da es sich beim Code des Groovy-Skripts um normales Java handelt ist dieser gleichermaßen für den Einsatz in einer andern Anwendung verwendbar. So kann er in der selben Weise in ein Programm eingebaut werden und für denselben Zweck zum Beispiel als Teil einer Serveranwendung laufen.
Anstelle der Ausführung innerhalb von Docker kann auch einfach Groovy auf einem Rechner installiert und das Groovy-Skript ausgeführt werden. Damit ist allerdings ein Eingriff in das System eines Rechners erforderlich und die Lösung zunächst an diesen Rechner gebunden. Auf einem anderen Rechner könnte sie nur laufen, wenn dort auch Groovy installiert würde.
Die virtuelle Maschine kann ebensogut auf dem lokalen Rechner betrieben werden, dann geht der Schritt des Kopierens der Bilder in die virtuelle Maschine hinein und aus der virtuellen Maschine heraus nicht über eine vielleicht langsame Netzstrecke. Damit ist allerdings die Lösung zunächst an diesen Rechner gebunden und kann nicht ohne weiteres an zentraler Stelle von verschiedenen Rechnern aus benutzt werden.
Eine weitere Variante ist, auf der betreffenden Maschine selbst Docker zu installieren. Dann kann das Skript zum Verkleinern von Bildern direkt auf ein Verzeichnis der lokalen Maschine ausgeführt werden. Die Schritte zum Kopieren der Bilder, Anmelden am Zielrechner, Starten und Stoppen der virtuellen Maschine können dann entfallen. Allerdings hat man so auch eine deutlich engere Koppelung an diese Maschine. Bei einem einfachen Skript wie dem hier vorgestellten fällt das nicht ins Gewicht. Für eine komplexere Lösung empfiehlt sich hingegen die hier beschriebene Virtualisierung.
Anstelle von Java und Groovy kann z.B. auch ImageMagick verwendet werden, das ist Geschmackssache. Die Vorgehensweise mit VirtualBox und Docker bleibt die gleiche, nur das Kommando zur Verkleinerung lautet mit ImageMagick dann anders. Auch kann diese Variante nicht ohne weiteres in andere Programme eingebaut werden und würde beim Einbau die Installation von ImageMagick zusätzlich zum eigenen Programm erfordern.
Java ist eine universelle, wiederverwendbare Form, Lösungen für Aufgaben zu formulieren, die von einer Vielzahl von Geräten ausgeführt werden können. Die Formulierung in Form von Java-Code erhöht die Wiederverwendbarkeit für die Nutzung der Lösung in einem anderen Kontext wie z.B. eingebettet in eine Webanwendung.
Groovy ist eine praktische Ablaufumgebung für Java-Code, der eigenständig und gezielt eine bestimmte Aufgabe lösen soll.
VirtualBox und Docker sind ideale Werkzeuge um Aufgaben entkoppelt von der jeweiligen Maschine auszuführen.
Mit den Mitteln von VirtualBox und Docker lassen sich vorhandene Lösungen automatisiert auf eine Plattform bringen und unabhängig von der Zielplattform ausführen. Die Bedienung ist jeweils auf wenige Handgriffe verringert und einmal zum Laufen gebracht mit wenigen Schritten auf anderen Plattformen wiederverwendbar.
Das hier beschriebene Vorgehen zur Virtualisierung und Containerisierung kann ebenso für andere Aufgaben verwendet werden. Es ist eine Musterlösung für die Ausführung beliebiger Aufgaben mit einer virtualisierten Ablaufumgebung und nicht auf das hier vorgestellte Beispiel zur Verkleinerung von Bildern beschränkt.
Kleiner Nachtrag: Dieser Beitrag verwendet Code auf der Grundlage der Package Java ImageIO und zeigt, wie sich solcher Java-Code mit Hilfe von Docker und Groovy ausführen lässt. Wer sich nicht in die Tiefen von ImageIO begeben möchte, kann diese Teile des hier gezeigten Codes auch mit der Klassenbibliothek Thumbnailator ersetzen.