Filtry masky SkiaSharp
Filtry masky jsou efekty, které manipulují s geometrií a alfa kanálem grafických objektů. Pokud chcete použít filtr masky, nastavte MaskFilter
vlastnost SKPaint
na objekt typu SKMaskFilter
, který jste vytvořili voláním jedné ze SKMaskFilter
statických metod.
Nejlepším způsobem, jak se seznámit s filtry masky, je experimentování s těmito statickými metodami. Nejužitečnější filtr masky vytvoří rozostření:
To je jediná funkce filtru masky popsaná v tomto článku. Další článek o filtrech obrázků SkiaSharp popisuje také rozostření efektu, který byste mohli raději použít.
Statická SKMaskFilter.CreateBlur
metoda má následující syntaxi:
public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma);
Přetížení umožňují zadat příznaky pro algoritmus použitý k vytvoření rozostření a obdélník, aby se zabránilo rozostření v oblastech, které budou pokryty jinými grafickými objekty.
SKBlurStyle
je výčet s následujícími členy:
Normal
Solid
Outer
Inner
Efekty těchto stylů jsou uvedeny v následujících příkladech. Parametr sigma
určuje rozsah rozostření. Ve starších verzích Skia byl rozsah rozostření označen hodnotou poloměru. Pokud je hodnota poloměru pro vaši aplikaci vhodnější, existuje statická SKMaskFilter.ConvertRadiusToSigma
metoda, která může převést z jedné na druhou. Metoda vynásobí poloměr hodnotou 0,57735 a přičte hodnotu 0,5.
Stránka s rozostřením masky v ukázce SkiaSharpFormsDemos umožňuje experimentovat se styly rozostření a hodnotami sigma. Soubor XAML vytvoří Picker
instanci se čtyřmi SKBlurStyle
členy výčtu a hodnotou Slider
pro určení hodnoty sigma:
<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>
Soubor kódu používá tyto hodnoty k vytvoření objektu SKMaskFilter
a jeho nastavení na MaskFilter
vlastnost objektu SKPaint
. Tento SKPaint
objekt se používá k vykreslení textového řetězce i rastrového obrázku:
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);
}
}
}
Tady je program běžící na iOSu, Androidu a Univerzální platforma Windows (UPW) s rozostřením Normal
a zvýšením sigma
úrovní:
Všimněte si, že rozostření ovlivní jenom okraje rastrového obrázku. Třída SKMaskFilter
není správný efekt, který se má použít, pokud chcete rozostřit celý rastrový obrázek. Pro to budete chtít použít SKImageFilter
třídu, jak je popsáno v dalším článku o filtrech obrázků SkiaSharp.
Text je rozmazanější s rostoucími hodnotami argumentu sigma
. Při experimentování s tímto programem si všimnete, že pro určitou sigma
hodnotu je rozostření na stolním počítači s Windows 10 mnohem extrémní. K tomuto rozdílu dochází, protože hustota pixelů je nižší na stolním monitoru než na mobilních zařízeních, a proto je výška textu v pixelech nižší. Hodnota sigma
je úměrná rozostření v pixelech, takže pro danou sigma
hodnotu je efekt na displejích s nižším rozlišením extrémnější. V produkční aplikaci budete pravděpodobně chtít vypočítat sigma
hodnotu, která je úměrná velikosti grafiky.
Zkuste několik hodnot před vyrovnáním na rozostření, která vypadá nejlépe pro vaši aplikaci. Například na stránce s rozostřením masky experimentu zkuste nastavit sigma
takto:
sigma = paint.TextSize / 18;
paint.MaskFilter = SKMaskFilter.CreateBlur(blurStyle, sigma);
Slider
Nyní nemá žádný vliv, ale stupeň rozostření je konzistentní mezi platformami:
Všechny snímky obrazovky zatím zobrazovaly rozostření vytvořené pomocí člena výčtu SKBlurStyle.Normal
. Následující snímky obrazovky znázorňují efekty Solid
stylů , Outer
a Inner
rozostření:
Snímek obrazovky iOS ukazuje Solid
styl: Textové znaky jsou stále přítomné jako plné černé tahy a rozostření se přidá do vnější části těchto znaků textu.
Snímek obrazovky s Androidem uprostřed zobrazuje Outer
styl: Samotné tahy znaků jsou eliminovány (stejně jako rastrový obrázek) a rozostření obklopuje prázdné místo, kde se znaky textu objeví.
Snímek obrazovky UPW na pravé straně zobrazuje Inner
styl. Rozostření je omezeno na oblast, která je obvykle obsazena textovými znaky.
Článek o lineárním přechodu SkiaSharp popsal program přechodu Reflexe ion, který použil lineární přechod a transformaci k napodobení odrazu textového řetězce:
Stránka rozmazaného Reflexe ionu přidá do kódu jeden příkaz:
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);
}
}
}
Nový příkaz přidá filtr rozostření pro odražený text založený na velikosti textu:
paint.MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, paint.TextSize / 36);
Tento filtr rozostření způsobí, že odraz bude mnohem realističtější: