SkiaSharp Maskenfilter
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:
Beispiel
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:
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:
Alle Bisherigen Screenshots zeigen Unschärfen, die mit dem Enumerationsmember SKBlurStyle.Normal
erstellt wurden. Die folgenden Screenshots zeigen die Auswirkungen der Solid
Formatvorlagen , Outer
, und Inner
Unschärfe:
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: