SkiaSharp bit eşlemlerini görüntüleme

SkiaSharp bit eşlemlerinin konusu, SkiaSharp'ta Bit Eşlem Temelleri makalesinde tanıtıldı. Bu makalede bit eşlemleri yüklemenin üç yolu ve bit eşlemleri görüntülemenin üç yolu gösterildi. Bu makalede bit eşlemleri yükleme teknikleri incelenir ve yöntemlerinin DrawBitmap kullanımına daha ayrıntılı bir şekilde göz atabilirsiniz SKCanvas.

Örnek Görüntüleniyor

ve yöntemleri, SkiaSharp bit eşlemlerinin kesimli görüntüsü makalesinde ele alınmalıdır.DrawBitmapNinePatch DrawBitmapLattice

Bu sayfadaki örnekler örnek uygulamadan alınıyor. Bu uygulamanın giriş sayfasında SkiaSharp Bit Eşlemleri'ni seçin ve ardından Bit Eşlemleri Görüntüleme bölümüne gidin.

Bit eşlem yükleme

SkiaSharp uygulaması tarafından kullanılan bit eşlem genellikle üç farklı kaynaktan birinden gelir:

  • İnternet üzerinden
  • Yürütülebilir dosyaya eklenmiş bir kaynaktan
  • Kullanıcının fotoğraf kitaplığından

Bir SkiaSharp uygulamasının yeni bir bit eşlem oluşturması ve üzerinde çizim yapmak veya bit eşlem bitlerini algoritmik olarak ayarlaması da mümkündür. Bu teknikler SkiaSharp Bit Eşlemleri Oluşturma ve Çizme ve SkiaSharp Bit Eşlem Piksellerine Erişme makalelerinde ele alınmalıdır.

Bit eşlem yüklemeye ilişkin aşağıdaki üç kod örneğinde sınıfın türünde SKBitmapbir alan içerdiği varsayılır:

SKBitmap bitmap;

SkiaSharp'taki Bit Eşlem Temelleri makalesinde belirtildiği gibi, internet üzerinden bit eşlem yüklemenin en iyi yolu sınıfıdırHttpClient. Sınıfın tek bir örneği alan olarak tanımlanabilir:

HttpClient httpClient = new HttpClient();

iOS ve Android uygulamalarıyla kullanırkenHttpClient, Aktarım Katmanı Güvenliği (TLS) 1.2 belgelerinde açıklandığı gibi proje özelliklerini ayarlamak istersiniz.

Kullanan HttpClient kod genellikle işlecini await içerir, bu nedenle bir async yöntemde bulunması gerekir:

try
{
    using (Stream stream = await httpClient.GetStreamAsync("https:// ··· "))
    using (MemoryStream memStream = new MemoryStream())
    {
        await stream.CopyToAsync(memStream);
        memStream.Seek(0, SeekOrigin.Begin);

        bitmap = SKBitmap.Decode(memStream);
        ···
    };
}
catch
{
    ···
}

öğesinden GetStreamAsync alınan nesnenin Stream içine MemoryStreamkopyalandığına dikkat edin. Android, zaman uyumsuz yöntemler dışında öğesinin HttpClient ana iş parçacığı tarafından işlenmesine izin Stream vermez.

SKBitmap.Decode çok fazla iş yapar: Ona Stream geçirilen nesne, genel olarak JPEG, PNG veya GIF gibi yaygın bit eşlem dosya biçimlerinden birinde bit eşlemin tamamını içeren bir bellek bloğuna başvurur. yönteminin biçimi belirlemesi Decode ve ardından bit eşlem dosyasını SkiaSharp'ın kendi iç bit eşlem biçiminde çözmesi gerekir.

Kodunuz çağrısından SKBitmap.Decodesonra, işleyicinin PaintSurface yeni yüklenen bit eşlemi görüntüleyebilmesi için büyük olasılıkla öğesini geçersiz kılacaktırCanvasView.

Bit eşlem yüklemenin ikinci yolu, bit eşlemi tek tek platform projeleri tarafından başvuruda bulunan .NET Standart kitaplığına ekli kaynak olarak eklemektir. Yöntemine GetManifestResourceStream bir kaynak kimliği geçirilir. Bu kaynak kimliği, noktalarla ayrılmış kaynağın derleme adından, klasör adından ve dosya adından oluşur:

string resourceID = "assemblyName.folderName.fileName";
Assembly assembly = GetType().GetTypeInfo().Assembly;

using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
    bitmap = SKBitmap.Decode(stream);
    ···
}

Bit eşlem dosyaları iOS, Android ve Evrensel Windows Platformu (UWP) için tek tek platform projesinde kaynak olarak da depolanabilir. Ancak, bu bit eşlemleri yüklemek için platform projesinde bulunan kod gerekir.

Bit eşlem elde etmeye yönelik üçüncü bir yaklaşım, kullanıcının resim kitaplığındandır. Aşağıdaki kod, örnek uygulamaya dahil edilen bir bağımlılık hizmetini kullanır. SkiaSharpFormsDemo .NET Standart Kitaplığı arabirimini içerirkenIPhotoLibrary, platform projelerinin her biri bu arabirimi uygulayan bir PhotoLibrary sınıf içerir.

IPhotoicturePicker picturePicker = DependencyService.Get<IPhotoLibrary>();

using (Stream stream = await picturePicker.GetImageStreamAsync())
{
    if (stream != null)
    {
        bitmap = SKBitmap.Decode(stream);
        ···
    }
}

Genellikle, bu tür kod işleyicinin PaintSurface yeni bit eşlemi görüntüleyebilmesi için öğesini de geçersiz kılabilirCanvasView.

SKBitmap sınıfı, bit Heighteşlemlerin piksel boyutlarının yanı sıra bit eşlem oluşturma, bunları kopyalama ve piksel bitlerini kullanıma sunma yöntemleri de dahil olmak üzere birçok yöntemi ortaya çıkaran ve gibi Width çeşitli yararlı özellikleri tanımlar.

Piksel boyutlarında görüntüleme

SkiaSharp Canvas sınıfı dört DrawBitmap yöntem tanımlar. Bu yöntemler bit eşlemlerin temelde iki farklı şekilde görüntülenmesini sağlar:

  • Bir SKPoint değer (veya ayrı x ve y değerler) belirtilmesi bit eşlemi piksel boyutlarında görüntüler. Bit eşlem pikselleri doğrudan video ekranının piksellerine eşlenir.
  • Dikdörtgenin belirtilmesi bit eşlemin dikdörtgenin boyutuna ve şekline genişletilmesine neden olur.

Bir bit eşlemi, bir parametreyle veya DrawBitmap ayrı x ve y parametrelerle SKPoint kullanarak DrawBitmap piksel boyutlarında görüntülersiniz:

DrawBitmap(SKBitmap bitmap, SKPoint pt, SKPaint paint = null)

DrawBitmap(SKBitmap bitmap, float x, float y, SKPaint paint = null)

Bu iki yöntem işlevsel olarak aynıdır. Belirtilen nokta, bit eşleminin tuvale göre sol üst köşesinin konumunu gösterir. Mobil cihazların piksel çözünürlüğü çok yüksek olduğundan, küçük bit eşlemler genellikle bu cihazlarda oldukça küçük görünür.

İsteğe bağlı SKPaint parametresi, saydamlık kullanarak bit eşlemi görüntülemenizi sağlar. Bunu yapmak için bir SKPaint nesne oluşturun ve özelliğini 1'den küçük bir alfa kanalı olan herhangi SKColor bir değere ayarlayınColor. Örneğin:

paint.Color = new SKColor(0, 0, 0, 0x80);

Son bağımsız değişken olarak geçirilen 0x80 %50 saydamlık gösterir. Önceden tanımlanmış renklerden birinde bir alfa kanalı da ayarlayabilirsiniz:

paint.Color = SKColors.Red.WithAlpha(0x80);

Ancak, rengin kendisi ilgisizdir. Nesneyi bir DrawBitmap çağrıda kullandığınızda SKPaint yalnızca alfa kanalı incelenmiş olur.

Nesne, SKPaint karma modlarını veya filtre efektlerini kullanarak bit eşlemleri görüntülerken de rol oynar. Bunlar SkiaSharp compositing and blend modları ve SkiaSharp görüntü filtreleri makalelerinde gösterilmiştir.

Örnek programdaki Pixel Dimensions sayfasında 320 piksel genişliğinde ve 240 piksel yüksekliğinde bir bit eşlem kaynağı görüntülenir:

public class PixelDimensionsPage : ContentPage
{
    SKBitmap bitmap;

    public PixelDimensionsPage()
    {
        Title = "Pixel Dimensions";

        // Load the bitmap from a resource
        string resourceID = "SkiaSharpFormsDemos.Media.Banana.jpg";
        Assembly assembly = GetType().GetTypeInfo().Assembly;

        using (Stream stream = assembly.GetManifestResourceStream(resourceID))
        {
            bitmap = SKBitmap.Decode(stream);
        }

        // Create the SKCanvasView and set the PaintSurface handler
        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();

        float x = (info.Width - bitmap.Width) / 2;
        float y = (info.Height - bitmap.Height) / 2;

        canvas.DrawBitmap(bitmap, x, y);
    }
}

İşleyici, PaintSurface görüntü yüzeyinin piksel boyutlarına ve y bit eşlem piksel boyutlarına göre bit eşlemi hesaplayarak ve değerleri hesaplayarak x bit eşlemi ortalar:

Piksel Boyutları

Uygulama bit eşlemi sol üst köşesinde görüntülemek isterse, yalnızca (0, 0) koordinatlarını geçirir.

Kaynak bit eşlemlerini yüklemek için bir yöntem

Yaklaşan örneklerin çoğunun bit eşlem kaynaklarını yüklemesi gerekir. Örnek çözümdeki statik BitmapExtensions sınıf, aşağıdakilere yardımcı olacak bir yöntem içerir:

static class BitmapExtensions
{
    public static SKBitmap LoadBitmapResource(Type type, string resourceID)
    {
        Assembly assembly = type.GetTypeInfo().Assembly;

        using (Stream stream = assembly.GetManifestResourceStream(resourceID))
        {
            return SKBitmap.Decode(stream);
        }
    }
    ···
}

parametresine Type dikkat edin. Bu, bit eşlem kaynağını depolayan derlemedeki herhangi bir türle ilişkili nesne olabilir Type .

Bu LoadBitmapResource yöntem bit eşlem kaynakları gerektiren sonraki tüm örneklerde kullanılacaktır.

Dikdörtgeni doldurmak için esnetme

SKCanvas sınıfı ayrıca bit eşlemi bir dikdörtgene işleyen bir DrawBitmap yöntem ve bit eşlem dikdörtgen alt kümesini dikdörtgen olarak işleyen başka DrawBitmap bir yöntem tanımlar:

DrawBitmap(SKBitmap bitmap, SKRect dest, SKPaint paint = null)

DrawBitmap(SKBitmap bitmap, SKRect source, SKRect dest, SKPaint paint = null)

Her iki durumda da bit eşlem adlı destdikdörtgeni dolduracak şekilde genişletilir. İkinci yöntemde source dikdörtgen, bit eşlem alt kümesini seçmenize olanak tanır. Dikdörtgen dest çıkış cihazına göre, source dikdörtgen ise bit eşlem ile görelidir.

Dikdörtgeni Doldur sayfası, önceki örnekte kullanılan bit eşlemi tuvalle aynı boyutta bir dikdörtgende görüntüleyerek bu iki yöntemden ilkini gösterir:

public class FillRectanglePage : ContentPage
{
    SKBitmap bitmap =
        BitmapExtensions.LoadBitmapResource(typeof(FillRectanglePage),
                                            "SkiaSharpFormsDemos.Media.Banana.jpg");
    public FillRectanglePage ()
    {
        Title = "Fill Rectangle";

        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();

        canvas.DrawBitmap(bitmap, info.Rect);
    }
}

Alanı ayarlamak için yeni BitmapExtensions.LoadBitmapResource yöntemin kullanıldığına SKBitmap dikkat edin. Hedef dikdörtgen, görüntü yüzeyinin Rect boyutunu kaldıran özelliğinden SKImageInfoelde edilir:

Dikdörtgeni Doldur

Bu genellikle istediğiniz şey değildir . Görüntü, yatay ve dikey yönlerde farklı şekilde esnetilerek bozulır. Bit eşlemi piksel boyutundan farklı bir şekilde görüntülerken genellikle bit eşlemin özgün en boy oranını korumak istersiniz.

En boy oranını korurken esnetme

En boy oranını korurken bit eşlem esnetmek, tekdüzen ölçeklendirme olarak da bilinen bir işlemdir. Bu terim algoritmik bir yaklaşım önerir. Tekdüzen Ölçeklendirme sayfasında olası bir çözüm gösterilir:

public class UniformScalingPage : ContentPage
{
    SKBitmap bitmap =
        BitmapExtensions.LoadBitmapResource(typeof(UniformScalingPage),
                                            "SkiaSharpFormsDemos.Media.Banana.jpg");
    public UniformScalingPage()
    {
        Title = "Uniform Scaling";

        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();

        float scale = Math.Min((float)info.Width / bitmap.Width,
                               (float)info.Height / bitmap.Height);
        float x = (info.Width - scale * bitmap.Width) / 2;
        float y = (info.Height - scale * bitmap.Height) / 2;
        SKRect destRect = new SKRect(x, y, x + scale * bitmap.Width,
                                           y + scale * bitmap.Height);

        canvas.DrawBitmap(bitmap, destRect);
    }
}

İşleyici, PaintSurface görüntüleme genişliğinin ve yüksekliğinin bit eşlem genişliğine ve yüksekliğine oranının en düşük olduğu bir scale faktörü hesaplar. Ve x y değerleri daha sonra ölçeklendirilen bit eşlemi görüntüleme genişliği ve yüksekliği içinde ortalamak için hesaplanabilir. Hedef dikdörtgenin sol üst köşesi x ve y bu değerlerin sağ alt köşesi ile bit eşlemlerin ölçeklendirilmiş genişliği ve yüksekliği vardır:

Tekdüzen Ölçeklendirme

Bit eşleminin bu alana kadar uzatıldığını görmek için telefonu yan çevirin:

Tekdüzen Ölçeklendirme yatayı

Bu scale faktörü kullanmanın avantajı, biraz farklı bir algoritma uygulamak istediğinizde belirginleşir. Bit eşlem en boy oranını korumak ancak hedef dikdörtgeni de doldurmak istediğinizi varsayalım. Bunun mümkün olan tek yolu görüntünün bir bölümünü kırpmaktır, ancak yukarıdaki kodda olarak değiştirerek Math.Min bu algoritmayı Math.Max uygulayabilirsiniz. Sonuç şu şekildedir:

Tekdüzen Ölçeklendirme alternatifi

Bit eşlemin en boy oranı korunur, ancak bit eşlemin sol ve sağındaki alanlar kırpılır.

Çok yönlü bit eşlem görüntüleme işlevi

XAML tabanlı programlama ortamları (UWP ve Xamarin.Formsgibi) bit eşlemlerin boyutunu genişletecek veya küçültürken en boy oranlarını koruyacak bir tesise sahiptir. SkiaSharp bu özelliği içermese de kendiniz uygulayabilirsiniz.

BitmapExtensions Örnek uygulamaya dahil edilen sınıf nasıl yapılacağını gösterir. sınıfı, en boy oranı hesaplaması yapan iki yeni DrawBitmap yöntem tanımlar. Bu yeni yöntemler uzantısı yöntemleridir SKCanvas.

Yeni DrawBitmap yöntemler, BitmapExtensions.cs dosyasında tanımlanan bir numaralandırma türündeki BitmapStretchbir parametreyi içerir:

public enum BitmapStretch
{
    None,
    Fill,
    Uniform,
    UniformToFill,
    AspectFit = Uniform,
    AspectFill = UniformToFill
}

None, Fill, Uniformve UniformToFill üyeleri UWP Stretch sabit listesi ile aynıdır. Benzer Xamarin.FormsAspect numaralandırma, , AspectFitve AspectFillüyelerini Filltanımlar.

Yukarıda gösterilen Tekdüzen Ölçeklendirme sayfası bit eşlemi dikdörtgenin içinde ortalar, ancak bit eşlemi dikdörtgenin sol veya sağ tarafına ya da üstüne veya altına konumlandırma gibi başka seçenekler de isteyebilirsiniz. Numaralandırmanın BitmapAlignment amacı da bu şekildedir:

public enum BitmapAlignment
{
    Start,
    Center,
    End
}

ile BitmapStretch.Fillkullanıldığında hizalama ayarlarının hiçbir etkisi olmaz.

