Freigeben über


SkiaSharp-Farbfilter

Farbfilter können Farben in einer Bitmap (oder einem anderen Bild) in andere Farben für Effekte wie die Posterisierung übersetzen:

Beispiel für Farbfilter

Um einen Farbfilter zu verwenden, legen Sie die ColorFilter Eigenschaft auf SKPaint ein Objekt vom Typ SKColorFilter fest, das von einer der statischen Methoden in dieser Klasse erstellt wurde. Dieser Artikel demonstriert Folgendes:

  • eine farbtransformation, die mit der CreateColorMatrix Methode erstellt wurde.
  • eine Farbtabelle, die mit der CreateTable Methode erstellt wurde.

Die Farbtransformation

Die Farbtransformation umfasst die Verwendung einer Matrix zum Ändern von Farben. Wie die meisten 2D-Grafiksysteme verwendet SkiaSharp Matrizen hauptsächlich zum Transformieren von Koordinatenpunkten, wie im Artikel Matrix Transforms in SkiaSharp beschrieben. Dies SKColorFilter unterstützt auch Matrixtransformationen, aber die Matrix transformiert RGB-Farben. Einige Kenntnisse mit Matrixkonzepten sind erforderlich, um diese Farbtransformationen zu verstehen.

Die Farbtransformationsmatrix weist eine Dimension von vier Zeilen und fünf Spalten auf:

| M11 M12 M13 M14 M15 |
| M21 M22 M23 M24 M25 |
| M31 M32 M33 M34 M35 |
| M41 M42 M43 M44 M45 |

Es transformiert eine RGB-Quellfarbe (R, G, B, A) in die Zielfarbe (R', G', B', A').

In Vorbereitung auf die Matrixmultiplikation wird die Quellfarbe in eine 5×1-Matrix konvertiert:

| R |
| G |
| B |
| A |
| 1 |

Diese R-, G-, B- und A-Werte sind die ursprünglichen Bytes zwischen 0 und 255. Sie werden nicht auf Gleitkommawerte im Bereich 0 bis 1 normalisiert.

Die zusätzliche Zelle ist für einen Übersetzungsfaktor erforderlich. Dies entspricht der Verwendung einer 3×3-Matrix zum Transformieren von zweidimensionalen Koordinatenpunkten, wie im Abschnitt "Grund für die 3:3-Matrix " im Artikel zur Verwendung von Matrizen zum Transformieren von Koordinatenpunkten beschrieben.

Die 4×5-Matrix wird mit der Matrix 5×1 multipliziert, und das Produkt ist eine 4×1-Matrix mit der transformierten Farbe:

| M11 M12 M13 M14 M15 |    | R |   | R' |
| M21 M22 M23 M24 M25 |    | G |   | G' |
| M31 M32 M33 M34 M35 |  × | B | = | B' |
| M41 M42 M43 M44 M45 |    | A |   | A' |
                           | 1 |

Hier sind die separaten Formeln für R', G', B' und A':

R' = M11·R + M12·G + M13·B + M14·A + M15

G' = M21·R + M22·G + M23·B + M24·A + M25

B' = M31·R + M32·G + M33·B + M34·A + M35

A' = M41·R + M42·G + M43·B + M44·A + M45

Die meisten der Matrix bestehen aus multiplizierten Faktoren, die sich im Allgemeinen im Bereich von 0 bis 2 befinden. Die letzte Spalte (M15 bis M45) enthält jedoch Werte, die in den Formeln hinzugefügt werden. Diese Werte liegen im Allgemeinen zwischen 0 und 255. Die Ergebnisse werden zwischen den Werten 0 und 255 eingeklemmt.

Die Identitätsmatrix lautet:

| 1 0 0 0 0 |
| 0 1 0 0 0 |
| 0 0 1 0 0 |
| 0 0 0 1 0 |

Dies führt zu keiner Änderung der Farben. Die Transformationsformeln sind:

R' = R

G' = G

