Im heutigen Artikel des CLI-Adventskalenders machen wir uns ein Bild zu ImageMagick.
Ah die Adventszeit! Zeit der Familienbilder! Zeit, riesige Fotosammlungen hastig in ein 36-seitiges Fotobuch für Familienmitglieder einzudampfen. Wenn es doch nur ein Werkzeug gäbe, das den Umgang mit mehreren tausend Fotos effizient gestaltet, keine nervige GUI hat und keine monatlichen Abogebühren erfordert. So ein Tool vom Kaliber eines diese Unix-Tools, dass es eventuell schon seit Jahrzehnten gibt. So wie GIMP, nur für die Kommandozeile …
ImageMagick
Ok, genug rumgealbert. Zeit, ImageMagick zu installieren und loszurocken.
Runter rendern.
Rechnen wir mal alle unsere jpgs auf 800 mal 600 Pixel runter.
find . -maxdepth 1 -name '*.jpg' -exec sh -c 'convert "$0" -resize 800x600 "${0%.jpg}_mini.jpg"' {} \;
Oder erstmal nur eines, der Übersicht halber.
convert bild.jpg -resize 800x600 bild_mini.jpg
Oder vielleicht will man ein Foto auch einfach nur für das Web herunter rechnen?
convert bild.jpg -quality 75 bild_web.jpg
Zuschneiden. Rotieren.
Ich habe hier ein Bild einer freundlichen Kuh von unsplash heruntergeladen. Ich finde, sie hat ein Pause verdient. Legen wir sie doch mal auf den Rücken.
convert kuh.jpg -rotate 180 bild_richtig_rum.jpg
Ok, das sieht mehr aus wie Spider-Kuh, aber schon irgendwie cool.
Und was, wenn ich ein Bild lieber zuschneiden als herunterskalieren möchte?
convert kuh.jpg -crop 800x600+50+50 bild_ausschnitt.jpg
Wir schnappen uns hier unsere 800 mal 600 Pixel vom Startpunkt (50,50) von der unteren linken Ecke. Hm … was kann man den noch so alles damit machen?
Wasserzeichen und Stempel
Was wäre ein Bild ohne ein Logo? Geklaut. Jawohl!
convert kuh.jpg mayflower_logo.png -gravity southeast -geometry +10+10 -composite bild_mit_stempel.jpg
Hinweis: Das soll hier nur aus Beispiel dienen und stellt keinen Rechtsanspruch dar. Bitte nicht abmahnen, ok? Danke!
Das packt unseren Stempel in die untere Ecke. Wenn wir vorher unser Logo etwas transparenter machen, sieht es aus wie ein Wasserzeichen.
convert mayflower_logo.png -fuzz 0% -fill "rgba(255,255,255,0.5)" -opaque white mayflower_logo_durchsichtig.png
Ich habe hier das Weiß und nur das reine Weiß (-fuzz 0%
) durch ein neues Weiß ersetzt, das 50% durchsichtig ist.
Und wenn wir wirklich sicher gehen wollen, dass Leute dieses Logo nicht einfach heraus editieren (außer mit Hilfe moderner KI-Werkzeuge, mit denen das dann immer noch geht, aber das ist ein anderer Blog-Artikel)?
convert mayflower_logo_durchsichtig.png -borderColor None -border 200 -resize x300 kleines_logo.png convert -size $(identify -format "%wx%h" kuh.jpg) tile:kleines_logo.png kachel_logo.png convert kuh.jpg kachel_logo.png -composite output.jpg
Bitte schalten Sie jetzt Ihre Endlosschleife ein
Mühselig, den Befehl einzutippen, ihn auszuführen, dann manuell ein Bildansichtsprogramm aufzurufen, um dann wieder zur Kommandozeile zurückzukehren … Das ist kein sinnvolles Arbeiten.
Der cron
-Artikel dieses Adventskalenders zeigt inotifywait
, womit sich Feedback-Loops extrem verkürzen lassen. Ich benutze feh
feh --auto-reload -Z output.jpg
… den leichtgewichtigen Imageviewer, bei dem das automatische Nachladen aus der Tüte fällt.
Wie schon im awk-Artikel beschrieben ist ein Editor, ein Output-Fenster und im Hintergrund laufende Automatisierung eine um Welten bessere User-Erfahrung, um „im echten Leben“ – „in der realen Welt“, „im Geschäftsalltag“ – mit der Kommandozeile zu arbeiten.
Geht das auch ohne GUI?
„Aber Eric? Ist das nicht technisch gesehen ein GUI-Tool?“ Wer Bilder direkt im Terminal anschauen möchte, holt sich am besten einen Terminal-Emulator, der Bilder unterstützt (kitty, iterm2, WezTerm, …). Nachdem ueberzug leider nicht mehr maintained wird (Open-Source-Developer-Burnout ist ernst und real), kann man sich ansonsten mit dem Drop-in-Replacement ueberzugpp oder mit z. B. mit viu oder w3m-img behelfen, die je nach verfügbaren Technologien (z. B. sixel-Support) unterschiedlich gute Ergebnisse liefern … womit wir wieder bei Terminal-Emulatoren wären.
„Das ist mir auch zu GUI, gib mir reines Linux direkt in die Pulsader!“ Wer grafischen Oberflächen komplett Adieu sagen machte, kann mit fbiviewer
Bilder direkt in den framebuffer schreiben. Mit ffmpeg kann man hier sogar Videos anschauen. Das geht logischerweise nur dann, wenn man keinen X-Server, keinen Wayland, etc am Laufen hat.
Linux im reinen Text-Mode hat eine Reihe von Einschränkungen. Nicht zuletzt deshalb, weil sich bisher niemand gefunden hat, um es zu maintainen und weiterzuentwickeln.
Mehr wissen
convert kuh.jpg -format %c histogram:output.jpg
Es ist möglich, schnell eine Menge nützlicher Informationen über ein Bild zu bekommen.
identify --verbose kuh.jpg
Was bedeutet, dass man nur einen grep davon entfernt ist, wichtige Infos automatisch aus einer Datei und ein find, ein xargs und ein grep entfernt, um besagte Infos automatisch aus vielen Dateien zu beziehen.
Farbkorrektur
Elementare Farbverbesserungen sind in ImageMagick mit allen Features kommerzieller Alternativen möglich. Beispielsweise lassen sich nicht nur Helligkeit und Kontrast anpassen.
convert kuh.jpg -brightness-contrast 20x50 output.jpg
… sondern auch Farbstufen.
convert kuh.jpg -level 20%,80%,0.5 output.jpg
Oder HSV …
convert kuh.jpg -modulate 50,170,50 output.jpg
… und Farbbalance.
convert kuh.jpg -channel R -gamma 0.3 -channel G -gamma 1.9 -channel B -gamma 1.2 output.jpg
Und natürlich kann man auch sein Glück mit der automatischen Farbjustierung probieren:
convert kuh.jpg -auto-level output.jpg
Zeit für ein Meme
Für manche Anwendungsfälle gibt es bereits spezialisierte Software. Memes kann man besser mit bereits geschriebenen Tools machen die automatisch Text runterskalieren, um in eine vordefinierte Box zu passen.
Für alle die es trotzdem wissen wollen …
convert challenge_accepted.jpg -pointsize 30 -fill white -stroke black -strokewidth 2 -annotate +20+30 "Meme using imagemagick?" -pointsize 40 -annotate +20+280 "Challenge accepted" output.jpg
Zensur!
Wer automatisiert persönliche Daten aus einem Stapel gescannter Dokumente herauszensieren möchte, kann auch zu ImageMagick greifen.
convert kuh.jpg -fill black -draw 'rectangle 250,300 450,370' output.jpg
Mit ein bißchen basteln (und Kopfrechnen) bekommt man auch einen Verpixelungseffekt hin.
convert kuh.jpg \( +clone -crop 250x300+1250+550 -scale 5% -scale 2000% \) -geometry +1250+550 -composite output.jpg
Ein Gemälde von einem Bild von einer Kuh
Manchmal möchte man einfach nur schnell einen Bildfilter auf etwas draufpacken, um einen schnellen, visuellen Effekt ohne viel Arbeit zu bekommen. ImageMagick hat eine tiefe Bibliothek davon:
convert kuh.jpg -paint 10 output.jpg
… schon haben wir einen Ölgemälde-Effekt. Die Zahl ist die Größe der Pinselpunkte.
convert kuh.jpg -polaroid 12 output.jpg
Hier ist die Zahl der Neigungswinkel des Polaroidbilds. Ich höre das Friends-Thema in meinem Hinterkopf spielen.
Man kann freilich einfache Effekte auch zu komplexeren verbinden. Anstelle sich durch die GUI eines Bildbearbeitungsprogramms zu kämpfen … warum nicht ein Bash-Skript schreiben?
#!/bin/bash convert -size $(identify -format "%wx%h" kuh.jpg) xc:"rgba(0,0,255,0.5)" blauer_filter.png convert -size $(identify -format "%wx%h" kuh.jpg) xc:"rgba(255,0,0,0.5)" roter_filter.png convert -size $(identify -format "%wx%h" kuh.jpg) xc:"rgba(255,255,0,0.5)" gelber_filter.png convert -size $(identify -format "%wx%h" kuh.jpg) xc:"rgba(0,255,0,0.5)" gruener_filter.png convert kuh.jpg blauer_filter.png -compose Over -composite blaue_kuh.jpg convert kuh.jpg roter_filter.png -compose Over -composite rote_kuh.jpg convert kuh.jpg gelber_filter.png -compose Over -composite gelbe_kuh.jpg convert kuh.jpg gruener_filter.png -compose Over -composite gruene_kuh.jpg montage blaue_kuh.jpg rote_kuh.jpg gelbe_kuh.jpg gruene_kuh.jpg -tile 2x2 -geometry +0+0 output.jpg
Hier lässt sich mit Sicherheit ein Workflow finden, um auch größere Projekte strukturiert umzusetzen.
Der Eisberg ist groß
In der Dokumentation von ImageMagick tun sich Untiefen auf.
#!/bin/bash convert kuh.jpg -crop 512x512+150+100 quadratische_kuh.jpg magick \ \( quadratische_kuh.jpg -alpha set -virtual-pixel transparent \ +distort Affine '0,512 0,0 0,0 -87,-50 512,512 87,-50' \) \ \( quadratische_kuh.jpg -alpha set -virtual-pixel transparent \ +distort Affine '512,0 0,0 0,0 -87,-50 512,512 0,100' \) \ \( quadratische_kuh.jpg -alpha set -virtual-pixel transparent \ +distort Affine ' 0,0 0,0 0,512 0,100 512,0 87,-50' \) \ \ -background none -compose plus -layers merge +repage \ -bordercolor black -compose over -border 5x2 output.jpg
(Vorhandene Codebeispiele lassen sich dann leicht für eigene Zwecke anpassen.)
Ich habe mich hier bemüht, die häufigsten Anwendungsfälle aufzuzeigen und ein paar Einblicke in die Möglichkeiten zu liefern. Am Ende des Tages muss ich allerdings anerkennen, dass ich ein Softwareentwickler bin; kein Fotograf und kein Künstler. Ich kann aber trotzdem mit Gewissheit sagen, dass mit ImageMagick viele Dinge möglich sind, bei denen man sonst Adobe Photoshop oder GIMP heranziehen würde.
Erinnert ihr euch an den ersten Matrix-Film? Wo der Operator im Raumschiff saß und auf Bildschirme voller scrollenden Symbolen starte? „I don’t even see the code. All I see is a blond, brunette, redhead.“ Die Shell funktioniert genauso.
grep -orPz "(?<=<Localized id=\")[^\"]*" /home/eric/projekt/js/src | tr '\0' '\n' | cut -d':' -f2 | sort -u | xargs -I {} psql -U db_user -h localhost -p 32123 -d development -q -A -t -c "SELECT category from l10n.translation WHERE key='{}';" | sort | uniq -c | sort -nr
Seit ich angefangen habe diese Blogartikel zu schreiben, haben sich meine Shellfähigkeiten um einiges verbessert. Wo ich vorher nur wilde Befehle gesehen habe, wo manche Leute „write-only Code“ sehen, sehe ich inzwischen eine ausformulierte Frage. Die Übersetzungssnippets in unserem JavaScript-Code, in wie viele Sprachen sind sie jeweils übersetzt worden?
Developer sind mit diesem Phänomen vertraut. Am Anfang sieht man eine Codebasis voller kryptischer Anweisungen. Nach etwas Lesen erkennt man Muster. Nach einigen Wochen im Projekt hat man viele der Konstrukte und Funktionen kennengelernt und kann flüssig lesen was der Code tut.
Die Shell besteht aus vielen Befehlen die sich für sich genommen einfach sind.
sort
tut genau das, was man vermuten würde.uniq
entfernt Dupletten … braucht aber sortierten Input.uniq -c
entfernt Dupletten und packt die Anzahl der Vorkomnisse einer jeden Zeile als Zahl dran.sort -nr
sortiert numerisch (62 kommt vor 103, obgleich es anders herum wäre wenn man Zahlen strikt alphabetisch sortiert) und dreht die Reihenfolge um, die höchste Zahl kommt zuerst.
Jedes Kommando ist für sich genommen einfach. Jeder Parameter ist für sich genommen einfach. Das ganze erinnert an einen Satz in einer natürlichen Sprache und liest sich auch irgendwann genau so.
Der Trick ist, dran zu bleiben. Einfach den nächsten Parameter nachschlagen. Einfach den nächsten Befehl zu lernen, auszuprobieren (einen Blogartikel darüber schreiben … *hust*) und ins Repertoire aufnehmen. Irgendwann fangen wir alle an, die Matrix zu sehen.
Schreibe einen Kommentar