Wyświetlanie map bitowych SkiaSharp
Temat map bitowych SkiaSharp został wprowadzony w artykule Podstawy mapy bitowej w SkiaSharp. W tym artykule przedstawiono trzy sposoby ładowania map bitowych i trzy sposoby wyświetlania map bitowych. W tym artykule przedstawiono techniki ładowania map bitowych i bardziej szczegółowe informacje na temat DrawBitmap
używania metod programu SKCanvas
.
Metody DrawBitmapLattice
i DrawBitmapNinePatch
zostały omówione w artykule Segmented display of SkiaSharp bitmaps (Segmented display of SkiaSharp map bitowych).
Przykłady na tej stronie pochodzą z przykładowej aplikacji. Na stronie głównej tej aplikacji wybierz pozycję Mapy bitowe SkiaSharp, a następnie przejdź do sekcji Wyświetlanie map bitowych.
Ładowanie mapy bitowej
Mapa bitowa używana przez aplikację SkiaSharp zazwyczaj pochodzi z jednego z trzech różnych źródeł:
- Z Internetu
- Z zasobu osadzonego w pliku wykonywalnym
- Z biblioteki zdjęć użytkownika
Istnieje również możliwość utworzenia nowej mapy bitowej przez aplikację SkiaSharp, a następnie narysować ją lub ustawić bity mapy bitowej algorytmicznie. Te techniki zostały omówione w artykułach Tworzenie i rysowanie na mapach bitowych SkiaSharp oraz Uzyskiwanie dostępu do pikseli mapy bitowej SkiaSharp.
W poniższych trzech przykładach kodu ładowania mapy bitowej przyjmuje się, że klasa zawiera pole typu SKBitmap
:
SKBitmap bitmap;
Jak stwierdził artykuł Bitmap Basics in SkiaSharp , najlepszym sposobem ładowania mapy bitowej przez Internet jest HttpClient
klasa . Pojedyncze wystąpienie klasy można zdefiniować jako pole:
HttpClient httpClient = new HttpClient();
W przypadku korzystania HttpClient
z aplikacji systemu iOS i Android należy ustawić właściwości projektu zgodnie z opisem w dokumentach protokołu Transport Layer Security (TLS) 1.2.
Kod, który używa HttpClient
operatora często obejmuje await
operator, więc musi znajdować się w metodzie async
:
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
{
···
}
Zwróć uwagę, że Stream
obiekt uzyskany z GetStreamAsync
obiektu jest kopiowany do obiektu MemoryStream
. System Android nie zezwala na Stream
przetwarzanie elementu z HttpClient
przez główny wątek z wyjątkiem metod asynchronicznych.
Wykonuje SKBitmap.Decode
wiele pracy: Stream
Obiekt przekazany do niego odwołuje się do bloku pamięci zawierającej całą mapę bitową w jednym z typowych formatów plików bitowych, na ogół JPEG, PNG lub GIF. Metoda Decode
musi określić format, a następnie zdekodować plik mapy bitowej do wewnętrznego formatu mapy bitowej SkiaSharp.
Po wywołaniu SKBitmap.Decode
kodu prawdopodobnie unieważni CanvasView
element tak, aby PaintSurface
program obsługi mógł wyświetlić nowo załadowaną mapę bitową.
Drugim sposobem ładowania mapy bitowej jest dołączenie mapy bitowej jako zasobu osadzonego w bibliotece .NET Standard, do których odwołuje się poszczególne projekty platformy. Identyfikator zasobu jest przekazywany do GetManifestResourceStream
metody . Ten identyfikator zasobu składa się z nazwy zestawu, nazwy folderu i nazwy pliku zasobu oddzielonego kropkami:
string resourceID = "assemblyName.folderName.fileName";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
bitmap = SKBitmap.Decode(stream);
···
}
Pliki mapy bitowej mogą być również przechowywane jako zasoby w indywidualnym projekcie platformy dla systemów iOS, Android i platforma uniwersalna systemu Windows (UWP). Jednak ładowanie tych map bitowych wymaga kodu znajdującego się w projekcie platformy.
Trzecim podejściem do uzyskania mapy bitowej jest biblioteka obrazów użytkownika. Poniższy kod używa usługi zależności uwzględnionej w przykładowej aplikacji. Biblioteka SkiaSharpFormsDemo .NET Standard Library zawiera IPhotoLibrary
interfejs, podczas gdy każdy z projektów platformy zawiera klasę PhotoLibrary
, która implementuje ten interfejs.
IPhotoicturePicker picturePicker = DependencyService.Get<IPhotoLibrary>();
using (Stream stream = await picturePicker.GetImageStreamAsync())
{
if (stream != null)
{
bitmap = SKBitmap.Decode(stream);
···
}
}
Ogólnie rzecz biorąc, taki kod unieważnia CanvasView
również element tak, aby PaintSurface
program obsługi mógł wyświetlić nową mapę bitową.
Klasa SKBitmap
definiuje kilka przydatnych właściwości, w tym Width
i Height
, które ujawniają wymiary pikseli mapy bitowej, a także wiele metod, w tym metod tworzenia map bitów bitowych, kopiowania ich i uwidocznienia bitów pikseli.
Wyświetlanie w wymiarach pikseli
Klasa SkiaSharp Canvas
definiuje cztery DrawBitmap
metody. Te metody umożliwiają wyświetlanie map bitowych na dwa zasadniczo różne sposoby:
- Określenie
SKPoint
wartości (lub oddzielnychx
iy
wartości) powoduje wyświetlenie mapy bitowej w wymiarach pikseli. Piksele mapy bitowej są mapowane bezpośrednio na piksele ekranu wideo. - Określenie prostokąta powoduje rozciągnięcie mapy bitowej na rozmiar i kształt prostokąta.
Mapa bitowa jest wyświetlana w wymiarach pikseli przy użyciu DrawBitmap
parametru SKPoint
lub DrawBitmap
z oddzielnymi x
parametrami i y
:
DrawBitmap(SKBitmap bitmap, SKPoint pt, SKPaint paint = null)
DrawBitmap(SKBitmap bitmap, float x, float y, SKPaint paint = null)
Te dwie metody są funkcjonalnie identyczne. Określony punkt wskazuje lokalizację lewego górnego rogu mapy bitowej względem kanwy. Ponieważ rozdzielczość pikseli urządzeń przenośnych jest tak wysoka, mniejsze mapy bitowe zwykle wydają się dość małe na tych urządzeniach.
Opcjonalny SKPaint
parametr umożliwia wyświetlanie mapy bitowej przy użyciu przezroczystości. W tym celu utwórz SKPaint
obiekt i ustaw Color
właściwość na dowolną SKColor
wartość z kanałem alfa mniejszym niż 1. Na przykład:
paint.Color = new SKColor(0, 0, 0, 0x80);
0x80 przekazana jako ostatni argument wskazuje 50% przezroczystości. Kanał alfa można również ustawić na jednym ze wstępnie zdefiniowanych kolorów:
paint.Color = SKColors.Red.WithAlpha(0x80);
Jednak sam kolor jest nieistotny. Podczas używania SKPaint
obiektu w wywołaniu DrawBitmap
sprawdzany jest tylko kanał alfa.
Obiekt SKPaint
odgrywa również rolę podczas wyświetlania map bitowych przy użyciu trybów mieszania lub efektów filtrowania. Przedstawiono je w artykułach SkiaSharp kompositing i blend tryby oraz filtry obrazów SkiaSharp.
Strona Wymiary pikseli w przykładowym programie wyświetla zasób mapy bitowej o szerokości 320 pikseli o wysokości 240 pikseli:
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);
}
}
Procedura PaintSurface
obsługi wyśrodkuje mapę bitową, obliczając x
i y
wartości na podstawie wymiarów pikseli powierzchni wyświetlania i wymiarów pikseli mapy bitowej:
Jeśli aplikacja chce wyświetlić mapę bitową w lewym górnym rogu, po prostu przekaże współrzędne (0, 0).
Metoda ładowania map bitowych zasobów
Wiele z nadchodzących próbek będzie musiało załadować zasoby mapy bitowej. Klasa statyczna BitmapExtensions
w przykładowym rozwiązaniu zawiera metodę pomagającą:
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);
}
}
···
}
Zwróć uwagę na Type
parametr . Może to być Type
obiekt skojarzony z dowolnym typem w zestawie, który przechowuje zasób mapy bitowej.
Ta LoadBitmapResource
metoda będzie używana we wszystkich kolejnych próbkach, które wymagają zasobów mapy bitowej.
Rozciąganie w celu wypełnienia prostokąta
Klasa SKCanvas
definiuje również metodę DrawBitmap
, która renderuje mapę bitową do prostokąta, oraz inną DrawBitmap
metodę, która renderuje prostokątny podzbiór mapy bitowej do prostokąta:
DrawBitmap(SKBitmap bitmap, SKRect dest, SKPaint paint = null)
DrawBitmap(SKBitmap bitmap, SKRect source, SKRect dest, SKPaint paint = null)
W obu przypadkach mapa bitowa jest rozciągana w celu wypełnienia prostokąta o nazwie dest
. W drugiej metodzie source
prostokąt umożliwia wybranie podzbioru mapy bitowej. Prostokąt dest
jest względny względem urządzenia wyjściowego; source
prostokąt jest względny względem mapy bitowej.
Strona Wypełnienie prostokąta przedstawia pierwszą z tych dwóch metod, wyświetlając tę samą mapę bitową używaną we wcześniejszym przykładzie w prostokątze o takim samym rozmiarze jak kanwa:
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);
}
}
Zwróć uwagę na użycie nowej BitmapExtensions.LoadBitmapResource
metody do ustawienia SKBitmap
pola. Prostokąt docelowy jest uzyskiwany z Rect
właściwości SKImageInfo
, która rozdziela rozmiar powierzchni wyświetlania:
Zwykle nie jest to to, co chcesz. Obraz jest zniekształcony przez rozciągnięcie w różnych kierunkach poziomych i pionowych. Podczas wyświetlania mapy bitowej w innym rozmiarze niż rozmiar piksela zwykle chcesz zachować oryginalny współczynnik proporcji mapy bitowej.
Rozciąganie przy zachowaniu współczynnika proporcji
Rozciąganie mapy bitowej przy zachowaniu współczynnika proporcji jest procesem znanym również jako jednolite skalowanie. Ten termin sugeruje podejście algorytmiczne. Jedno z możliwych rozwiązań jest wyświetlane na stronie Ujednolicone skalowanie :
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);
}
}
Procedura PaintSurface
obsługi oblicza scale
współczynnik, który jest minimalnym współczynnikiem szerokości i wysokości ekranu do szerokości i wysokości mapy bitowej. Wartości x
i y
można następnie obliczyć na potrzeby wyśrodkowania skalowanych map bitowych w obrębie szerokości i wysokości ekranu. Prostokąt docelowy ma lewy górny róg x
i y
prawy dolny róg tych wartości oraz skalowaną szerokość i wysokość mapy bitowej:
Przesuń telefon w bok, aby zobaczyć mapę bitową rozciągniętą do tego obszaru:
Zaleta korzystania z tego scale
czynnika staje się oczywista, gdy chcesz zaimplementować nieco inny algorytm. Załóżmy, że chcesz zachować współczynnik proporcji mapy bitowej, ale także wypełnić prostokąt docelowy. Jedynym sposobem, w jaki jest to możliwe, jest przycinanie części obrazu, ale można zaimplementować ten algorytm po prostu zmieniając Math.Min
wartość na Math.Max
w powyższym kodzie. Oto wynik:
Współczynnik proporcji mapy bitowej jest zachowywany, ale obszary po lewej i prawej stronie mapy bitowej są przycinane.
Wszechstronna funkcja wyświetlania map bitowych
Środowiska programowania oparte na języku XAML (takie jak platforma UWP i Xamarin.Forms) mają obiekt umożliwiający rozszerzanie lub zmniejszanie rozmiaru map bitowych przy zachowaniu współczynników proporcji. Mimo że skiaSharp nie obejmuje tej funkcji, możesz zaimplementować ją samodzielnie.
Klasa BitmapExtensions
uwzględniona w przykładowej aplikacji pokazuje, jak to zrobić. Klasa definiuje dwie nowe DrawBitmap
metody, które wykonują obliczenia współczynnika proporcji. Te nowe metody to metody SKCanvas
rozszerzenia klasy .
Nowe DrawBitmap
metody obejmują parametr typu BitmapStretch
, wyliczenie zdefiniowane w pliku BitmapExtensions.cs :
public enum BitmapStretch
{
None,
Fill,
Uniform,
UniformToFill,
AspectFit = Uniform,
AspectFill = UniformToFill
}
Elementy None
członkowskie , Fill
, Uniform
i UniformToFill
są takie same jak w wyliczenie platformy UWP Stretch
. Xamarin.FormsAspect
Podobne wyliczenie definiuje elementy członkowskie Fill
, AspectFit
i AspectFill
.
Strona Jednolite skalowanie pokazana powyżej wyśrodkuje mapę bitową w obrębie prostokąta, ale możesz chcieć wybrać inne opcje, takie jak pozycjonowanie mapy bitowej po lewej lub prawej stronie prostokąta albo u góry lub dołu. Jest to cel BitmapAlignment
wyliczenia:
public enum BitmapAlignment
{
Start,
Center,
End
}
Ustawienia wyrównania nie mają żadnego wpływu w przypadku użycia z BitmapStretch.Fill
programem .
Pierwsza DrawBitmap
funkcja rozszerzenia zawiera prostokąt docelowy, ale bez prostokąta źródłowego. Wartości domyślne są definiowane tak, aby jeśli chcesz wyśrodkować mapę bitową, musisz określić tylko element członkowski BitmapStretch
:
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);
}
}
···
}
Podstawowym celem tej metody jest obliczenie współczynnika skalowania o nazwie scale
, który jest następnie stosowany do szerokości i wysokości mapy bitowej podczas wywoływania CalculateDisplayRect
metody. Jest to metoda, która oblicza prostokąt do wyświetlania mapy bitowej na podstawie wyrównania poziomego i pionowego:
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);
}
}
Klasa BitmapExtensions
zawiera dodatkową DrawBitmap
metodę z prostokątem źródłowym określającym podzbiór mapy bitowej. Ta metoda jest podobna do pierwszej z tą różnicą, że współczynnik skalowania jest obliczany na source
podstawie prostokąta, a następnie zastosowany do prostokąta source
w wywołaniu metody :CalculateDisplayRect
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);
}
}
···
}
Pierwsza z tych dwóch nowych DrawBitmap
metod jest pokazana na stronie Tryby skalowania. Plik XAML zawiera trzy Picker
elementy, które pozwalają wybrać elementy członkowskie i BitmapStretch
BitmapAlignment
wyliczenia:
<?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>
Plik związany z kodem po prostu unieważnia CanvasView
element, gdy dowolny Picker
element uległ zmianie. Procedura PaintSurface
obsługi uzyskuje dostęp do trzech Picker
widoków w celu wywołania DrawBitmap
metody rozszerzenia:
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);
}
}
Oto kilka kombinacji opcji:
Strona Podzestaw prostokąta ma praktycznie ten sam plik XAML co tryby skalowania, ale plik za kodem definiuje prostokątny podzbiór mapy bitowej podanej SOURCE
przez pole:
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);
}
}
To źródło prostokąta izoluje głowę małpy, jak pokazano na poniższych zrzutach ekranu: