Anzeigen von SkiaSharp-Bitmaps
Das Thema der SkiaSharp-Bitmaps wurde im Artikel Bitmap Basics in SkiaSharp eingeführt. In diesem Artikel wurden drei Möglichkeiten zum Laden von Bitmaps und drei Möglichkeiten zum Anzeigen von Bitmaps gezeigt. In diesem Artikel werden die Techniken zum Laden von Bitmaps überprüft und die Verwendung der Methoden von DrawBitmap
SKCanvas
.
Die DrawBitmapLattice
Methoden und DrawBitmapNinePatch
Methoden werden im Artikel Segmented display of SkiaSharp bitmaps erläutert.
Beispiele auf dieser Seite stammen aus der Beispielanwendung. Wählen Sie auf der Startseite dieser Anwendung "SkiaSharp Bitmaps" aus, und wechseln Sie dann zum Abschnitt " Bitmaps anzeigen" .
Laden einer Bitmap
Eine von einer SkiaSharp-Anwendung verwendete Bitmap stammt in der Regel aus einer von drei verschiedenen Quellen:
- Von über das Internet
- Aus einer in die ausführbare Datei eingebetteten Ressource
- Aus der Fotobibliothek des Benutzers
Es ist auch möglich, dass eine SkiaSharp-Anwendung eine neue Bitmap erstellen und dann darauf zeichnen oder die Bitmapbits algorithmisch festlegen kann. Diese Techniken werden in den Artikeln Creating and Drawing on SkiaSharp Bitmaps und Accessing SkiaSharp Bitmap Pixels erläutert.
In den folgenden drei Codebeispielen für das Laden einer Bitmap wird davon ausgegangen, dass die Klasse ein Feld vom Typ SKBitmap
enthält:
SKBitmap bitmap;
Wie der Artikel Bitmap Basics in SkiaSharp sagte, ist die beste Möglichkeit, eine Bitmap über das Internet zu laden, mit der HttpClient
Klasse. Eine einzelne Instanz der Klasse kann als Feld definiert werden:
HttpClient httpClient = new HttpClient();
Bei Verwendung HttpClient
mit iOS- und Android-Anwendungen sollten Sie Projekteigenschaften festlegen, wie in den Dokumenten für Transport Layer Security (TLS) 1.2 beschrieben.
Code, der häufig verwendet wird HttpClient
, umfasst den await
Operator, daher muss er sich in einer async
Methode befinden:
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
{
···
}
Beachten Sie, dass das Stream
abgerufene GetStreamAsync
Objekt in ein MemoryStream
. Android lässt nicht zu, dass die Stream
Daten HttpClient
vom Hauptthread verarbeitet werden, außer in asynchronen Methoden.
Das SKBitmap.Decode
hat viel Arbeit: Das Stream
an sie übergebene Objekt verweist auf einen Speicherblock, der eine gesamte Bitmap enthält, in einem der gängigen Bitmapdateiformate, im Allgemeinen JPEG, PNG oder GIF. Die Decode
Methode muss das Format bestimmen und dann die Bitmapdatei in das eigene interne Bitmapformat von SkiaSharp decodieren.
Nach dem Aufrufen SKBitmap.Decode
des Codes wird dies CanvasView
wahrscheinlich ungültig, sodass der PaintSurface
Handler die neu geladene Bitmap anzeigen kann.
Die zweite Möglichkeit zum Laden einer Bitmap besteht darin, dass die Bitmap als eingebettete Ressource in die .NET Standard-Bibliothek eingeschlossen wird, auf die von den einzelnen Plattformprojekten verwiesen wird. An die Methode wird eine GetManifestResourceStream
Ressourcen-ID übergeben. Diese Ressourcen-ID besteht aus dem Assemblynamen, dem Ordnernamen und dem Dateinamen der Ressource, die durch Punkte getrennt ist:
string resourceID = "assemblyName.folderName.fileName";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
bitmap = SKBitmap.Decode(stream);
···
}
Bitmapdateien können auch als Ressourcen im einzelnen Plattformprojekt für iOS, Android und die Universelle Windows-Plattform (UWP) gespeichert werden. Das Laden dieser Bitmaps erfordert jedoch Code, der sich im Plattformprojekt befindet.
Ein dritter Ansatz zum Abrufen einer Bitmap stammt aus der Bildbibliothek des Benutzers. Der folgende Code verwendet einen Abhängigkeitsdienst, der in der Beispielanwendung enthalten ist. Die SkiaSharpFormsDemo .NET Standard Library enthält die IPhotoLibrary
Schnittstelle, während jedes Plattformprojekt eine PhotoLibrary
Klasse enthält, die diese Schnittstelle implementiert.
IPhotoicturePicker picturePicker = DependencyService.Get<IPhotoLibrary>();
using (Stream stream = await picturePicker.GetImageStreamAsync())
{
if (stream != null)
{
bitmap = SKBitmap.Decode(stream);
···
}
}
Im Allgemeinen wird durch diesen Code auch die CanvasView
Prozedur ungültig, sodass der PaintSurface
Handler die neue Bitmap anzeigen kann.
Die SKBitmap
Klasse definiert mehrere nützliche Eigenschaften, einschließlich Width
und Height
, die die Pixelabmessungen der Bitmap sowie viele Methoden anzeigen, einschließlich Methoden zum Erstellen von Bitmaps, zum Kopieren und Verfügbarmachen der Pixelbits.
Anzeigen in Pixelabmessungen
Die SkiaSharp-Klasse Canvas
definiert vier DrawBitmap
Methoden. Mit diesen Methoden können Bitmaps grundsätzlich auf unterschiedliche Weise angezeigt werden:
- Wenn Sie einen
SKPoint
Wert (oder separatex
Wertey
) angeben, wird die Bitmap in ihren Pixelabmessungen angezeigt. Die Pixel der Bitmap werden direkt den Pixeln der Videoanzeige zugeordnet. - Wenn Sie ein Rechteck angeben, wird die Bitmap auf die Größe und Form des Rechtecks gestreckt.
Sie zeigen eine Bitmap in ihren Pixelabmessungen mit DrawBitmap
einem SKPoint
Parameter oder DrawBitmap
mit separaten x
Parametern an y
:
DrawBitmap(SKBitmap bitmap, SKPoint pt, SKPaint paint = null)
DrawBitmap(SKBitmap bitmap, float x, float y, SKPaint paint = null)
Diese beiden Methoden sind funktional identisch. Der angegebene Punkt gibt die Position der oberen linken Ecke der Bitmap relativ zum Zeichenbereich an. Da die Pixelauflösung mobiler Geräte so hoch ist, erscheinen kleinere Bitmaps in der Regel ziemlich klein auf diesen Geräten.
Mit dem optionalen SKPaint
Parameter können Sie die Bitmap mithilfe von Transparenz anzeigen. Erstellen Sie dazu ein SKPaint
Objekt, und legen Sie die Color
Eigenschaft auf einen beliebigen SKColor
Wert mit einem Alphakanal unter 1 fest. Zum Beispiel:
paint.Color = new SKColor(0, 0, 0, 0x80);
Die als letztes Argument übergebene 0x80 gibt 50 % Transparenz an. Sie können auch einen Alphakanal für eine der vordefinierten Farben festlegen:
paint.Color = SKColors.Red.WithAlpha(0x80);
Die Farbe selbst ist jedoch irrelevant. Nur der Alphakanal wird untersucht, wenn Sie das SKPaint
Objekt in einem DrawBitmap
Aufruf verwenden.
Das SKPaint
Objekt spielt auch eine Rolle beim Anzeigen von Bitmaps mithilfe von Blendmodi oder Filtereffekten. Diese werden in den Artikeln SkiaSharp Compositing und Blendmodi und SkiaSharp Bildfilter gezeigt.
Die Seite "Pixelabmessungen " im Beispielprogramm zeigt eine Bitmapressource mit einer Breite von 320 Pixeln um 240 Pixel hoch an:
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);
}
}
Der PaintSurface
Handler zentriert die Bitmap durch Berechnung x
und y
Werte basierend auf den Pixelabmessungen der Anzeigeoberfläche und den Pixelabmessungen der Bitmap:
Wenn die Anwendung die Bitmap in der oberen linken Ecke anzeigen möchte, würde sie einfach Koordinaten von (0, 0) übergeben.
Eine Methode zum Laden von Ressourcenbitmaps
Viele der verfügbaren Beispiele müssen Bitmapressourcen laden. Die statische BitmapExtensions
Klasse in der Beispiellösung enthält eine Methode, die Ihnen helfen soll:
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);
}
}
···
}
Beachten Sie den Type
Parameter. Dies kann das Objekt sein, das Type
einem beliebigen Typ in der Assembly zugeordnet ist, in dem die Bitmapressource gespeichert wird.
Diese LoadBitmapResource
Methode wird in allen nachfolgenden Beispielen verwendet, die Bitmapressourcen erfordern.
Strecken zum Ausfüllen eines Rechtecks
Die SKCanvas
Klasse definiert auch eine DrawBitmap
Methode, die die Bitmap in einem Rechteck rendert, und eine andere DrawBitmap
Methode, die eine rechteckige Teilmenge der Bitmap in einem Rechteck rendert:
DrawBitmap(SKBitmap bitmap, SKRect dest, SKPaint paint = null)
DrawBitmap(SKBitmap bitmap, SKRect source, SKRect dest, SKPaint paint = null)
In beiden Fällen wird die Bitmap gestreckt, um das Rechteck mit dem Namen zu dest
füllen. In der zweiten Methode können Sie mit dem source
Rechteck eine Teilmenge der Bitmap auswählen. Das dest
Rechteck ist relativ zum Ausgabegerät; das source
Rechteck ist relativ zur Bitmap.
Auf der Seite "Rechteck ausfüllen" wird die erste dieser beiden Methoden veranschaulicht, indem dieselbe Bitmap angezeigt wird, die im vorherigen Beispiel in einem Rechteck dieselbe Größe wie der Zeichenbereich verwendet wird:
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);
}
}
Beachten Sie die Verwendung der neuen BitmapExtensions.LoadBitmapResource
Methode zum Festlegen des SKBitmap
Felds. Das Zielrechteck wird aus der Rect
Eigenschaft von SKImageInfo
abgerufen, die die Größe der Anzeigeoberfläche desribes:
Dies ist in der Regel nicht das, was Sie wollen. Das Bild wird verzerrt, indem es in horizontaler und vertikaler Richtung unterschiedlich gestreckt wird. Beim Anzeigen einer Bitmap in einer anderen Größe als der Pixelgröße möchten Sie in der Regel das ursprüngliche Seitenverhältnis der Bitmap beibehalten.
Strecken beim Beibehalten des Seitenverhältnisses
Das Strecken einer Bitmap beim Beibehalten des Seitenverhältnisses ist ein Prozess, der auch als einheitliche Skalierung bezeichnet wird. Dieser Begriff schlägt einen algorithmischen Ansatz vor. Eine mögliche Lösung wird auf der Seite "Uniform Scaling " angezeigt:
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);
}
}
Der PaintSurface
Handler berechnet einen scale
Faktor, der das Minimum des Verhältnisses der Anzeigebreite und -höhe zur Bitmapbreite und -höhe darstellt. Die x
Werte y
können dann für die Zentrierung der skalierten Bitmap innerhalb der Anzeigebreite und -höhe berechnet werden. Das Zielrechteck weist eine obere linke Ecke und x
y
eine untere rechte Ecke dieser Werte sowie die skalierte Breite und Höhe der Bitmap auf:
Drehen Sie das Telefon seitwärts, um die Bitmap zu diesem Bereich gestreckt anzuzeigen:
Der Vorteil der Verwendung dieses scale
Faktors wird offensichtlich, wenn Sie einen etwas anderen Algorithmus implementieren möchten. Angenommen, Sie möchten das Seitenverhältnis der Bitmap beibehalten, aber auch das Zielrechteck ausfüllen. Die einzige Möglichkeit besteht darin, einen Teil des Bilds zuzuschneiden, aber Sie können diesen Algorithmus einfach implementieren, indem Sie im obigen Code zu Math.Max
wechselnMath.Min
. Das Ergebnis lautet wie folgt:
Das Seitenverhältnis der Bitmap wird beibehalten, bereiche auf der linken und rechten Seite der Bitmap werden jedoch zugeschnitten.
Eine vielseitige Bitmapanzeigefunktion
XAML-basierte Programmierumgebungen (z. B. UWP und Xamarin.Forms) verfügen über eine Möglichkeit, die Größe von Bitmaps zu erweitern oder zu verkleinern und gleichzeitig ihre Seitenverhältnisse beizubehalten. Obwohl SkiaSharp dieses Feature nicht enthält, können Sie es selbst implementieren.
Die BitmapExtensions
in der Beispielanwendung enthaltene Klasse zeigt, wie das geht. Die Klasse definiert zwei neue DrawBitmap
Methoden, mit denen die Seitenverhältnisberechnung durchgeführt wird. Diese neuen Methoden sind Erweiterungsmethoden von SKCanvas
.
Die neuen DrawBitmap
Methoden enthalten einen Parameter vom Typ BitmapStretch
, eine in der BitmapExtensions.cs Datei definierte Aufzählung:
public enum BitmapStretch
{
None,
Fill,
Uniform,
UniformToFill,
AspectFit = Uniform,
AspectFill = UniformToFill
}
Die None
Elemente , Fill
, , Uniform
und UniformToFill
Member sind identisch mit denen in der UWP-Aufzählung Stretch
. Die ähnliche Xamarin.FormsAspect
Aufzählung definiert Member Fill
, AspectFit
und AspectFill
.
Die oben gezeigte Seite für die einheitliche Skalierung zentriert die Bitmap innerhalb des Rechtecks, sie kann jedoch auch andere Optionen haben, z. B. das Positionieren der Bitmap auf der linken oder rechten Seite des Rechtecks oder oben oder unten. Dies ist der Zweck der BitmapAlignment
Enumeration:
public enum BitmapAlignment
{
Start,
Center,
End
}
Ausrichtungseinstellungen haben keine Auswirkung, wenn sie mit BitmapStretch.Fill
.
Die erste DrawBitmap
Erweiterungsfunktion enthält ein Zielrechteck, aber kein Quellrechteck. Standardwerte sind definiert, sodass Sie nur ein BitmapStretch
Element angeben müssen, wenn die Bitmap zentriert werden soll:
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);
}
}
···
}
Der Hauptzweck dieser Methode besteht darin, einen Skalierungsfaktor scale
zu berechnen, der dann beim Aufrufen der CalculateDisplayRect
Methode auf die Bitmapbreite und -höhe angewendet wird. Dies ist die Methode, die ein Rechteck für die Anzeige der Bitmap basierend auf der horizontalen und vertikalen Ausrichtung berechnet:
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);
}
}
Die BitmapExtensions
Klasse enthält eine zusätzliche DrawBitmap
Methode mit einem Quellrechteck zum Angeben einer Teilmenge der Bitmap. Diese Methode ähnelt dem ersten, mit der Ausnahme, dass der Skalierungsfaktor basierend auf dem source
Rechteck berechnet wird und dann im Aufruf auf das source
Rechteck angewendet wird: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);
}
}
···
}
Die erste dieser beiden neuen DrawBitmap
Methoden wird auf der Seite "Skalierungsmodi" veranschaulicht. Die XAML-Datei enthält drei Picker
Elemente, mit denen Sie Elemente und BitmapStretch
BitmapAlignment
Enumerationen auswählen können:
<?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>
Die CodeBehind-Datei macht einfach ungültig CanvasView
, wenn ein Picker
Element geändert wurde. Der PaintSurface
Handler greift auf die drei Picker
Ansichten zum Aufrufen der DrawBitmap
Erweiterungsmethode zu:
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);
}
}
Hier sind einige Kombinationen von Optionen:
Die Seite " Rechteck-Teilmenge " hat praktisch dieselbe XAML-Datei wie skalierungsmodi, aber die CodeBehind-Datei definiert eine rechteckige Teilmenge der Bitmap, die vom SOURCE
Feld angegeben wird:
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);
}
}
Diese Rechteckquelle isoliert den Kopf des Affen, wie in den folgenden Screenshots gezeigt: