Filtres de masque SkiaSharp
Les filtres de masque sont des effets qui manipulent la géométrie et le canal alpha des objets graphiques. Pour utiliser un filtre de masque, définissez la MaskFilter
propriété sur SKPaint
un objet de type SKMaskFilter
que vous avez créé en appelant l’une des SKMaskFilter
méthodes statiques.
La meilleure façon de se familiariser avec les filtres de masque consiste à expérimenter ces méthodes statiques. Le filtre de masque le plus utile crée un flou :
Il s’agit de la seule fonctionnalité de filtre de masque décrite dans cet article. L’article suivant sur les filtres d’images SkiaSharp décrit également un effet flou que vous pouvez préférer à celui-ci.
La méthode statique SKMaskFilter.CreateBlur
a la syntaxe suivante :
public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma);
Les surcharges permettent de spécifier des indicateurs pour l’algorithme utilisé pour créer le flou et un rectangle pour éviter le flou dans les zones couvertes par d’autres objets graphiques.
SKBlurStyle
est une énumération avec les membres suivants :
Normal
Solid
Outer
Inner
Les effets de ces styles sont présentés dans les exemples ci-dessous. Le sigma
paramètre spécifie l’étendue du flou. Dans les versions antérieures de Skia, l’étendue du flou a été indiquée avec une valeur de rayon. Si une valeur radius est préférable pour votre application, il existe une méthode statique SKMaskFilter.ConvertRadiusToSigma
qui peut passer d’une valeur à l’autre. La méthode multiplie le rayon de 0,57735 et ajoute 0,5.
La page Masquer l’expérience de flou dans l’exemple vous permet d’expérimenter les styles flous et les valeurs sigma. Le fichier XAML instancie un Picker
avec les quatre SKBlurStyle
membres d’énumération et un Slider
pour spécifier la valeur 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>
Le fichier code-behind utilise ces valeurs pour créer un SKMaskFilter
objet et le définir sur la MaskFilter
propriété d’un SKPaint
objet. Cet SKPaint
objet est utilisé pour dessiner à la fois une chaîne de texte et une bitmap :
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);
}
}
}
Voici le programme en cours d’exécution sur iOS, Android et le plateforme Windows universelle (UWP) avec le style flou et les Normal
niveaux croissants sigma
:
Vous remarquerez que seuls les bords de la bitmap sont affectés par le flou. La SKMaskFilter
classe n’est pas l’effet correct à utiliser si vous souhaitez flouter une image bitmap entière. Pour cela, vous souhaiterez utiliser la SKImageFilter
classe comme décrit dans l’article suivant sur les filtres d’images SkiaSharp.
Le texte est flou davantage avec les valeurs croissantes de l’argument sigma
. Dans l’expérience de ce programme, vous remarquerez que pour une valeur particulière sigma
, le flou est plus extrême sur le bureau Windows 10. Cette différence se produit parce que la densité de pixels est inférieure sur un moniteur de bureau que sur les appareils mobiles, et par conséquent la hauteur du texte en pixels est inférieure. La sigma
valeur est proportionnelle à une étendue floue en pixels. Par conséquent, pour une valeur donnée sigma
, l’effet est plus extrême sur les affichages de résolution inférieure. Dans une application de production, vous souhaiterez probablement calculer une sigma
valeur proportionnelle à la taille du graphique.
Essayez plusieurs valeurs avant de vous installer sur un niveau flou qui semble le mieux pour votre application. Par exemple, dans la page Flou du masque, essayez de définir sigma
comme suit :
sigma = paint.TextSize / 18;
paint.MaskFilter = SKMaskFilter.CreateBlur(blurStyle, sigma);
Maintenant, le Slider
degré de flou n’a aucun effet, mais le degré de flou est cohérent entre les plateformes :
Toutes les captures d’écran jusqu’à présent ont montré un flou créé avec le membre d’énumération SKBlurStyle.Normal
. Les captures d’écran suivantes montrent les effets des Solid
styles , Outer
et Inner
flou :
La capture d’écran iOS montre le Solid
style : les caractères de texte sont toujours présents sous forme de traits noirs solides, et le flou est ajouté à l’extérieur de ces caractères de texte.
La capture d’écran Android au milieu montre le Outer
style : les traits de caractères eux-mêmes sont éliminés (comme c’est le bitmap) et le flou entoure l’espace vide où les caractères de texte sont apparus une fois.
La capture d’écran UWP à droite montre le Inner
style. Le flou est limité à la zone occupée normalement par les caractères de texte.
L’article de dégradé linéaire SkiaSharp a décrit un programme de dégradé d’Réflexions ion qui a utilisé un dégradé linéaire et une transformation pour imiter une réflexion d’une chaîne de texte :
La page Floue Réflexions ion ajoute une instruction unique à ce code :
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);
}
}
}
La nouvelle instruction ajoute un filtre flou pour le texte réfléchi basé sur la taille du texte :
paint.MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, paint.TextSize / 36);
Ce filtre flou provoque la réflexion beaucoup plus réaliste :