Filtry masek ve skiasharpu

Ukázka stažení Stažení ukázky

Filtry masek jsou efekty, které zpracovávají geometrii a alfa kanál grafických objektů. Chcete-li použít filtr masek, 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 masek, je experimentovat s těmito statickými metodami. Nejužitečnější filtr masek vytvoří rozostření:

Blur ExamplePříklad –

Toto je jediná funkce filtru masek popsaná v tomto článku. Další článek o filtrech obrázků ve skiasharpu také popisuje efekt rozostření, který byste mohli upřednostňovat.

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 pro zamezení rozostření v oblastech, které budou pokryty dalšími grafickými objekty.

SKBlurStyle je výčet s následujícími členy:

  • Normal
  • Solid
  • Outer
  • Inner

Účinky těchto stylů jsou uvedeny v níže uvedených příkladech. sigmaParametr určuje rozsah rozostření. Ve starších verzích Skia byl rozsah rozostření označen hodnotou poloměru. Pokud je pro vaši aplikaci vhodnější hodnota poloměru, existuje statická SKMaskFilter.ConvertRadiusToSigma metoda, která může být převedena z jednoho na druhý. Metoda vynásobí poloměr o 0,57735 a přidá 0,5.

Stránka experiment rozostření masky v ukázce SkiaSharpFormsDemos umožňuje experimentovat s hodnotami rozostření a hodnotami Sigma. Soubor XAML vytvoří instanci Picker se čtyřmi SKBlurStyle členy výčtu a a Slider pro zadání 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 na pozadí používá tyto hodnoty k vytvoření SKMaskFilter objektu a jeho nastavení na MaskFilter vlastnost SKPaint objektu. Tento SKPaint objekt se používá k nakreslení 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í v iOS, androidu a Univerzální platforma Windows (UWP) se Normal stylem rozostření a rostoucími sigma úrovněmi:

Experiment rozostření masky – experiment – normální

Všimněte si, že rozostření ovlivňuje jenom okraje rastrového obrázku. SKMaskFilterTřída není správného efektu pro použití, pokud chcete Rozostřit celou bitovou kopii. Aby bylo možné použít třídu, jak je SKImageFilter popsáno v dalším článku o SKImageFilter.

Text je rozmazaný více o rostoucí hodnoty sigma argumentu. v rámci experimentování s tímto programem si všimnete, že pro konkrétní sigma hodnotu je rozostření na Windows 10 plochu mnohem extrémní. K tomuto rozdílu dochází, protože hustota pixelů je nižší než na mobilních zařízeních, a proto je výška textu v pixelech nižší. sigmaHodnota je úměrná rozsahu rozostření v pixelech, takže pro danou sigma hodnotu je efekt mnohem extrémní na zobrazení s nižším rozlišením. V produkční aplikaci pravděpodobně budete chtít vypočítat sigma hodnotu, která je úměrná velikosti grafiky.

Před vyrovnáním na úrovni rozostření, která je pro vaši aplikaci nejvhodnější, zkuste použít několik hodnot. Například na stránce experimenty při rozostření masky zkuste nastavit toto nastavení takto :

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

Nyní Slider nemá žádný účinek, ale stupeň rozostření je v rámci platforem konzistentní:

Experimenty při rozostření masky –

Všechny snímky obrazovky doposud ukázaly rozostření vytvořené se SKBlurStyle.Normal členem výčtu. Následující snímky obrazovky ukazují efekty SolidOuter stylů, a Inner rozostření:

masek experimenty

Snímek obrazovky iOS zobrazuje Solid styl: textové znaky jsou pořád přítomné jako plné černé tahy a rozostření je přidané na vnější z těchto textových znaků.

Snímek obrazovky se systémem Android v prostředním tvaru znázorňuje Outer styl: tahy znaků samotné jsou eliminovány (jako rastrové obrázky) a rozostří ohraničení prázdného místa, kde se zobrazily textové znaky.

Snímek UWP na pravé straně zobrazuje Inner styl. Rozostření je omezeno na oblast obvykle obsazenou textovými znaky.

Článek ve skiasharpu lineárního přechodu popisuje program přechodu odrazů , který používal lineární přechod a transformaci, aby napodoboval odraz textového řetězce:

Barevný přechod odrazu

Stránka rozmazaných reflexe přidá do tohoto 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 zrcadlený text, který je 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ší:

Fuzzy reflexe fuzzy