Reflektierende Oberflächen mit ImageMagick

Endergebnis Wer kennt es nicht – Bilder, die aussehen als würden sie auf einer spiegelnden Oberfläche stehen und von dieser reflektiert werden. Insbesondere auf der Apple Homepage ist dieser Effekt quasi allgegenwärtig, aber auch in meiner Galerie kann man ihn bewundern. Mit Programmen wie Photoshop oder The GIMP ist es auch nicht sehr viel Aufwand, den Shiny Table Look zu imitieren. Aber es ist (zumindest für mich) viel interessanter, das ganze automatisch zu machen, um es in einer Web-Anwendung nutzen zu können.

Um den Effekt in meine Galerie zu bekommen, hatte ich dank meines Webhosters zwei Optionen: die Bildverarbeitungs-Funktionen von PHP oder ImageMagick. Die PHP-Funktionen haben den Vorteil, dass man sehr einfach mit ihnen arbeiten kann und man vor allem viele rudimentäre Werkzeuge zur Verfügung hat. ImageMagick hingegen hat sehr viele komplexere Effekte eingebaut und ist im Allgemeinen schneller, verbraucht weniger Speicher die Bilder weisen eine höhere Qualität bei gleicher oder geringerer Dateigröße auf. Ich habe meine Prototypen mit den PHP-Funktionen entwickelt und habe das ganze dann später auf ImageMagick umgestellt.

Eigentlich steckt nicht sehr viel hinter diesem Effekt. Das Ursprungsbild wird eventuell verkleinert, anschließend kopiert, gespiegelt und mit einem Farbverlauf überblendet. Bei ImageMagick wird dafür der Befehl convert verwendet. Die Syntax sieht stark vereinfacht so aus: convert ursprungsbild.jpg <Verarbeitungsbefehle> ergebnisbild.jpg. Die Verarbeitungsbefehle sind der wirklich interessante Teil hierbei.

Schritt 1: Verkleinern, Kopieren & Spiegeln

Kopiert und Gespiegelt Im ersten Schritt wird das Bild verkleinert, kopiert und gespiegelt. Das Verkleinern ist der einfachste Teil, man muss lediglich die Maximalgröße in eckigen Klammern an den Dateinamen des Ursprungsbildes anhängen, etwa so: ursprungsbild.jpg[300x250]. So wird das Bild direkt beim Einlesen verkleinert, was die Performance erhöht.
Operationen wie Kopieren und Spiegeln werden deutlich einfacher, wenn man einen Image Stack verwendet. Man hat dann eigentlich ein separates Bild, das man nach Belieben verändern kann und anschließend einfach in das Gesamtbild einfügt. Ein Image Stack wird durch Klammern eingeleitet und beendet. Der Stack muss mit einer Kopie des Ursprungsbildes gefüllt werden, was die Option clone erledigt. Die (vertikale) Spiegelung wird durch flip erreicht.
Bisher sieht der Befehl für den Image Stack also folgendermaßen aus:  ( +clone -flip ) . Die Leerzeichen vor und hinter den Klammern sind dabei wichtig und in den meisten Shells müssen die Klammern noch durch Backslashes maskiert werden (nicht unter Windows).
Jetzt wurde allerdings das komplette Bild kopiert und gespiegelt, später soll jedoch nur ein Ausschnitt zu sehen sein. Deshalb muss der Inhalt des Image Stacks noch auf diesen Ausschnitt reduziert werden, was mit dem Befehl crop erledigt wird, im Beispiel wird auf einen 50 Pixel hohen Streifen zugeschnitten. Abschließend wird der Inhalt des Image Stacks mit dem Befehl append an das untere Ende des Bildes angefügt. Der komplette Befehl sieht jetzt so aus: convert ursprungsbild.jpg[300x250] ( +clone -flip -crop x50+0+0 ) -append ergebnisbild.jpg, das Ergebnis ist links abgebildet.

Schritt 2: Farbverlauf