B' = B

A' = A

Die M44-Zelle ist sehr wichtig, da sie die Deckkraft bewahrt. Es ist in der Regel der Fall, dass M41, M42 und M43 alle null sind, da Sie wahrscheinlich keine Deckkraft auf den Werten rot, grün und blau basieren sollen. Wenn M44 aber null ist, wird A' null sein, und nichts wird sichtbar.

Eine der am häufigsten verwendeten Verwendungen der Farbmatrix besteht darin, eine Farbbitmap in eine Grauskalierungsbitmap zu konvertieren. Dies umfasst eine Formel für einen gewichteten Mittelwert der Rot-, Grün- und Blauwerte. Bei Videoanzeigen mit dem sRGB-Farbraum ("Standardrotgrünblau") lautet die folgende Formel:

Grauschattierung = 0,2126· R + 0,7152· G + 0,0722· B

Um eine Farbbitmap in eine Grauskala-Bitmap zu konvertieren, müssen die Ergebnisse von R', G' und B denselben Wert aufweisen. Die Matrix lautet:

| 0.21 0.72 0.07 0 0 |
| 0.21 0.72 0.07 0 0 |
| 0.21 0.72 0.07 0 0 |
| 0    0    0    1 0 |

Es gibt keinen SkiaSharp-Datentyp, der dieser Matrix entspricht. Stattdessen müssen Sie die Matrix als Matrix mit 20 float Werten in der Zeilenreihenfolge darstellen: erste Zeile, dann zweite Zeile usw.

Die statische SKColorFilter.CreateColorMatrix Methode weist die folgende Syntax auf:

public static SKColorFilter CreateColorMatrix (float[] matrix);

dabei matrix handelt es sich um ein Array der 20 float Werte. Beim Erstellen des Arrays in C# ist es einfach, die Zahlen so zu formatieren, dass sie der Matrix 4×5 ähneln. Dies wird auf der Seite "Grauskalamatrix " im Beispiel veranschaulicht:

public class GrayScaleMatrixPage : ContentPage
{
    SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
                        typeof(CenteredTilesPage),
                        "SkiaSharpFormsDemos.Media.Banana.jpg");

    public GrayScaleMatrixPage()
    {
        Title = "Gray-Scale Matrix";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {
            paint.ColorFilter =
                SKColorFilter.CreateColorMatrix(new float[]
                {
                    0.21f, 0.72f, 0.07f, 0, 0,
                    0.21f, 0.72f, 0.07f, 0, 0,
                    0.21f, 0.72f, 0.07f, 0, 0,
                    0,     0,     0,     1, 0
                });

            canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
        }
    }
}

Die DrawBitmap in diesem Code verwendete Methode stammt aus der BitmapExtension.cs Datei, die im Beispiel enthalten ist.

Hier sehen Sie das Ergebnis, das unter iOS, Android und Universelle Windows-Plattform ausgeführt wird:

Graumaßstab-Matrix

Achten Sie auf den Wert in der vierten Zeile und vierten Spalte. Dies ist der entscheidende Faktor, der mit dem A-Wert der Originalfarbe für den A-Wert der transformierten Farbe multipliziert wird. Wenn diese Zelle null ist, wird nichts angezeigt, und das Problem kann schwer zu finden sein.

Beim Experimentieren mit Farbmatrizen können Sie die Transformation entweder aus der Perspektive der Quelle oder der Perspektive des Ziels behandeln. Wie soll das rote Pixel der Quelle zu den roten, grünen und blauen Pixeln des Ziels beitragen? Dies wird durch die Werte in der ersten Spalte der Matrix bestimmt. Alternativ dazu, wie sollte das rote Zielpixel von den roten, grünen und blauen Pixeln der Quelle beeinflusst werden? Dies wird durch die erste Zeile der Matrix bestimmt.

Einige Ideen zur Verwendung von Farbtransformationen finden Sie auf den Seiten "Bilder neu einfärben ". Die Diskussion betrifft Windows Forms, und die Matrix ist ein anderes Format, aber die Konzepte sind identisch.

