SkiaSharp Mask Filter
Maskenfilter sind Effekte, die die Geometrie und den Alphakanal grafischer Objekte bearbeiten. Um einen Maskenfilter zu verwenden, legen Sie die MaskFilter
Eigenschaft eines SKPaint
Typs SKMaskFilter
fest, das Sie durch Aufrufen einer der SKMaskFilter
statischen Methoden erstellt haben.
Die beste Möglichkeit, sich mit Maskenfiltern vertraut zu machen, besteht darin, mit diesen statischen Methoden zu experimentieren. Der nützlichste Maskenfilter erstellt einen Weichzeichner:
Dies ist das einzige Maskenfilterfeature, das in diesem Artikel beschrieben wird. Im nächsten Artikel zu SkiaSharp-Bildfiltern wird auch ein Weichzeichnereffekt beschrieben, 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 des Weichzeichnens verwendet wird, und ein Rechteck, um zu vermeiden, dass in Bereichen, die mit anderen grafischen Objekten abgedeckt werden, verschwommen werden.
SKBlurStyle
ist eine Aufzählung mit den folgenden Membern:
Normal
Solid
Outer
Inner
Die Effekte dieser Formatvorlagen werden in den folgenden Beispielen gezeigt. Der sigma
Parameter gibt den Umfang des Weichzeichners an. In älteren Versionen von Skia wurde der Umfang des Weichzeichners mit einem Radiuswert angegeben. Wenn ein Radiuswert für Ihre Anwendung bevorzugt wird, gibt es eine statische SKMaskFilter.ConvertRadiusToSigma
Methode, die von einer in die andere konvertiert werden kann. Die Methode multipliziert den Radius um 0,57735 und addiert 0,5.
Auf der Seite "Mask Blur Experiment" im Beispiel können Sie mit den Weichzeichnerarten und Sigmawerten experimentieren. Die XAML-Datei instanziiert eine Picker
mit den vier SKBlurStyle
Enumerationsmembern und eine 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 ist das Programm, das unter iOS, Android und dem Universelle Windows-Plattform (UWP) ausgeführt wird, mit dem Weichzeichnerstil und der Erhöhung sigma
der Normal
Ebenen:
Sie werden feststellen, dass nur die Kanten der Bitmap vom Weichzeichner betroffen sind. Die SKMaskFilter
Klasse ist nicht der richtige Effekt, der verwendet werden soll, wenn Sie ein gesamtes Bitmapbild weichzeichnen möchten. Dafür sollten Sie die SKImageFilter
Klasse wie im nächsten Artikel zu SkiaSharp-Bildfiltern beschrieben verwenden.
Der Text wird mit zunehmenden Werten des sigma
Arguments verschwommen. Beim Experimentieren mit diesem Programm werden Sie feststellen, dass der Weichzeichner für einen bestimmten sigma
Wert auf dem Windows 10-Desktop extremer ist. Dieser Unterschied tritt auf, da die Pixeldichte auf einem Desktopmonitor niedriger ist als auf mobilen Geräten, und daher ist die Texthöhe in Pixeln niedriger. Der sigma
Wert ist proportional zu einem Weichzeichner in Pixeln, daher ist der Effekt für einen bestimmten sigma
Wert extremer auf Displays mit niedrigerer Auflösung. In einer Produktionsanwendung möchten Sie wahrscheinlich einen sigma
Wert berechnen, der proportional zur Größe der Grafik ist.
Probieren Sie mehrere Werte aus, bevor Sie sich auf einer Weichzeichnerebene niederlassen, die für Ihre Anwendung am besten geeignet ist. Versuchen Sie z. B. auf der Seite "Mask blur Experiment " die Einstellung sigma
wie folgt:
sigma = paint.TextSize / 18;
paint.MaskFilter = SKMaskFilter.CreateBlur(blurStyle, sigma);
Jetzt hat dies Slider
keine Wirkung, aber der Grad des Weichzeichnens ist unter den Plattformen konsistent:
Alle bisher erstellten Screenshots haben den Weichzeichner mit dem SKBlurStyle.Normal
Enumerationselement erstellt. Die folgenden Screenshots zeigen die Effekte der Solid
Formatvorlagen , Outer
und Inner
Weichzeichner:
Der iOS-Screenshot zeigt die Solid
Formatvorlage: Die Textzeichen sind weiterhin als einfarbige schwarze Striche vorhanden, und der Weichzeichner wird außerhalb dieser Textzeichen hinzugefügt.
Der Android-Screenshot in der Mitte zeigt die Outer
Formatvorlage: Die Zeichenstriche selbst werden entfernt (wie die Bitmap), und der Weichzeichner umgibt den leeren Bereich, in dem die Textzeichen einmal angezeigt wurden.
Der UWP-Screenshot auf der rechten Seite zeigt die Inner
Formatvorlage. Der Weichzeichner ist auf den Bereich beschränkt, der normalerweise von den Textzeichen belegt wird.
Der Linearverlaufsartikel "SkiaSharp" beschreibt ein Reflection Gradient-Programm, das einen linearen Farbverlauf und eine Transformation verwendet hat, um eine Spiegelung einer Textzeichenfolge nachzuahmen:
Die Seite "Verschwommene Spiegelung " 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 Weichzeichnerfilter bewirkt, dass die Reflexion viel realistischer erscheint: