Grafikbearbeitung muss nicht zwangsläufig mit der Maus erfolgen. Mit den Filtern des Netpbm-Pakets und “Verwandten” lassen sich Arbeitsschritte per Shell-Skript automatisieren.
Pixelbasierte Grafikformate gab es schon vor Jahren zuhauf. Entsprechend oft wurden und werden passende Konvertierungsprogramme benötigt. Will man diese Aufgabe nach Unix-Art mit einzelnen Filterprogrammen für die Kommandozeile lösen, so müsste man für n Grafikformate genau (n-1)@L: *n Filter schreiben. Nimmt man stattdessen ein Zwischenformat hinzu, so braucht es nur noch n Filter, die von den verschiedenen Grafikformaten in das Zwischenformat konvertieren und weitere n, die vom Zwischenformat in die Grafikformate zurück wandeln.
Mit dieser Idee begann Jef Poskanzer 1989 seine Arbeit an den pbmtools. Bis 1994 kamen Schritt für Schritt neue Formate und Effektfilter für das Zwischenformat zur Sammlung dazu, die inzwischen unter dem Namen netpbm firmiert. Seit dem Jahr 2000 geht die Netpbm-Entwicklung wieder aktiv voran; das Projekt ist auf Sourceforge beheimatet.
Bit, Grey oder Pix?
Genaugenommen gibt es nicht nur eines, sondern drei Zwischenformate in Netpbm: “Portable Bitmap” (PBM), “Portable Greymap” (PGM) und “Portable Pixmap” (PPM). Das PBM-Format kennt nur gesetzte (schwarze) und nicht gesetzte (weiße) Pixel und kommt deshalb mit einem Bit pro Pixel aus. Das PGM-Format kann nur Graustufen speichern und verwendet dafür im Normalfall acht Bit pro Pixel (256 Graustufen). Das PPM-Format sieht 24 Bit pro Pixel vor (jeweils acht Bit für die Grundfarben Rot, Grün und Blau), was 16,7 Millionen Farben (“True Color”) ergibt. Ist irgendeins der drei Zwischenformate gemeint, spricht man von “Portable Anymap” (PNM).
Filter, die von Fremdformaten ins Zwischenformat konvertieren, heißen etwa tgatoppm, giftopnm oder g3topbm. Für die umgekehrte Richtung sind zum Beispiel ppmtogif, pnmtotiff oder pnmtops zuständig. Dazu kommen Filter, die ausschließlich auf den Zwischenformaten arbeiten. So wandelt ppmtopgm in Graustufen um, pnmsmooth rechnet unscharf, und pgmnorm normiert Graustufen.
Quellmaterial
Für die Bildbearbeitung braucht es natürlich Ausgangsmaterial, das es kommandozeilengesteuert zu verwursten gilt. Auch die Erzeugung dieser Bilder kann der Rechner erledigen, und zwar mit dem freien Raytracer Povray. Die Szenenbeschreibungsdatei glass.pov aus Listing 1 veranlasst das Programm dazu, ein Bild mit fünf gläsernen Kugeln vor einem karierten Hintergrund zu berechnen. Mit der clock-Variable kann zusätzlich der Hintergrund für eine simple Animation bewegt werden.
Listing 1
glass.pov
// Glaskugel-Animation
// (C) 7/2002 Christian Perle (POVaddict) / LinuxUser
// Kamera
camera {
location <0, 0, -10>
direction <0, 0, 4>
look_at <0, 0, 0>
}
// Beleuchtung
light_source { <10, 10, -10> color rgb<1, 1, 1> }
// Deklaration der Glaskugel
#declare GKugel = sphere {
<0, 0, 0>, 0.5
scale <1, 1, 0.5>
finish { phong 0.7 reflection 0.1 refraction 1 ior 1.33 }
}
// Fuenf farbige Glaskugeln
object {
GKugel
translate <-1, -0.6, 0>
pigment { rgbf<1, 0.7, 0.7, 0.7> }
}
object {
GKugel
translate <0, 0, 0>
pigment { rgbf<.7, 1, .7, .7> }
}
object {
GKugel
translate <1, 0.6, 0>
pigment { rgbf<0.7, 0.7, 1, 0.7> }
}
object {
GKugel
translate <1, -0.6, 0>
pigment { rgbf<1, 0.7, 1, 0.7> }
}
object {
GKugel
translate <-1, 0.6, 0>
pigment { rgbf<0.7, 1, 1, 0.7> }
}
// Schachbrettmuster im Hintergrund
plane {
<0, 0, -1>, -4
pigment {
checker color rgb<0.5, 0.5, 0.5>, rgb<1, 1, 1>
translate <-clock, -clock, 0>
scale 0.4
}
finish { ambient 0.4 }
}
Diese Datei werfen wir Povray in der Version 3.0 oder 3.1. zum Fraß vor. Das Programm soll ein 320 mal 240 Pixel großes Bild erzeugen, Anti-Aliasing verwenden und praktischerweise gleich das PPM-Format zur Ausgabe verwenden:
povray +i glass.pov +w320 +h240 +a0.1 +fp +v
Abbildung 1 zeigt das Ergebnis, das in der Datei glass.ppm gespeichert ist.
Filter in Ketten
Die folgenden Arbeitsschritte verfremden das Testbild mit einigen Filterkommandos. Zuerst wandelt folgender Befehl das Bild in Graustufen:
ppmtopgm glass.ppm > glass.pgm
Wie jeder andere Filter aus dem Netpbm-Paket schreibt ppmtopgm das Ergebnis auf die Standardausgabe, die wir mit dem Größer-als-Zeichen > in eine neue Datei glass.pgm umleiten. Das Ergebnis zeigt Abbildung 2.
Um für weitere Filterschritte unnötige Temporärdateien zu vermeiden, nutzen wir nun aus, dass die Netpbm-Programme von der Standardeingabe lesen können. Damit ist es möglich, mehrere Filter mit Pipes in der Shell hintereinander zu schalten:
ppmtopgm glass.ppm | pgmoil -n 5 | pgmtoppm Blue-White > oil.pgm
Die Ausgabe von ppmtopgm wird dabei direkt an pgmoil weiter gereicht. Dieser Filter versieht das Bild mit einem Effekt, der die Konturen wie in einem Ölbild verlaufen lässt. Die pgmoil-Option -n 5 teilt dem Filter mit, den Öl-Effekt auf Felder von je 5 mal 5 Pixeln anzuwenden.
Um wieder Farbe ins Bild zu bringen, reiht sich ein weiterer Filter (pgmtoppm) in die Kette ein, der die Graustufen auf einen Blau-Weiß-Verlauf abbildet. Das Resultat sehen Sie in Abbildung 3.
Laufen lernen
Einzelne Filter von der Kommandozeile aus aufzurufen ist zwar ganz nett, doch viele Stärken der Kommandozeilentools nutzen erst Shell-Skripte richtig aus. Damit können Sie in einem Rutsch ganze Sammlungen von Bilddateien durch die gleiche Filterkette schicken oder einfach nur in ein anderes Format bringen.
Doch woher die Bilderflut nehmen? Auch hier hilft Povray mit dem bereits angesprochenen Animationsfeature. Mit dem Kommando
povray +i glass.pov +w240 +h180 +fp +a0.1 +kfi00 +kff49 +kc
bringen Sie den Raytracer dazu, eine Animationssequenz von 50 Bildern zu berechnen. Die Bilddateien heißen glass00.ppm, glass01.ppm bis glass49.ppm. Entsprechend stehen die Optionen +kfi und +kff für die Nummern des ersten bzw. letzten Bildes. Die Option +kc zeigt an, dass es sich um eine zyklisch wiederholte Animation handelt.
Nun soll aus den Einzelbildern ein animiertes GIF-Bild zum Einbau in eine Web-Seite entstehen. Damit die GIF-Datei nicht zu groß wird, bietet sich eine Verkleinerung der Bildabmessungen auf 100 mal 75 Pixel an. Das Shell-Skript mkgifanim (Listing 2) bewältigt diese Aufgabe und ruft abschließend das Tool whirlgif auf, das die GIF-Einzelbilder zum animierten GIF zusammenklebt.
Listing 2
mkgifanim
#!/bin/bash
for f in glass??.ppm
do
pnmscale -w 100 $f | ppmquant 256 | ppmtogif > ${f%.ppm}.gif
done
whirlgif -o g_anim.gif -loop -time 8 glass??.gif
In der for-Schleife durchläuft die Variable f alle Dateinamen, die auf das Shell-Muster (siehe Kasten 1) glass??.ppm passen. In der Filterkette skaliert pnmscale das jeweilige Bild auf 100 Pixel Breite. Die Höhe wird entsprechend dem Seitenverhältnis mitskaliert. Den nächsten Schritt besorgt ppmquant, das die Farbanzahl auf die für GIF maximalen 256 Farben reduziert. Schließlich schreibt ppmtogif das eigentliche GIF-Bild. Den neuen Dateinamen konstruiert das Skript dabei aus dem aktuellen Inhalt der Variable f, wobei es .ppm als Endung abschneidet und .gif als neue Endung anhängt. Der nachfolgende whirlgif-Aufruf erzeugt die Animation g_anim.gif, die durch die Option -loop endlos wiederholt wird und durch -time 8 zwischen den Bildern 8 Millisekunden Pause lässt. In Abbildung 4 sehen Sie die Animation, wenn Sie dieses Heft mit Daumenkino-Plugin gekauft haben. Im Ernst: Die Datei befindet sich auch auf der Heft-CD und lässt sich in einem Web-Browser oder xanim betrachten.