Farbverlauf Um einen Farbverlauf über das Bild zu legen, bietet sich wieder ein Image Stack an. Nur muss er dieses Mal nicht mit einem Teil eines Bildes gefüllt werden sondern mit einem Farbverlauf. Um das zu erreichen, muss man ein wenig in die Trickkiste greifen. Neben sehr vielen normalen Bildformaten unterstützt ImageMagick auch sogenannte Pseudo-Formate. Man kann damit Bilder „öffnen“, die in Wirklichkeit von einem anderen Teil der Software dynamisch erzeugt werden. Ein Farbverlauf (englisch Gradient) ist eines dieser Pseudo-Formate.
Um damit arbeiten zu können, muss dem Image Stack aber erstmal mit dem Befehl size eine Größe zugewiesen werden, hier entspricht die Breite der Breite des verkleinerten Bildes und die Höhe den 50 Pixeln, auf die die Spiegelung reduziert wurde. Anschließend kann der Farbverlauf „geöffnet” werden, indem die Start- und Endfarbe angegeben wird. Dies kann zum Beispiel im RGBA-Format gemacht werden. Im Beispiel beginnt der Farbverlauf mit einem etwas durchsichtigem Weiß (#ffffff88) und endet mit einem deckenden Weiß (#ffffffff). Der Image Stack sieht dann so aus:  ( -size 300x50 gradient:#ffffff88-#ffffffff ) .
Jetzt muss nur noch der Inhalt des Image Stacks über das untere Ende des Bildes geblendet werden. Und das geht nicht. Man kann ihn nur mit dem Befehl flatten über das obere Ende des Bildes blenden, solange man nicht weiß wie hoch das Bild genau ist. Die Lösung ist allerdings recht einfach, man spiegelt das Bild mit dem bekannten flip-Befehl, überblendet es mit dem (dadurch ebenfalls gespiegelten Farbverlauf) und spiegelt das Ergebnis erneut. Konkret sieht der Teil folgendermaßen aus:  ( -size 300x50 gradient:#ffffff88-#ffffffff ) -flip -flatten -flip und es ergibt sich der komplette Befehl, dessen Ergebnis rechts zu sehen ist: convert ursprungsbild.jpg[300x250] ( +clone -flip -crop x50+0+0 ) -append ( -size 300x50 gradient:#ffffff88-#ffffffff ) -flip -flatten -flip ergebnisbild.jpg

Schritt 3: Feinschliff

Endergebnis Um auf das gleiche Ergebnis wie ganz oben zu kommen, ist noch ein wenig Feinschliff nötig. Am auffälligsten ist der kleine weiße Strich, der Bild und Spiegelbild voneinander trennt. ImageMagick bietet hierfür den Befehl splice an, mit dem das Bild aufgetrennt werden kann, so dass die Hintergrundfarbe durchscheint. Die Hintergrundfarbe muss man vorher mit dem Befehl background definieren. Dem Befehl splice muss man eine Geometrie-Definition übergeben. Diese setzt sich zusammen aus der Breite und der Höhe sowie einem vertikalen und einem horizontalen Abstand und gibt die Stelle an, an der das Bild aufgetrennt werden soll. Im Beispiel soll die Breite der des gesamten Bildes entsprechen und wird daher weggelassen, die Höhe wird auf 1 Pixel gesetzt (sieht meiner Meinung nach am besten aus), der horizontale Abstand ist 0 (die Auftrennung soll am linken Bildrand anfangen) und der vertikale Abstand entspricht der Höhe der Spiegelung, also 50 Pixel. Die 50 Pixel beziehen sich jetzt jedoch wieder auf den oberen Rand des Bildes. Bei Geometrie-Definitionen hat man allerdings die Möglichkeit, den Bezugspunkt mit Hilfe des Befehls gravity z.B. auf den unteren Bildrand zu ändern. Weil das Bild aber durch den vorherigen Schritt sowieso auf dem Kopf steht, kann man stattdessen den splice-Befehl vor dem letzten flip-Befehl einfügen. Insgesamt sieht der convert-Aufruf dann so aus: convert ursprungsbild.jpg[300x250] ( +clone -flip -crop x50+0+0 ) -append ( -size 300x50 gradient:#ffffff88-#ffffffff ) -flip -flatten -background white -splice x1+0+50 -flip ergebnisbild.jpg Und wer wirklich genau hinsieht oder Erfahrung mit dem Aufbereiten von Bildern für das Internet hat, dem wird auffallen, dass die Bilder nach der Verkleinerung etwas matschig aussehen. Wenn man Bilder manuell in einem Bildbearbeitungsprogramm bearbeitet, wendet man daher meist noch den Filter unscharf maskieren an. Zum Glück kann ImageMagick das auch, der Befehl heißt unsharp. Die Bedeutung der einzelnen Optionen ist zu kompliziert, um sie hier zu erläutern, aber es gibt einen sehr guten Artikel dazu bei Luminous Landscape. Ich wende den Befehl direkt nach der Verkleinerung mit dem Radius von 5, Sigma 1 und Amout 1 an. Der komplette convert-Befehl sieht dann so aus:convert ursprungsbild.jpg[300x250] -unsharp 5x1+1 ( +clone -flip -crop x50+0+0 ) -append ( -size 300x50 gradient:#ffffff88-#ffffffff ) -flip -flatten -background white -splice x1+0+50 -flip ergebnisbild.jpg

Sehr geholfen beim zusammenbasteln der einzelnen Schritte und Optionen haben mir übrigens die ImageMagick Usage Examples – sehr empfehlenswert, wenn man sich mit ImageMagick näher beschäftigen möchte.

Kommentare

Gravatar #1 Huaba
03.07.2009, 12:14
Sehr nett, danke für das Tut!
Gravatar #2 Anonym
04.11.2009, 00:01
Hallo,

erst mal vielen Dank für die tolle Anleitung, ich stoße jedoch an einer Stelle auf ein Problem, nämlich bei dem Gradienten. Sobald ich hier eine Farbe in RGBA eingebe, erhalte ich keinen Verlauf, sondern einen einfarbigen Balken.
Ich verwende Im 6.2.4 auf Debian etch 2.6.24.

Hat jemand einen Tipp für mich

Danke
Gravatar #3 Anonym
30.03.2010, 13:47
das problem mit dem transparenten farbverlauf hatte ich auch.
nach update von imagemagick version 6.2.7 auf 6.6.0 funktioniert es einwandfrei.
Gravatar #4 Simon
07.06.2010, 17:21
Super Tutorial, vielen Dank!
Ein Problem habe ich dennoch: wie kann ich denn den Verlauf so erstellen, dass er ins alphatransprente läuft (also so, dass der Hintergrund durchscheint)?

Es gibt schon eine Anleitung auf CLI-Ebene, aber ich kriege es nicht auf die Reihe, das in IMagick-Form umzuwandeln:

http://www.imagemagick.org/Usage/advanced/#reflections
Gravatar #5 Simon
07.06.2010, 17:28
edit: sorry, ist ja hier auch "nur" für CLI erklärt :-(

Kommentar schreiben

Optionale Angaben


(wird nicht veröffentlicht, Gravatar wird unterstützt)

CAPTCHA ← den Code in das Feld →

Neue Kommentare