Das Modul Image::Magick
konvertiert Bilder von einem Format ins
andere, schneidet Teile aus, flickt Text hinein, montiert Einzelbilder
zu kombinierten Darstellungen, erzeugt animierte GIFs und morpht
sogar Übergänge -- Sackzement!
ImageMagick
dürfte Linux-Hardlinern wohlbekannt sein -- diese
Distribution stellt einige Utility-Programme zur Verfügung, die
allerhand mit verschiedensten Graphikformaten anstellen. Ist die
Perl-Schnittstelle Image::Magick
von Kyle Shorter erst einmal
installiert (siehe Abschnitt Installation
), eröffnet
sie den programmierten Zugriff und vereinfacht die Automatisierung
von Bilderkonvertierungsaufgaben.
Der Zugriff ist objektorientiert, ein neues Bild entsteht mit dem Konstruktor
$image = Image::Magick->new();
und mit Daten wird es mittels der Read
-Methode gefüllt, die
ein Bild von der Platte einliest:
$image->Read("test.gif") && die "Cannot read!";
Image::Magick
folgt leider nicht der Perl-Konvention, im
Erfolgsfall einen wahren und im Fehlerfall einen falschen Wert
zurückzuliefern, sondern es gibt die Anzahl erfolgreich eingelesener
Dateien zurück -- im Erfolgsfall 1
, und dann kommt der über
eine And
-Anweisung gekoppelte die
-Befehl nicht zum Einsatz.
Zurückgeschrieben wird auf die gleiche Weise:
$image->Write("test.jpg") && die "Cannot write!";
Weist der Name der Ausgabedatei eine andere Endung als das eingelesene
Bild auf, konvertiert Image::Magick
alles automatisch ins richtige
Format, im vorliegenden Fall von GIF
nach JPG
. Weiter
werden PNG, BMP, TIFF und viele andere unterstützt.
Ein Objekt vom Typ Image::Magick
kann dabei nicht nur ein
Bild aufnehmen, sondern eine ganze Reihe, jeder weitere Aufruf
der Read
-Methode hängt ein weiteres an. Listing tojpg.pl
zeigt eine Anwendung: Die foreach
-Schleife liest alle Dateien,
deren Namen über die Kommandozeile hereinkommen, der Reihe nach
ein und hängt deren Inhalt immer wieder an das Objekt, das
sich hinter $images
verbirgt, an.
Über alle Bilder im Objekt kann man nun iterieren, indem man
die Objektreferenz $images
in einen Array konvertiert und
so über die Elemente von @$images
eiert.
Diese sind wiederum Image::Magick
-Objekte und verstehen daher
neben den bereits besprochenen Methoden Read
und Write
auch Get
(Attribute abfragen) und Set
(Attribute setzen).
Einige der wichtigsten Attribute:
base_columns Breite des Original-Bildes base_rows Höhe des Original-Bildes base_filename Name der Eingabedatei filesize Größe der Eingabedatei in Bytes total_colors Anzahl der Farben x-resolution Auflösung in X-Richtung y-resolution Auflösung in Y-Richtung
tojpg.pl
macht nun aus jedem hereinkommenden Dateinamen einen mit
der Endung *.jpg
, ruft die Write
-Methode auf und konvertiert
so alle angegebenen Dateien ins JPG
-Format. Damit's spannend
anzusehen ist, ermittelt es mittels des filesize
-Attributs
auch noch die ursprüngliche Dateigröße, und läßt anschließend
den -s
-Operator auf das frischgeschriebene File los, der anstandslos
dessen Größe zurückliefert. Die commify
-Funktion setzt Punkte
in die zurückkommenden Zahlen, um sie übersichtlich in Dreiergruppen
zu strukturieren.
Ruft man also tojpg.pl
mittels
tojpg.pl images/*.bmp
auf, lautet die Ausgabe etwa
images/lion.bmp->images/lion.jpg (717.606 -> 73.241 Bytes) images/pieks.bmp->images/pieks.jpg (688.018 -> 53.743 Bytes) images/schuh.bmp->images/schuh.jpg (708.302 -> 50.450 Bytes)
und für alle *.bmp
-Dateien entstehen platzsparende JPEGs.
tojpg.pl
01 #!/usr/bin/perl 02 ################################################## 03 # Michael Schilli, mschilli@perlmeister.com 1999 04 # Dateien nach JPG konvertieren 05 ################################################## 06 use Image::Magick; 07 08 $images = Image::Magick->new(); 09 10 foreach $file (@ARGV) { 11 $images->Read(filename => $file) && 12 die "Read failed"; 13 } 14 15 foreach $image (@$images) { 16 17 $oldsize = $image->Get('filesize'); 18 19 ($newname = $image->Get('base_filename')) 20 =~ s/\.[^.]*$/.jpg/; 21 22 $image->Write($newname) && die "Write failed"; 23 24 printf "%s->%s (%s -> %s Bytes)\n", 25 $image->Get('base_filename'), 26 $newname, 27 commify($oldsize), 28 commify(-s $newname); 29 } 30 31 ################################################## 32 sub commify { # Punkte in große Zahlen einfügen 33 ################################################## 34 my $number = shift; 35 while($number =~ s/(\d)(\d{3})\b/\1.\2/) { } 36 return $number; 37 }
Von den dutzenden von Methoden, die Image::Magick
anbietet, um
am Bildinhalt herumzuschustern, kann ich nur einen kleinen Teil besprechen:
Crop
zum Ausschneiden von Teilen, Scale
zum Strecken und Stauchen,
Frame
zum Rahmenziehen und Annotate
zum Hineinschreiben von Text.
Für den Rest sei auf die ausführliche Dokumentation [2]
verwiesen.
In Listing manip.pl
nimmt
die Crop
-Methode ein geometry
-Attribut entgegegen, das
wie in X-Windows üblich im Format WxH+X+Y
aufgebaut ist. Crop
ersetzt das ursprüngliche Bild durch den Ausschnitt. So schneidet es
aus dem dritten Bild aus Abbildung 2 die abgebildete Tafel aus und
streckt das Ergebnis anschließend mit der Scale
-Methode von
100 auf 200 Pixels. Dies hat zur Folge, daß sich das Bild etwas
verzerrt. Einen Rahmen zeichnet dann die Frame
-Methode, und zwar
mit einer Innenkante von 2 Pixels, einer Außenkante von 2 Pixels
und einer oberen und unteren Rahmenbreite von 20 Pixels.
Die Annotate
-Methode schließlich schreibt den Text Woohoo!
in Rot 55 Pixels vom linken und 30 Pixels vom oberen Rand entfernt
ins Bild. Als Font wird ``Helvetica'' gewählt. Das Ergebnis, das
die Write
-Methode wegschreibt, zeigt Abbildung 1.
Abb.2: Croppen, Ausziehen, Beschriften, Rahmen zeichnen |
manip.pl
01 #!/usr/bin/perl 02 ################################################## 03 # Michael Schilli, mschilli@perlmeister.com 1999 04 # Ein Bild manipulieren 05 ################################################## 06 use Image::Magick; 07 08 $image = Image::Magick->new; 09 10 $image->Read("images/lion.jpg") && 11 die "Cannot read"; 12 13 $image->Crop(geom=>'155x300+110+100'); 14 15 $image->Scale(width => 200); 16 17 $image->Frame(inner => 2, outer => 2, 18 width => 20, height => 20); 19 20 $image->Annotate(text => "Woohoo!", 21 geometry => "+55+30", 22 pen => "red", font => 'helvetica', 23 pointsize => 30); 24 25 $image->Write("../fig/manip.gif") && 26 die "Cannot write";
Um Sammlungen von Bildern in Übersichtstafeln als kleine ``Thumbnails''
darzustellen, eignet sich die Montage
-Methode. Listing montage.pl
zeigt, wie Montage
alle im Objekt $images
gespeicherten Bilder
entsprechend den gesetzten Attributen zusammenfaßt und eine Referenz
auf ein neues Objekt, $montage
, zurückliefert.
Das tile
-Attribut gibt in der vorgestellten Form die Anzahl der
Spalten an, in die Montage
die Bildchen aufreiht, in der Form
3x4
ließe sich dazu auch noch die Anzahl der Zeilen begrenzen.
Das auf True
gesetzte Shadow
-Attribut läßt rechts und
unterhalb jedes Bildes einen kleinen Schatten erscheinen, der
eine Tiefenwirkung vermittelt. Das label
-Attribut schließlich
gibt an, was als Beschriftung unter jeden Bild stehen wird, und neben
normalem Text dürfen auch einige Makros stehen, hier die wichtigsten:
%b Dateigröße %f Dateiname %h Höhe %m Typ (GIF, JPG) %w Breite
Abb.2: Montierte Bilder |
montage.pl
01 #!/usr/bin/perl 02 ################################################## 03 # Michael Schilli, mschilli@perlmeister.com 1999 04 # Montage von Bildern 05 ################################################## 06 07 use Image::Magick; 08 09 $images = Image::Magick->new(); 10 11 foreach $file (@ARGV) { 12 $images->Read($file) && die "Read failed"; 13 } 14 15 $montage = $images->Montage(label => "%f", 16 shadow => "True", 17 tile => "2"); 18 19 $montage->Write("../fig/montage.gif") && 20 die "Write failed";
Und schließlich kann Image::Magick
auch noch animierte GIFs schreiben
-- und die Animation sogar noch durch Morphen zwischen mehreren Bildern
selbst erzeugen.
Listing morph.pl
zeigt wie's geht: Für ein animiertes GIF, das
langsam zwischen zwei Darstellungen wechselt und die Übergänge
fließend herstellt, brauchen wir zwei statische GIFs, im Listing
sind das book1.gif
und book2.gif
.
Damit das animierte GIF, wenn es sich bis zum zweiten Bild durchgemorpht
hat, nicht ruckartig zum ersten Bild zurückspringt, sondern auch
ordentlich abmorpht (dieses Wort gefällt mir), speichert morph.pl
die Dreierfolge book1.gif
-book2.gif
-book1.gif
in $images
ab und fordert die Morph
-Methode auf, jeweils 10 Übergangsbilder
(Frames-Attribut) zwischen den Eckpunkten zu erzeugen.
Vor dem Schreiben des animierten GIFs mit der Write
-Methode
setzt morph.pl
noch schnell die Attributwerte für
delay
und loop
-- die Anzahl von Hunderstelsekunden zwischen
den einzelnen Frames und die Gesamtzahl der Schleifendurchläufe bis
das animierte GIF stehenbleibt.
morph.pl
Abbildung 3: Bildübergänge durch Morphen |
01 #!/usr/bin/perl 02 ################################################## 03 # Michael Schilli, 1998 (mschilli@perlmeister.com) 04 ################################################## 05 06 use Image::Magick; 07 08 $images = Image::Magick->new(); 09 10 foreach $file (qw(book1.gif book2.gif book1.gif)) { 11 $images->Read(filename => $file) && die "Read failed"; 12 } 13 14 $morph = $images->Morph(frames => 10); 15 16 $morph->Set(delay => 20, loop => 10); 17 18 $morph->Write("../fig/morph.gif") && 19 die "Cannot write";
Ausgehend von einer Redhat-5.2-Installation, die bereits über
die Bibliotheken libpng
, libtiff
, libjpeg
und libz
verfügt, fehlen noch drei Sachen (Fehlt mehr, hilft
README.txt
der ImageMagick-Distribution weiter):
Die ImageMagick
-Distribution, die in Version 4.1.8
vorliegt,
holt man von der Original-Site
ftp://ftp.wizards.dupont.com/pub/ImageMagick
oder vom niederländischen Spiegel
ftp://ftp.oce.nl/pub/Internet/audio+video/ImageMagick
als komprimierte Tar-Datei ImageMagick-4.1.8.tar.gz
.
Bevor's ans Auspacken
geht, brauchen wir noch die Freetype-Bibliothek libttf
, die unter
ftp://ftp.freetype.org/pub/freetype/freetype-1.2.tar.gz
liegt. Weiter braucht's noch die BZLIB, die's unter
http://www.muraroa.demon.co.uk/bzip2-0.9.0c.tar.gz
gibt. Sind alle drei Distributionen in einem Verzeichnis, kann die Installiererei losgehen:
tar zxfv ImageMagick-4.1.8.tar.gz cd ImageMagick-4.1.8 tar zxfv ../bzip2-0.9.0c.tar.gz mv bzip2-0.9.0c bzlib cd bzlib make cd .. tar zxfv ../freetype-1.2.tar.gz mv freetype-1.2 ttf cd ttf ./configure make cd .. ./configure make make install cd PerlMagick make install cd .. cd ttf make install cd ..
Die Perl-Bibliothek PerlMagick
liegt dem Ganzen als Version 1.60
schon bei und wird mit installiert. Falls übrigens
die Environment-Variable LD_LIBRARY_PATH
nicht den Pfad
/usr/local/lib
enthält, bitte nachziehen, sonst
funktionieren die Binaries, die der ImageMagick
-Distribution
beiliegen (wie z.B. das handliche Programm convert
) nicht.
Sodann sollte ein einfaches
#!/usr/bin/perl -w
use Image::Magick;
funktionieren. Uff!
Fröhliches Abmorphen, bis zum nächsten Mal -- wenn es wieder heißt: News aus Perl-Land!
Michael Schilliarbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com. |