Filter in SVG/Selbstdefinierte Filter

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Wenn die vordefinierten Filter nicht ausreichen, gibt es die Möglichkeit, eigene Filter aus einem Satz von vordefinierten Filtereffekten (Ur-Filter oder Filter-Primitive) zusammenzusetzen. Dies geschieht mit Hilfe des SVG-Elements filter.

Einen eigenen Filter definieren

Erzeugen

Das <filter>-Element wird in einem SVG-Dokument als Kind-Element eines <defs>-Elements verwendet. Es benötigt ein id-Attribut, um verwendet werden zu können, und erhält die gewünschten Filtereffekte als seine Kind-Elemente. Alle Filtereffekte haben einen Tagnamen, der mit fe beginnt – aber Vorsicht, nicht alles, was mit fe beginnt, ist auch ein Filtereffekt.

Ein einfaches Beispiel ist ein Weichzeichner. Schauen wir uns an, wie das aussieht:

Unschärfefilter als filter-Element
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 150" width="300" height="150">
  <defs>
    <filter id="soft-3">
      <feGaussianBlur stdDeviation="2" />
    </filter>
  </defs>

  <rect x="10" y="10" width="130" height="100"
        fill="red" stroke="black" stroke-width="5" />
  <rect x="160" y="10" width="130" height="100" filter="url(#soft-3)"
        fill="red" stroke="black" stroke-width="5" />
</svg>
SVG-Filter-Demo1.svg

Unser Beispiel verwendet den Filtereffekt feGaussianBlur, das ist ein Unschärfefilter, der auf der von Carl Friedrich Gauß entwickelten Normalverteilungskurve basiert.[1] Diese Kurve ist eigentlich ein Werkzeug der Statistik, aber wegen ihrer Glockenform eignet sie sich gut, um einen Unschärfeübergang mathematisch zu beschreiben. Der Statistikbegriff „Standardabweichung“ ist ein Maß für die Breite der Glocke, und deshalb heißt das Filtereffekt-Attribut, das die Stärke der Unschärfe angibt, stdDeviation.

Einbinden

Das <filter>-Element hat das Attribut id="soft-3" bekommen. Mit dieser ID kann der Filter auf das <rect>-Element mittels filter="url(#soft-3)" angewendet werden. In SVG ist das Filter-Attribut der übliche Weg. In HTML weist man Filter per CSS über die Filter-Eigenschaft zu. Beide Methoden bieten die gleichen Möglichkeiten.

