rel="stylesheet">
Prof. Dr.-Ing. Oliver Radfelder
Informatik / Wirtschaftsinformatik
Hochschule Bremerhaven
ImageMagick

ImageMagick ist die wohl meist verbreitete Grafikumgebung unter Linux. Natürlich gibt es auch unter Linux grafische Werkzeuge, aber für das automatisierte Bearbeiten und Erzeugen von Bildern ist ImageMagick besser geeignet.

convert ist das Hauptwerkzeug von ImageMagick. Damit lassen sich Bilder von einem Format in ein anderes konvertieren. Mit identify lassen sich Metainformationen wie die Größe in Pixeln auslesen.

cp /home/common/circle.png .
convert circle.png circle.jpg
identify circle.jpg

Diese Seite soll wieder keine allgemeine Anleitung für ImageMagick oder eine Dokumentation sein. Davon gibt es im Internet genügend und ganz unten sind wie üblich ein paar Links zum Weiterlesen aufgelistet. Hier soll ein kleiner Überblick und ein Schnellstart gegeben werden für die Dinge, die man so gelegentlich benötigt.

Mit convert lassen sich allerdings auch Bilder erzeugen und mit Grafikkommandos um Texte und Grafikprimitive anreichern.

TEXT="Moin Moin"
convert -size 300x200 canvas:skyblue \
  -fill blue -stroke black  \
  -draw "circle 150,100 150,190" \
  -fill black -font Liberation-Sans -pointsize 30 \
  -gravity center \
  -draw "text 0,0 '$TEXT'" \
  circle.png

convert circle.png six:- ; echo # in sixel-fähigem Terminal

Erzeugt ein png-Bild (circle.png)

Wie man sieht, ist das alles ein einziger Kommandozeilenaufruf in der Shell - dementsprechend muss an der einen oder anderen Stelle mit Quotation-Zeichen gearbeitet werden. Bei solch langen Aufrufen hilft es, gelegentlich den Zeilenumbruch zu escapen - also mit einem Backslash seine besondere Bedeutung zu entziehen.

Auf den ersten Blick wirkt diese Art, ein Bild zu beschreiben, vermutlich etwas eigenartig. Allerdings lässt sich damit hervorragend in einem kleinen Shell-Skript das Erzeugen oder Verändern von vielen Bildern mit ähnlichen Inhalten automatisieren. Das macht wohl den Reiz und die große Verbreitung von ImageMagick aus.

Die besonderen Bedeutungen der Switche und die notwendige Reihenfolge ergibt sich mit der Zeit und Ihr sucht sie Euch am Besten aus einem Tutorial oder Video zusammen. Für die folgenden Experimente genügt es im Wesentlichen den obigen Aufruf zu nutzen.

Macht Experimente und spielt damit herum. Schaut kurz in die man-Page. Findet heraus, wie man Linien zeichnet. Schaut auf linuxhint für eine ausführlichere Beschreibung des Grafik-API. ImageMagick ist sehr mächtig und es finden sich auch nach Jahren noch neue Anwendungsfälle.

Statt ein neues Bild zu erzeugen, lässt sich auch in ein bestehendes Bild hineinzeichnen:

convert circle.png -fill red -draw "rectangle 20,10 80,50" veraendert.png

Oder auch ein Bild in ein Bild einfügen:

convert circle.png -draw 'image SrcOver 10,10 60,40 circle.jpg' over.png

Ein Schachbrettmuster als Hintergrund:

convert -size 640x480 pattern:checkerboard checkerboard.png

Den Hintergrund transparent lassen:

convert -size 640x480 canvas:transparent \
        -fill blue -draw 'rectangle 20,20,300,100' rectangle.png

Sixel funktioniert mit transparenten Hintergründen nicht besonders gut. Daher lohnt es sich, sich in solchen Fällen anzugewöhnen, Transparenz dafür wieder zu entfernen:

convert kreise.png -background white -alpha remove -alpha off six:-; echo

Ein Bild beschneiden:

convert circle.png -crop 300x100+0+50 /var/www/html/$USER-web/crop.png

Einfaches Verändern der Größe unter Beibehaltung des Seitenverhältnisses:

convert circle.png -resize 150x100 resize.png

Da Bilder oft im nichtlinearen sRGB-Format gespeichert werden, ist das Rescaling korrekter, wenn man erst den Farbraum verändert, dann die Größe ändert und schließlich das Format wieder zurückwandelt:

convert circle.png -colorspace RGB  -resize 120  \
          -colorspace sRGB  resized.png

Selbsterklärendes:

convert circle.png -rotate 90 rotated.png
convert circle.png -flip flipped.png
convert circle.png -flop mirror.png
convert circle.png -colorspace Gray gray.png

