SkiaSharp Maskenfilter

Beispiel herunterladen Das Beispiel herunterladen

Maskenfilter sind Effekte, die die Geometrie und den Alphakanal grafischer Objekte bearbeiten. Um einen Maskenfilter zu verwenden, legen Sie die MaskFilter Eigenschaft von SKPaint auf ein Objekt vom Typ SKMaskFilter fest, das Sie erstellt haben, indem Sie eine der SKMaskFilter statischen Methoden aufrufen.

Die beste Möglichkeit, sich mit Maskenfiltern vertraut zu machen, besteht darin, mit diesen statischen Methoden zu experimentieren. Der nützlichste Maskenfilter erzeugt eine Unschärfe:

fürBeispiel

Dies ist die einzige Maskenfilterfunktion, die in diesem Artikel beschrieben wird. Der nächste Artikel zu SkiaSharp-Bildfiltern beschreibt auch einen Unschärfeeffekt, den Sie diesem vorziehen könnten.

Die statische SKMaskFilter.CreateBlur Methode weist die folgende Syntax auf:

public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma);

Überladungen ermöglichen das Angeben von Flags für den Algorithmus, der zum Erstellen der Unschärfe verwendet wird, und ein Rechteck, um zu vermeiden, dass in Bereichen, die mit anderen grafischen Objekten abgedeckt werden, unschärfen.

SKBlurStyle ist eine Enumeration mit den folgenden Membern:

  • Normal
  • Solid
  • Outer
  • Inner

Die Auswirkungen dieser Stile sind in den folgenden Beispielen dargestellt. Der sigma Parameter gibt den Umfang der Unschärfe an. In älteren Versionen von Skia wurde der Umfang der Unschärfe mit einem Radiuswert angegeben. Wenn ein Radiuswert für Ihre Anwendung vorzuziehen ist, gibt es eine statische SKMaskFilter.ConvertRadiusToSigma Methode, die von einer in die andere konvertieren kann. Die Methode multipliziert den Radius mit 0,57735 und fügt 0,5 hinzu.

Auf der Seite Mask Blur Experiment im SkiaSharpFormsDemos-Beispiel können Sie mit den Weichzeichnerstilen und Sigmawerten experimentieren. Die XAML-Datei instanziiert ein Picker mit den vier SKBlurStyle Enumerationsmembern und ein Slider zum Angeben des Sigmawerts:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp;assembly=SkiaSharp"
             xmlns:skiaforms="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.MaskBlurExperimentPage"
             Title="Mask Blur Experiment">
    
    <StackLayout>
        <skiaforms:SKCanvasView x:Name="canvasView"
                                VerticalOptions="FillAndExpand"
                                PaintSurface="OnCanvasViewPaintSurface" />

        <Picker x:Name="blurStylePicker" 
                Title="Filter Blur Style" 
                Margin="10, 0"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKBlurStyle}">
                    <x:Static Member="skia:SKBlurStyle.Normal" />
                    <x:Static Member="skia:SKBlurStyle.Solid" />
                    <x:Static Member="skia:SKBlurStyle.Outer" />
                    <x:Static Member="skia:SKBlurStyle.Inner" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <Slider x:Name="sigmaSlider"
                Maximum="10"
                Margin="10, 0"
                ValueChanged="OnSliderValueChanged" />

        <Label Text="{Binding Source={x:Reference sigmaSlider},
                              Path=Value,
                              StringFormat='Sigma = {0:F1}'}"
               HorizontalTextAlignment="Center" />
    </StackLayout>
</ContentPage>

Die CodeBehind-Datei verwendet diese Werte, um ein SKMaskFilter -Objekt zu erstellen und auf die MaskFilter -Eigenschaft eines SKPaint -Objekts festzulegen. Dieses SKPaint Objekt wird verwendet, um sowohl eine Textzeichenfolge als auch eine Bitmap zu zeichnen:

public partial class MaskBlurExperimentPage : ContentPage
{
    const string TEXT = "Blur My Text";

    SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
                            typeof(MaskBlurExperimentPage), 
                            "SkiaSharpFormsDemos.Media.SeatedMonkey.jpg");

    public MaskBlurExperimentPage ()
    {
        InitializeComponent ();
    }

    void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

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

        canvas.Clear(SKColors.Pink);

        // Get values from XAML controls
        SKBlurStyle blurStyle =
            (SKBlurStyle)(blurStylePicker.SelectedIndex == -1 ?
                                        0 : blurStylePicker.SelectedItem);

        float sigma = (float)sigmaSlider.Value;

        using (SKPaint paint = new SKPaint())
        {
            // Set SKPaint properties
            paint.TextSize = (info.Width - 100) / (TEXT.Length / 2);
            paint.MaskFilter = SKMaskFilter.CreateBlur(blurStyle, sigma);

            // Get text bounds and calculate display rectangle
            SKRect textBounds = new SKRect();
            paint.MeasureText(TEXT, ref textBounds);
            SKRect textRect = new SKRect(0, 0, info.Width, textBounds.Height + 50);

            // Center the text in the display rectangle
            float xText = textRect.Width / 2 - textBounds.MidX;
            float yText = textRect.Height / 2 - textBounds.MidY;

            canvas.DrawText(TEXT, xText, yText, paint);

            // Calculate rectangle for bitmap
            SKRect bitmapRect = new SKRect(0, textRect.Bottom, info.Width, info.Height);
            bitmapRect.Inflate(-50, -50);

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

Hier sehen Sie das Programm, das unter iOS, Android und dem Universelle Windows-Plattform (UWP) mit dem Normal Weichzeichnerstil und steigenden sigma Ebenen ausgeführt wird:

Mask Blur Experiment – Normal

Sie werden feststellen, dass nur die Kanten der Bitmap von der Unschärfe betroffen sind. Die SKMaskFilter -Klasse ist nicht der richtige Effekt, der verwendet werden kann, wenn Sie ein gesamtes Bitmapbild unschärfen möchten. Dazu sollten Sie die SKImageFilter -Klasse verwenden, wie im nächsten Artikel zu SkiaSharp-Bildfiltern beschrieben.

Der Text wird mit zunehmenden Werten des sigma Arguments mehr verschwommen. Wenn Sie mit diesem Programm experimentieren, werden Sie feststellen, dass für einen bestimmten sigma Wert die Unschärfe auf dem Windows 10 Desktops extremer ist. Dieser Unterschied tritt auf, weil die Pixeldichte auf einem Desktopmonitor niedriger ist als auf mobilen Geräten und daher die Texthöhe in Pixel niedriger ist. Der sigma Wert ist proportional zu einer Unschärfenausdehnung in Pixel, sodass der Effekt für einen bestimmten sigma Wert auf Displays mit niedrigerer Auflösung extremer ist. In einer Produktionsanwendung sollten Sie wahrscheinlich einen sigma Wert berechnen, der proportional zur Größe der Grafik ist.

Testen Sie mehrere Werte, bevor Sie sich auf eine Unschärfenebene festlegen, die für Ihre Anwendung am besten aussieht. Versuchen Sie beispielsweise auf der Seite Mask Blur Experiment die Einstellung sigma wie folgt:

sigma = paint.TextSize / 18;
paint.MaskFilter = SKMaskFilter.CreateBlur(blurStyle, sigma);

Jetzt hat die Slider keine Auswirkung, aber der Grad der Unschärfe ist konsistent zwischen den Plattformen:

MaskEnunschärfe-Experiment – Experiment mit konsistenter

Alle Bisherigen Screenshots zeigen Unschärfen, die mit dem Enumerationsmember SKBlurStyle.Normal erstellt wurden. Die folgenden Screenshots zeigen die Auswirkungen der SolidFormatvorlagen , Outer, und Inner Unschärfe:

Mask Blur Experiment

Der iOS-Screenshot zeigt den Solid Stil: Die Textzeichen sind weiterhin als durchgehende schwarze Striche vorhanden, und die Unschärfe wird an der Außenseite dieser Textzeichen hinzugefügt.

Der Android-Screenshot in der Mitte zeigt den Outer Stil: Die Zeichenstriche selbst werden eliminiert (wie die Bitmap), und die Unschärfe umgibt den leeren Raum, in dem die Textzeichen einmal erschienen sind.

Der UWP-Screenshot auf der rechten Seite zeigt den Inner Stil. Die Unschärfe ist auf den Bereich beschränkt, der normalerweise von den Textzeichen belegt wird.

Im Artikel SkiaSharp linearer Farbverlauf wurde ein Reflexionsverlaufsprogramm beschrieben, das einen linearen Farbverlauf und eine Transformation verwendet, um eine Reflexion einer Textzeichenfolge nachzuahmen:

Die Seite Verschwommene Reflexion fügt diesem Code eine einzelne Anweisung hinzu:

public class BlurryReflectionPage : ContentPage
{
    const string TEXT = "Reflection";

    public BlurryReflectionPage()
    {
        Title = "Blurry Reflection";

        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())
        {
            // Set text color to blue
            paint.Color = SKColors.Blue;

            // Set text size to fill 90% of width
            paint.TextSize = 100;
            float width = paint.MeasureText(TEXT);
            float scale = 0.9f * info.Width / width;
            paint.TextSize *= scale;

            // Get text bounds
            SKRect textBounds = new SKRect();
            paint.MeasureText(TEXT, ref textBounds);

            // Calculate offsets to position text above center
            float xText = info.Width / 2 - textBounds.MidX;
            float yText = info.Height / 2;

            // Draw unreflected text
            canvas.DrawText(TEXT, xText, yText, paint);

            // Shift textBounds to match displayed text
            textBounds.Offset(xText, yText);

            // Use those offsets to create a gradient for the reflected text
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(0, textBounds.Top),
                                new SKPoint(0, textBounds.Bottom),
                                new SKColor[] { paint.Color.WithAlpha(0),
                                                paint.Color.WithAlpha(0x80) },
                                null,
                                SKShaderTileMode.Clamp);

            // Create a blur mask filter
            paint.MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, paint.TextSize / 36);

            // Scale the canvas to flip upside-down around the vertical center
            canvas.Scale(1, -1, 0, yText);

            // Draw reflected text
            canvas.DrawText(TEXT, xText, yText, paint);
        }
    }
}

Die neue Anweisung fügt einen Weichzeichnerfilter für den reflektierten Text hinzu, der auf der Textgröße basiert:

paint.MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, paint.TextSize / 36);

Dieser Unschärfenfilter lässt die Reflexion viel realistischer erscheinen:

Verschwommene Reflexion