Die Pastellmatrix berechnet das rote Zielpixel, indem das rote Quellpixel abgeschwächt und die roten und grünen Pixel leicht hervorgehoben werden. Dieser Vorgang tritt für die grünen und blauen Pixel auf ähnliche Weise auf:

public class PastelMatrixPage : ContentPage
{
    SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
                        typeof(PastelMatrixPage),
                        "SkiaSharpFormsDemos.Media.MountainClimbers.jpg");

    public PastelMatrixPage()
    {
        Title = "Pastel Matrix";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {
            paint.ColorFilter =
                SKColorFilter.CreateColorMatrix(new float[]
                {
                    0.75f, 0.25f, 0.25f, 0, 0,
                    0.25f, 0.75f, 0.25f, 0, 0,
                    0.25f, 0.25f, 0.75f, 0, 0,
                    0, 0, 0, 1, 0
                });

            canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
        }
    }
}

Das Ergebnis besteht darin, die Intensität der Farben stummzuschalten, wie Sie hier sehen können:

Pastellmatrix

Farbtabellen

Die statische SKColorFilter.CreateTable Methode wird in zwei Versionen verwendet:

public static SKColorFilter CreateTable (byte[] table);

public static SKColorFilter CreateTable (byte[] tableA, byte[] tableR, byte[] tableG, byte[] tableB);

Die Arrays enthalten immer 256 Einträge. In der CreateTable Methode mit einer Tabelle wird dieselbe Tabelle für die roten, grünen und blauen Komponenten verwendet. Es handelt sich um eine einfache Nachschlagetabelle: Wenn die Quellfarbe (R, G, B) und die Zielfarbe (R', B', G') lautet, werden die Zielkomponenten durch Indizieren table mit den Quellkomponenten abgerufen:

R' = table[R]

G' = table[G]

B' = table[B]

In der zweiten Methode kann jede von vier Farbkomponenten eine separate Farbtabelle aufweisen, oder die gleichen Farbtabellen können von zwei oder mehr Komponenten gemeinsam verwendet werden.

Wenn Sie eines der Argumente auf die zweite CreateTable Methode auf eine Farbtabelle festlegen möchten, die die Werte 0 bis 255 in Folge enthält, können Sie stattdessen verwenden null . Sehr oft hat der CreateTable Aufruf ein null erstes Argument für den Alphakanal.

Im Abschnitt " Posterisierung " im Artikel zum Zugreifen auf SkiaSharp-Bitmappixelbits haben Sie gesehen, wie Sie die einzelnen Pixelbits einer Bitmap ändern, um die Farbauflösung zu verringern. Dies ist eine Technik, die als Posterisierung bezeichnet wird.

Sie können eine Bitmap auch mit einer Farbtabelle posterisieren. Der Konstruktor der Seite "Tabelle posterisieren " erstellt eine Farbtabelle, die ihren Index einem Byte zuordnet, wobei die unteren 6 Bits auf Null festgelegt sind:

public class PosterizeTablePage : ContentPage
{
    SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
                        typeof(PosterizeTablePage),
                        "SkiaSharpFormsDemos.Media.MonkeyFace.png");

    byte[] colorTable = new byte[256];

    public PosterizeTablePage()
    {
        Title = "Posterize Table";

        // Create color table
        for (int i = 0; i < 256; i++)
        {
            colorTable[i] = (byte)(0xC0 & i);
        }

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {
            paint.ColorFilter =
                SKColorFilter.CreateTable(null, null, colorTable, colorTable);

            canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
        }
    }
}

Das Programm wählt diese Farbtabelle nur für die grünen und blauen Kanäle aus. Der rote Kanal hat weiterhin volle Auflösung:

Posterize Table

Sie können verschiedene Farbtabellen für die verschiedenen Farbkanäle für verschiedene Effekte verwenden.