Manchmal braucht man speziell das ppm-Format P3/8bit - dazu später mehr:

convert circle.png -depth 8 -compress none circle.ppm

Oder sogar speziell das monochrome pbm-Format P1/1bit:

convert -size 300x200 canvas:white -fill black -draw 'rectangle 20,20,100,100' -compress none rect.pbm
convert rect.pbm six:- ; echo
convert rect.pbm rect.png

Der Reiz dieser beiden Formate ist, dass sie zwar unglaublich große Dateien erzeugen, aber da es textuelle Repräsentationen sind, man mit Kommandozeilen-Tools wie bash, sed etc. gewissermaßen zeichnen kann, indem man Pixel setzt. Das ist zwar langsam, aber zum Verständnis von Computergrafik bisweilen durchaus hilfreich. Schauen Sie einfach mit less einmal in das Ergebnis circle.ppm hinein: 3 Zeilen Konfiguration, dann immer drei Zahlen, die den RGB-Wert repräsentieren ... Bei rect.pbm ist es noch einfacher, weil dort nur zwei Zeilen Konfiguration benötigt werden und dann jede 1 oder 0 für ein gesetztes oder nicht gesetztes Pixel steht. Etwas ausführicher wird das unter ffmpeg.html beschrieben.

Dass solcherlei durchaus auch im Informatik-Unterricht in den Schulen bereits behandelt werden kann, zeigt www.inf-schule.de.

Bilder vergleicht man mit:

compare -density 300 -dissimilarity-threshold 0.2 \
        veraendert.png circle.png \
        -highlight-color blue \
        differenz.png

Mit identify lassen sich - so vorhanden - auch exif-Daten auslesen:

identify -format '%[exif:orientation]' camerapicture.jpg

Allerdings ist bei uns auch das in dieser Hinsicht deutlich mächtigere exiftool installiert.

Mit convert und append Bilder aneinanderhängen:

convert -append circle.png circle.png circle.png vertical.png
convert +append vertical.png vertical.png large.png

Manchmal benötigt man die Breite und Höhe eines Textes in einer Schriftart und -größe:

convert -font "Liberation-Sans" \
        -pointsize 64 label:"this is the text" -format "%w\n" info:

Mit identify -list font listen Sie die verfügbaren Fonts auf.

Da es sehr viele Fonts gibt, schaue ich mir bisweilen ganz gerne eine Schriftenfamilie an, bevor ich sie auswähle. Alle Fonts in den Docker-Containern zusammen auf ein Bild zu zeichnen, würde bei über 2500 die Grenzen des eingestellten Maximalbildes (etwa 8000x16000) überschreiten. Daher ein kleines Skript zum Auswählen mit einem regulären Ausdruck:

#!/usr/bin/env bash
if [ "$1" = "" ]; then
  echo "gib einen regulären Ausdruck an"
  echo "zB: 'Roboto|URW'"
  exit 1
fi
identify -list font |grep 'Font:'|egrep "$1" >/tmp/fonts.txt
lines=$(cat /tmp/fonts.txt|wc -l)
commands=" -size 1600x$((lines*60+20)) canvas:white "
y=0
while read desc name ; do 
  ((y+=60))
  sub=" -pointsize 60 -font $name -draw 'text 0,$y $name' "
  commands+="$sub"
done < /tmp/fonts.txt
bash -c "convert $commands fonts.png"

Konstruktion von komplexeren Kommandos

Das Folgende ist nicht spezifisch für Imagemagick, sondern gilt immer, wenn man in der Shell/Bash versucht komplexere Kommandos zusammenzubauen. Aufgrund der Reihenfolge der Auswertungen von Wildcards, Quotes, etc. ist es besser, in solchen Situationen mit Arrays zu arbeiten:

commands=(-fill red -stroke black -strokewidth 3  )
for i in $(seq 200 -10 0); do
  commands+=(-draw "circle 400,200,400,$((200+i))")
done
convert -size 800x400 canvas:maroon "${commands[@]}" image.png

Es bleibt allerdings zu hoffen, dass möglichst bald ImageMagick in der Version 7 in den Distributionen Einzug hält. Dann wird es möglich sein, mit echo "$commands"|magick-script - Kommandos an stdin zu pipen.

Beispiele für installierte Schriftarten:

Poppins|Lora
Roboto
URW
TeXGyre
Open-Sans
DejaVu
Helvetica|Courier|Palatino|Times

Weiterführendes
Basic Usage
Getting started with ImageMagick
ImageMagick Introduction
ImageMagick - better than you know
Imagemagick for CHADS!: Canvases, Plasma, Composites, Geometry
ImageMagick - better than you know