İlk DrawBitmap uzantı işlevi bir hedef dikdörtgen içerir ancak kaynak dikdörtgen içermez. Varsayılanlar tanımlanır, böylece bit eşlem ortalanmasını istiyorsanız yalnızca bir BitmapStretch üye belirtmeniz gerekir:

static class BitmapExtensions
{
    ···
    public static void DrawBitmap(this SKCanvas canvas, SKBitmap bitmap, SKRect dest,
                                  BitmapStretch stretch,
                                  BitmapAlignment horizontal = BitmapAlignment.Center,
                                  BitmapAlignment vertical = BitmapAlignment.Center,
                                  SKPaint paint = null)
    {
        if (stretch == BitmapStretch.Fill)
        {
            canvas.DrawBitmap(bitmap, dest, paint);
        }
        else
        {
            float scale = 1;

            switch (stretch)
            {
                case BitmapStretch.None:
                    break;

                case BitmapStretch.Uniform:
                    scale = Math.Min(dest.Width / bitmap.Width, dest.Height / bitmap.Height);
                    break;

                case BitmapStretch.UniformToFill:
                    scale = Math.Max(dest.Width / bitmap.Width, dest.Height / bitmap.Height);
                    break;
            }

            SKRect display = CalculateDisplayRect(dest, scale * bitmap.Width, scale * bitmap.Height,
                                                  horizontal, vertical);

            canvas.DrawBitmap(bitmap, display, paint);
        }
    }
    ···
}

Bu yöntemin birincil amacı, yöntemini çağırırken bit eşlem genişliğine ve yüksekliğine uygulanan adlı scale bir ölçeklendirme faktörünü CalculateDisplayRect hesaplamaktır. Bu, bit eşlemi yatay ve dikey hizalamaya göre görüntülemek için bir dikdörtgen hesaplayan yöntemdir:

static class BitmapExtensions
{
    ···
    static SKRect CalculateDisplayRect(SKRect dest, float bmpWidth, float bmpHeight,
                                       BitmapAlignment horizontal, BitmapAlignment vertical)
    {
        float x = 0;
        float y = 0;

        switch (horizontal)
        {
            case BitmapAlignment.Center:
                x = (dest.Width - bmpWidth) / 2;
                break;

            case BitmapAlignment.Start:
                break;

            case BitmapAlignment.End:
                x = dest.Width - bmpWidth;
                break;
        }

        switch (vertical)
        {
            case BitmapAlignment.Center:
                y = (dest.Height - bmpHeight) / 2;
                break;

            case BitmapAlignment.Start:
                break;

            case BitmapAlignment.End:
                y = dest.Height - bmpHeight;
                break;
        }

        x += dest.Left;
        y += dest.Top;

        return new SKRect(x, y, x + bmpWidth, y + bmpHeight);
    }
}

sınıfı, BitmapExtensions bit eşlem alt kümesini belirtmek için kaynak dikdörtgen içeren ek DrawBitmap bir yöntem içerir. Bu yöntem, ölçeklendirme faktörünün dikdörtgene göre source hesaplanması ve ardından çağrısındaki dikdörtgene source uygulanması dışında ilk yönteme CalculateDisplayRectbenzer:

static class BitmapExtensions
{
    ···
    public static void DrawBitmap(this SKCanvas canvas, SKBitmap bitmap, SKRect source, SKRect dest,
                                  BitmapStretch stretch,
                                  BitmapAlignment horizontal = BitmapAlignment.Center,
                                  BitmapAlignment vertical = BitmapAlignment.Center,
                                  SKPaint paint = null)
    {
        if (stretch == BitmapStretch.Fill)
        {
            canvas.DrawBitmap(bitmap, source, dest, paint);
        }
        else
        {
            float scale = 1;

            switch (stretch)
            {
                case BitmapStretch.None:
                    break;

                case BitmapStretch.Uniform:
                    scale = Math.Min(dest.Width / source.Width, dest.Height / source.Height);
                    break;

                case BitmapStretch.UniformToFill:
                    scale = Math.Max(dest.Width / source.Width, dest.Height / source.Height);
                    break;
            }

            SKRect display = CalculateDisplayRect(dest, scale * source.Width, scale * source.Height,
                                                  horizontal, vertical);

            canvas.DrawBitmap(bitmap, source, display, paint);
        }
    }
    ···
}