Ein Filter muss dabei nicht zwangsläufig im gleichen Dokument stehen. Wenn sich der Weichzeichner beispielsweise im gleichen Ordner, aber im Dokument filtersammlung.svg befindet, kann man ihn mit url(filtersammlung.svg#soft-3) einbinden.

Es ist auch möglich, mehrere Filter nacheinander anzuwenden. Dazu notiert man sie in der gewünschten Reihenfolge, durch Leerzeichen getrennt, im filter-Attribut oder der filter-Eigenschaft. Vor- und selbstdefinierte Filter können beliebig gemischt werden.

Festlegen des Eingabebildes

Als Eingabe für einen Filter dient normalerweise die RGBA-Darstellung des Elements, auf das der Filter anzuwenden ist, und zwar nur das Element, ohne den Hintergrund, auf dem es liegt. Dies ist aber nicht die einzige Möglichkeit. Jeder Filtereffekt besitzt ein Attribut in (manche auch ein weiteres Attribut in2), mit dem man festlegen kann, was genau als Eingabebild dienen soll. Zur Auswahl stehen sechs mögliche Schlüsselwort-Angaben, die Standard-Inputs des Filters bezeichnen, oder der Verweis auf das Ergebnis eines vorherigen Filtereffekts.

SourceGraphic
Dies ist der Standardfall und bezeichnet das Element, so wie es vom Browser gezeichnet wird.
SourceAlpha
SourceAlpha ist eine „geschwärzte“ Form von SourceGraphic. In jedem Bildpunkt werden die Farbanteile Rot, Grün und Blau auf 0 gesetzt, aber der Transparenzwert bleibt erhalten. Man erhält auf diese Weise eine Maske für die Stellen, an denen das Element etwas überdeckt.
BackgroundImage, BackgroundAlpha, FillPaint, StrokePaint
Diese vier Schlüsselwörter werden von der Spezifikation genannt, besitzen aber eine schlechte Browserunterstützung und werden hier darum nicht weiter beschrieben. Etwas mehr dazu steht im Referenzartikel zum in-Attribut.
filtereffekt-verweis
Der Filtereffekt verarbeitet die Ausgabe eines vorhergehenden Filtereffekts. Darauf gehen wir im folgenden Abschnitt genauer ein.

Verketten von Filtereffekten

Einzelne Filtereffekte können nützlich sein, wirklich mächtig werden Filter aber erst, wenn man mehrere verkettet. Um zu verstehen, wie das funktioniert, müssen wir einen genaueren Blick darauf werfen, wie Filter angewendet werden.

Wie bereits in der Einführung erwähnt, werden Filter auf die RGB-Bilddarstellung eines Elements angewendet und erzeugen ein neues Bild. In einem Filter mit mehreren Effekten ist es standardmäßig so, dass der erste Effekt auf das gefilterte Element angewendet wird, der zweite Effekt wird auf das Ergebnis des ersten Effekts angewendet, und so weiter. Das Ergebnis des letzten Effekts ist dann das, was der Browser auf den Bildschirm zeichnet.

Dieser lineare Zusammenhang lässt sich aufbrechen. Dazu verwendet man das result-Attribut der Filtereffekte, um dem Effektergebnis einen Namen zuzuweisen. Der Name kann in den in und in2-Attributen genutzt werden, um dieses Ergebnis als Eingabe für einen Effekt festzulegen.

Ein komplexeres Beispiel

Das folgende Bild zeigt die Anwendung eines komplexeren Filters auf ein einfaches rotes Rechteck mit schwarzem Rand (mit „SourceGraphic“ beschriftet). Die übrigen Bildfelder sind mit dem Filtereffekt beschriftet, der sie erzeugt hat. Die Pfeile geben an, welches Bildfeld die Eingabe für diesen Filter war.

SVG-Filter-Demo2.svg

Das feGaussianBlur-Feld kennen wir schon - beinahe. Es ist hier schwarz, und das liegt daran, dass für den Filtereffekt nicht SourceGraphic, sondern SourceAlpha als Eingabe diente. Der Filtereffekt sieht so aus:

 <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blurred" />

Für das darunter befindliche Feld wird der Filtereffekt feOffset genutzt. Dieser Effekt verschiebt den Inhalt seines Eingangsbildes um einen bestimmten x- und y-Wert. Dabei geht ein Teil des Bildes verloren (es wird „hinausgeschoben“, und gegenüber wird Transparenz „hineingeschoben“. So sieht es aus:

 <feOffset in="blurred" dx="5" dy="5" result="shadowForm" />

Für den feOffset-Effekt haben wir in="blurred" angegeben, um zu verdeutlichen, dass das Ergebnis des GaussianBlur-Effekts die Eingabe sein soll. Wenn beide Effekt direkt hintereinander stehen, kann man das in-Attribut – wie eingangs beschrieben – aber auch weglassen.

Als drittes gibt es ein einfaches grünes Feld. Es entsteht durch den feFlood-Effekt, der die vom Filtereffekt beeinflusste Region einfach mit einer bestimmten Farbe füllt. Auffällig ist hier, dass das grüne Feld größer ist als die Eingangsgrafik. Das liegt daran, dass die Filterregion standardmäßig in jeder Richtung 10% größer ist als das gefilterte Bild, damit genug Platz für die Ergebnisse von Blur- oder Offset-Effekten ist. Wir werden darauf noch näher eingehen. Der feFlood-Effekt sie so aus:

 <feFlood flood-color="green" result="allGreen" />

Ein in-Attribut fehlt und ist für feFlood auch nicht vorgesehen, weil dieser Filtereffekt nicht auf ein anderes Bild wirkt, sondern lediglich eine Farbfläche erzeugt.

Als nächstes werden das feOffset- und feFlood-Ergebnis zusammengeführt. Dazu verwenden wir den feComposite-Effekt, der zwei Bilder miteinander kombiniert. Das operator-Attribut bezeichnet den Algorithmus, der dabei zu verwenden ist. Für diese Kombination haben wir operator="in" verwendet:

 <feComposite in="allGreen" operator="in" in2="shadowForm" result="greenShadow" />

Die Wirkung des Effekts ist genau so zu lesen, wie die Attribute aufgeschrieben sind: Erzeuge einen Ergebnisbildpunkt, wenn sich der Punkt im "in"-Bild innerhalb des "in2"-Bildes befindet. Oder anders ausgedrückt: Verwende für den Ergebnis-Bildpunkt den RGBA-Wert des "in" Bildes und wende auf diesen Punkt zusätzlich den Transparenzwert des Bildpunktes aus "in2" an.

Das unterste Bildfeld zeigt die Kombination des grünen Schattenfeldes mit dem Originalbild. Hier wird wiederum feComposite benutzt, diesmal aber mit operator="over". Dieser Operator zeichnet das "in"-Bild über das "in2" Bild. Nur dort, wo ein Bildpunkt von "in" Transparenz besitzt, ist "in2" erkennbar.

     <feComposite in="SourceGraphic" operator="over" in2="greenShadow" result="ergebnis" />

Beeindruckend, aber...

...aber eigentlich ist es doch nur ein Schlagschatten? Richtig. Die vordefinierte Filterfunktion drop-shadow() leistet das gleiche, und es gibt auch den Effekt feDropShadow, der für Schatten genutzt werden kann.

Maßeinheiten und Filterregionen

Bei dem vorigen Beispiel hatten wir gesehen, dass das feFlood-Ergebnis ein Stück größer war als ursprüngliche Rechteck. Wie ist nun diese Aussage „in jeder Richtung 10% größer“ zu verstehen? Und was ist die „Filterregion“?

Filterregion

Als Filterregion bezeichnet man den rechteckigen Ausschnitt des Bildschirms (oder welches Ausgabemedium auch immer genutzt wird), auf den ein Filter wirkt. Ihre Lage und Größe kann man in Bezug auf die Größe des Rechtecks angeben, dass das gefilterte Elements gerade noch einschließt, dies nennt man objectBoundingBox. Oder man verwendet das Koordinatensystem an der Stelle, wohin das Ergebnis gezeichnet wird, dann spricht man von userSpaceOnUse.

Welche dieser beiden Varianten verwendet wird, legt man mit Hilfe des Attributs filterUnits des filter-Elements fest. Belässt man es bei dem Standardwert objectBoundingBox, befindet sich das gefilterte Objekt an der Position (0,0) und hat die Breite und Höhe von 1. Die Umrechnung in die echte Position und Größe übernimmt der Browser. Um die Größe der Filterregion zu verändern, besitzt das filter-Element die vom Rechteck her bekannten Attribute x, y, width und height, und die Standardwerte sind x="-10%", y="-10%", width="120%" und height="120%". Ein Rechteck an Position (30,20) mit der Größe 200×150 hat damit eine Filterregion, die 240 Einheiten breit und 180 Einheiten hoch ist und sich an der Position (10,5) befindet.

Hätten wir für den Drop-Shadow Filter aus dem obigen Beispiel eine stärkere Verschiebung des Schattens gewünscht, wäre eine Anpassung von width und height erforderlich geworden.

Welche der beiden Maßeinheiten Sie verwenden, hängt von Ihrem Anwendungsfall ab. Mit userSpaceOnUse müssen Sie die Lage und die Abmessungen des gefilterten Elements kennen, ein solcher Filter ist deshalb sehr spezifisch. Dafür ermöglicht er die präzise Festlegung der Filterregion.

Filtereffekt-Subregion

Außer der Filterregion gibt es noch die Subregionen der Filtereffekte. Auch die Filtereffekte besitzen ein Rechteck, auf das sie wirken, und darüber hinaus noch weitere Maßangaben als Parameter. Beim feGaussianBlur-Filter hatten wir die Standardabweichung, und beim feOffset-Filter die Verschiebung.

Die Einheit, in der Maße für die Filtereffekte angegeben werden, wird durch das Attribut primitiveUnits festgelegt. Achtung - dies ist ein Attribut des filter-Elements, nicht des Filtereffekts, man kann diese Maßeinheit also nur für alle Filtereffekte gemeinsam festlegen. Auch hier gibt es die beiden möglichen Werte objectBoundingBox und userSpaceOnUse, aber der Standardwert ist userSpaceOnUse. Das sieht man beispielsweise beim feOffset-Effekt, dort wurde die Verschiebung in SVG-Einheiten angegeben und nicht relativ zur Größe des Rechtecks.

Der Standardwert für x, y, width und height bei Filtereffekten ist etwas komplizierter. Die Spezifikation sagt: Das Defaultrechteck einer Filtereffekt-Subregion ist kleinstmögliche Rechteck, dass die Subregionen aller vom Effekt angesprochenen „Nodes“ einschließt. Mit Nodes sind hier die Filtereffekt-Ergebnisse beziehungsweise Standard-Inputs gemeint, die mit in oder in2 angegeben wurden. Das kann nur einer sein (feOffset, feGaussianBlur), aber auch zwei (siehe feComposite) oder noch mehr (feMerge). Oder auch gar keiner, das ist bei feFlood der Fall – in diesem Fall ist die Subregion so groß wie die Filterregion.

Auch hier gilt: Welche Einheit für Sie richtig ist, hängt vom Anwendungsfall ab.

Empfehlung: Teste, ob der gewählte Begrenzungsrahmen für die Filter ausreicht, da manche Filter das Bild vergrößern. Darüber hinaus ist anzuraten, den Begrenzungsrahmen immer um einige Prozent zu vergrößern, da manche Filter die Grafik etwas ausdehnen.

Verfügbare Filtereffekte

Zum Abschluss soll noch eine Übersicht über die verfügbaren Filtereffekte gegeben werden. Zu jedem Effekt gibt es einen verlinkten Referenzartikel, der weitere Details und ein Beispiel enthält.

Effekt Kurzbeschreibung
feBlend Überblenden zweier Zwischenbilder unter Verwendung eines CSS-Blending-Modes
feColorMatrix Pixelweise Farbanpassung eines Bildes mit Hilfe einer 5×5 Übergangsmatrix
feComponentTransfer Pixelweise Farbanpassung eines Bildes mit Hilfe von Anpassungsfunktionen
feComposite Pixelweise Farbanpassung eines Bildes mit Hilfe von Anpassungsfunktionen
feConvolveMatrix Anpassen von Bildpunkten unter Betrachtung der Nachbarpunkte. Ermöglicht Operationen wie Weichzeichnen, Schärfen, Embossing, Kantenerkennung und mehr
feDiffuseLighting Erzeugen eines Zwischenbildes mit Beleuchtungsstärken, basierend auf einer von mehreren Lichtquellen.
feDisplacementMap Verschieben von Bildpunkten in einem Bild. Die Farbwerte in einem zweiten Bild werden als Verschiebungsoffsets genutzt
feDisplacementMap Der Effekt fasst mehrere andere Effekte zusammen, um einen Schlagschatten zu erzeugen
feFlood Auffüllen eines Zwischenbildes mit einer Farbe
feGaussianBlur Anwenden der Gaußschen Unschärfe auf ein Bild
feImage Laden eines anderen Bildes als neue Eingabe für weitere Effekte
feMerge Übereinanderlegen mehrerer Effektergebnisse (ohne Blending)
feMorphology Macht die Elemente in einem Bild fetter oder dünner
feOffset Macht die Elemente in einem Bild fetter oder dünner
feSpecularLighting Berechnet die Spiegelungseffekte einer Beleuchtung
feTile Verwendet ein Effektergebnis mit einer kleinen Subfilter-Region und kachelt damit die Subfilter-Region des feTile-Effekts aus
feTurbulence Erzeugt ein zufälliges Verwirbelungsmuster als Eingabe für weitere Effekte

Weblinks

  1. Wikipedia: Gaußscher Weichzeichner

Wikibooks: SVG (von 2012, aber gut erklärt und gute Beispiele])