Abbildung 4: Animation
Kasten 1: Shell-Muster
Die Shell kennt bestimmte Muster für Datei- und Verzeichnisnamen, die sie vor dem Aufruf des entsprechenden Kommandos expandiert. Die wichtigsten sind
- das Fragezeichen
?. Es steht für genau ein beliebiges Zeichen. - der Stern
*. Er dient als Joker für beliebig viele (auch null) beliebige Zeichen. - Zeichenaufzählungen in eckigen Klammern
[]. An der entsprechenden Stelle muss genau eines der umklammerten Zeichen stehen. Dabei gibt es verschiedene Schreibweisen, die die folgenden Beispielen verdeutlichen: Das Musterlx[acE].txtpasst auf die Namenlxa.txt,lxc.txtundlxE.txt. graph[a-z][0-9][0-9].jp?passt (unter anderem) auf die Namengraphi50.jpg,grapho01.jpgundgraphx55.jpe. Der Bindestrich innerhalb der eckigen Klammern sorgt dafür, dass ein ganzer Zeichenbereich gemeint ist, also alle Kleinbuchstaben vonabiszbzw. alle Ziffern von0bis9.
Das Muster [^abc][xyz].b* passt (unter anderem) auf wy.b und 3x.ball, aber nicht auf cz.bmg oder rx.img. Das Dach ^ nach der einführenden Klammer steht für Negation, gemeint sind also alle Zeichen außer den nachfolgend aufgelisteten.
Effekte animieren
Neben GIF gibt es weniger patentbelastete Animationsformate wie MPEG und FLI. xanim zeigt auch letzteres an. Für die mkedge-Animation aus Listing 3 brauchen wir ppm2fli, das nicht Teil der Netpbm-Tools ist.
Listing 3
mkedge
#!/bin/bash
for f in glass??.ppm
do
ppmtopgm $i | pgmedge | pgmnorm > ${i%.ppm}.pgm
done
ls glass??.pgm > frames.list
ppm2fli -g240x180 frames.list edge_anim.fli
Das Skript durchläuft wiederum alle Einzelbilder der Glaskugel-Sequenz, wandelt sie in Graustufen (ppmtopgm), erzeugt eine Liniendarstellung der Kanten im Bild (pgmedge) und normiert die Helligkeitsverteilung (pgmnorm). Die Ergebnisbilder erhalten die Dateinamen glass00.pgm bis glass49.pgm. Da ppm2fli die Liste der Einzelbilder in einer Datei erwartet, muss das ls-Kommando diese Liste zunächst erzeugen, bevor der eigentliche ppm2fli-Lauf starten kann. Auch die Abmessungen der Bilder müssen Sie dem Tool durch die Option -g mitteilen.
Für die Erzeugung einer weiteren Animation verwenden wir das Tool ffmpeg, das – wie der Name vermuten lässt – MPEG-Animationen schreiben kann. Als Filterkette kommt zunächst die gleiche wie in mkedge zum Einsatz, jedoch addiert ein weiterer Schritt das Originalbild glass00.ppm pixelweise dazu (pnmarith). So entsteht ein interessanter Overlay-Effekt. Beim Aufruf von ffmpeg in mkedge (Listing 4) wird das Muster für die Eingabedateien (glass%02d.overlay.ppm) nicht von der Shell expandiert, sondern von ffmpeg selbst.
Listing 4
mkoverlay
#!/bin/sh
for i in glass??.ppm
do
ppmtopgm $i | pgmedge | pgmnorm > temp.ppm
pnmarith -add temp.ppm glass00.ppm > ${i%.ppm}.overlay.ppm
done
ffmpeg -an -i glass%02d.overlay.ppm -b 768 g_overlay.mpg
Die gesamte Filter-Vielfalt der Netpbm-Tools ergründen Sie am besten durch Ausprobieren und Lesen der Manpages. Eine Übersicht finden Sie in denen zu pbm, pgm, ppm und pnm. Damit bleibt nur noch die Aufforderung: Experimentieren Sie!
Glossar
-
Sourceforge
-
Ein unter http://sourceforge.net/ zu findender Web-Dienst, der viele Open-Source-Projekte beheimatet [1]. Entwicklerforen, Versionsverwaltung, Downloadbereiche und vieles mehr stellt er zur Verfügung.
-
Povray
-
Ein frei kopierbares Raytracing-(3D-Grafik)-Programm, das auf vielen Betriebssystemen zu Hause ist – so auch auf Linux. Seine Homepage finden Sie unter http://www.povray.org/; die Heft-CD enthält ein Tutorial in HTML-Form.
-
Anti-Aliasing
-
Automatische Kantenglättung bei hohen Kontrasten. So erscheint die Grafik weniger “verpixelt”, es wird eine höhere Auflösung vorgegaukelt.
-
Standardeingabe
-
Bei vielen Kommandozeilenprogrammen gibt es die Möglichkeit, den Namen der Eingabedatei wegzulassen. In diesem Fall liest das Programm von der Standardeingabe, die normalerweise mit der Tastatur verbunden ist. Wird der Name der Ausgabedatei weggelassen, geben viele Programme auf der Standardausgabe aus, also sichtbar aufs Terminal.
-
Standardausgabe
-
Bei vielen Kommandozeilenprogrammen gibt es die Möglichkeit, den Namen der Eingabedatei wegzulassen. In diesem Fall liest das Programm von der Standardeingabe, die normalerweise mit der Tastatur verbunden ist. Wird der Name der Ausgabedatei weggelassen, geben viele Programme auf der Standardausgabe aus, also sichtbar aufs Terminal.
-
Pipes
-
Das Pipezeichen “|” (steht für eine stilisierte Rohrleitung) verbindet die Standardausgabe eines Programms mit der Standardeingabe eines anderen. So lassen sich mehrere Programme zu einem Verarbeitungsschritt zusammen fassen.
-
Shell-Skripte
-
Eine Datei mit Shell-Kommandos, die automatisch abgearbeitet werden. Häufig wiederkehrende Arbeitsschritte lassen sich durch Shell-Skripte gut automatisieren.
Infos
[1] Andreas Bauer: “Sourceforge & Co.”, LinuxUser 02/2002, S. 39 ff.