Bu iki yeni DrawBitmap yöntemden ilki Ölçeklendirme Modları sayfasında gösterilmiştir. XAML dosyası, ve BitmapAlignment sabit listelerinin üyelerini seçmenize BitmapStretch olanak sağlayan üç Picker öğe içerir:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SkiaSharpFormsDemos"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Bitmaps.ScalingModesPage"
             Title="Scaling Modes">

    <Grid Padding="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <skia:SKCanvasView x:Name="canvasView"
                           Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <Label Text="Stretch:"
               Grid.Row="1" Grid.Column="0"
               VerticalOptions="Center" />

        <Picker x:Name="stretchPicker"
                Grid.Row="1" Grid.Column="1"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type local:BitmapStretch}">
                    <x:Static Member="local:BitmapStretch.None" />
                    <x:Static Member="local:BitmapStretch.Fill" />
                    <x:Static Member="local:BitmapStretch.Uniform" />
                    <x:Static Member="local:BitmapStretch.UniformToFill" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <Label Text="Horizontal Alignment:"
               Grid.Row="2" Grid.Column="0"
               VerticalOptions="Center" />

        <Picker x:Name="horizontalPicker"
                Grid.Row="2" Grid.Column="1"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type local:BitmapAlignment}">
                    <x:Static Member="local:BitmapAlignment.Start" />
                    <x:Static Member="local:BitmapAlignment.Center" />
                    <x:Static Member="local:BitmapAlignment.End" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>

        <Label Text="Vertical Alignment:"
               Grid.Row="3" Grid.Column="0"
               VerticalOptions="Center" />

        <Picker x:Name="verticalPicker"
                Grid.Row="3" Grid.Column="1"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type local:BitmapAlignment}">
                    <x:Static Member="local:BitmapAlignment.Start" />
                    <x:Static Member="local:BitmapAlignment.Center" />
                    <x:Static Member="local:BitmapAlignment.End" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>
    </Grid>
</ContentPage>

Arka planda kod dosyası herhangi bir Picker öğe değiştiğinde CanvasView öğesini geçersiz kılmıştır. İşleyici, PaintSurface uzantı yöntemini çağırmak için üç Picker görünüme DrawBitmap erişir:

public partial class ScalingModesPage : ContentPage
{
    SKBitmap bitmap =
        BitmapExtensions.LoadBitmapResource(typeof(ScalingModesPage),
                                            "SkiaSharpFormsDemos.Media.Banana.jpg");
    public ScalingModesPage()
    {
        InitializeComponent();
    }

    private void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKRect dest = new SKRect(0, 0, info.Width, info.Height);

        BitmapStretch stretch = (BitmapStretch)stretchPicker.SelectedItem;
        BitmapAlignment horizontal = (BitmapAlignment)horizontalPicker.SelectedItem;
        BitmapAlignment vertical = (BitmapAlignment)verticalPicker.SelectedItem;

        canvas.DrawBitmap(bitmap, dest, stretch, horizontal, vertical);
    }
}

Seçeneklerin bazı bileşimleri şunlardır:

Ölçeklendirme Modları

Dikdörtgen Alt Kümesi sayfası, Ölçeklendirme Modları ile neredeyse aynı XAML dosyasına sahiptir, ancak arka planda kod dosyası, alan tarafından SOURCE verilen bit eşlemin dikdörtgen bir alt kümesini tanımlar:

public partial class ScalingModesPage : ContentPage
{
    SKBitmap bitmap =
        BitmapExtensions.LoadBitmapResource(typeof(ScalingModesPage),
                                            "SkiaSharpFormsDemos.Media.Banana.jpg");

    static readonly SKRect SOURCE = new SKRect(94, 12, 212, 118);

    public RectangleSubsetPage()
    {
        InitializeComponent();
    }

    private void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKRect dest = new SKRect(0, 0, info.Width, info.Height);

        BitmapStretch stretch = (BitmapStretch)stretchPicker.SelectedItem;
        BitmapAlignment horizontal = (BitmapAlignment)horizontalPicker.SelectedItem;
        BitmapAlignment vertical = (BitmapAlignment)verticalPicker.SelectedItem;

        canvas.DrawBitmap(bitmap, SOURCE, dest, stretch, horizontal, vertical);
    }
}

Bu dikdörtgen kaynağı, şu ekran görüntülerinde gösterildiği gibi maymun kafasını yalıtıyor:

Dikdörtgen Alt Kümesi