Bitmapgrundlagen in SkiaSharp
Laden Sie Bitmaps aus verschiedenen Quellen, und zeigen Sie sie an.
Die Unterstützung von Bitmaps in SkiaSharp ist ziemlich umfangreich. In diesem Artikel werden nur die Grundlagen behandelt– wie Bitmaps geladen werden und wie sie angezeigt werden:
Eine viel tiefere Erkundung von Bitmaps finden Sie im Abschnitt SkiaSharp Bitmaps.
Eine SkiaSharp-Bitmap ist ein Objekt vom Typ SKBitmap
. Es gibt viele Möglichkeiten zum Erstellen einer Bitmap, aber dieser Artikel beschränkt sich auf die SKBitmap.Decode
Methode, die die Bitmap aus einem .NET-Objekt Stream
lädt.
Die Seite "Grundlegende Bitmaps " im Programm "SkiaSharpFormsDemos " veranschaulicht, wie Bitmaps aus drei verschiedenen Quellen geladen werden:
- Von über das Internet
- Aus einer in die ausführbare Datei eingebetteten Ressource
- Aus der Fotobibliothek des Benutzers
Drei SKBitmap
Objekte für diese drei Quellen werden als Felder in der BasicBitmapsPage
Klasse definiert:
public class BasicBitmapsPage : ContentPage
{
SKCanvasView canvasView;
SKBitmap webBitmap;
SKBitmap resourceBitmap;
SKBitmap libraryBitmap;
public BasicBitmapsPage()
{
Title = "Basic Bitmaps";
canvasView = new SKCanvasView();
canvasView.PaintSurface += OnCanvasViewPaintSurface;
Content = canvasView;
...
}
...
}
Laden einer Bitmap aus dem Web
Um eine Bitmap basierend auf einer URL zu laden, können Sie die HttpClient
Klasse verwenden. Sie sollten nur eine Instanz instanziieren HttpClient
und wiederverwenden, damit sie als Feld gespeichert wird:
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.
Da die Verwendung des Operators mit dem await
Operator HttpClient
am bequemsten ist, kann der Code nicht im BasicBitmapsPage
Konstruktor ausgeführt werden. Stattdessen ist er Teil der OnAppearing
Außerkraftsetzung. Die URL verweist hier auf einen Bereich auf der Xamarin-Website mit einigen Beispielbitmaps. Ein Paket auf der Website ermöglicht das Anfügen einer Spezifikation zum Ändern der Größe der Bitmap an eine bestimmte Breite:
protected override async void OnAppearing()
{
base.OnAppearing();
// Load web bitmap.
string url = "https://developer.xamarin.com/demo/IMG_3256.JPG?width=480";
try
{
using (Stream stream = await httpClient.GetStreamAsync(url))
using (MemoryStream memStream = new MemoryStream())
{
await stream.CopyToAsync(memStream);
memStream.Seek(0, SeekOrigin.Begin);
webBitmap = SKBitmap.Decode(memStream);
canvasView.InvalidateSurface();
};
}
catch
{
}
}
Das Android-Betriebssystem löst eine Ausnahme aus, wenn sie die in GetStreamAsync
der Stream
SKBitmap.Decode
Methode zurückgegebene Verwendung verwendet, da sie einen langwierigen Vorgang in einem Standard Thread ausführt. Aus diesem Grund werden die Inhalte der Bitmapdatei mit CopyToAsync
einem MemoryStream
Objekt kopiert.
Die statische SKBitmap.Decode
Methode ist für die Decodierung von Bitmapdateien verantwortlich. Es funktioniert mit JPEG-, PNG- und GIF-Bitmapformaten und speichert die Ergebnisse in einem internen SkiaSharp-Format. An diesem Punkt muss der SKCanvasView
Handler ungültig sein, damit der PaintSurface
Handler die Anzeige aktualisieren kann.
Laden einer Bitmapressource
Im Hinblick auf Code ist der einfachste Ansatz zum Laden von Bitmaps eine Bitmapressource direkt in Ihrer Anwendung enthalten. Das SkiaSharpFormsDemos-Programm enthält einen Ordner namens "Medien" , der mehrere Bitmapdateien enthält, einschließlich eines namens monkey.png. Für Bitmaps, die als Programmressourcen gespeichert sind, müssen Sie das Dialogfeld "Eigenschaften " verwenden, um der Datei eine Buildaktion der eingebetteten Ressource zuzuweisen!
Jede eingebettete Ressource verfügt über eine Ressourcen-ID , die aus dem Projektnamen, dem Ordner und dem Dateinamen besteht, die alle nach Zeiträumen verbunden sind: SkiaSharpFormsDemos.Media.monkey.png. Sie können zugriff auf diese Ressource erhalten, indem Sie diese Ressourcen-ID als Argument für die GetManifestResourceStream
Methode der Assembly
Klasse angeben:
string resourceID = "SkiaSharpFormsDemos.Media.monkey.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
resourceBitmap = SKBitmap.Decode(stream);
}
Dieses Stream
Objekt kann direkt an die SKBitmap.Decode
Methode übergeben werden.
Laden einer Bitmap aus der Fotobibliothek
Es ist auch möglich, dass der Benutzer ein Foto aus der Bildbibliothek des Geräts lädt. Diese Einrichtung wird nicht selbst Xamarin.Forms bereitgestellt. Der Auftrag erfordert einen Abhängigkeitsdienst, z. B. den im Artikel "Auswählen eines Fotos aus der Bildbibliothek" beschriebenen Dienst.
Die IPhotoLibrary.cs Datei im Projekt SkiaSharpFormsDemos und die drei PhotoLibrary.cs Dateien in den Plattformprojekten wurden aus diesem Artikel angepasst. Darüber hinaus wurde die Android-MainActivity.cs-Datei wie im Artikel beschrieben geändert, und dem iOS-Projekt wurde die Berechtigung erteilt, auf die Fotobibliothek mit zwei Zeilen am Ende der Info.plist-Datei zuzugreifen.
Der BasicBitmapsPage
Konstruktor fügt dem SKCanvasView
Tipper eine TapGestureRecognizer
Benachrichtigung hinzu. Beim Empfang eines Tippens erhält der Tapped
Handler Zugriff auf den Abhängigkeitsdienst für die Bildauswahl und Aufrufe PickPhotoAsync
. Wenn ein Stream
Objekt zurückgegeben wird, wird es an die SKBitmap.Decode
Methode übergeben:
// Add tap gesture recognizer
TapGestureRecognizer tapRecognizer = new TapGestureRecognizer();
tapRecognizer.Tapped += async (sender, args) =>
{
// Load bitmap from photo library
IPhotoLibrary photoLibrary = DependencyService.Get<IPhotoLibrary>();
using (Stream stream = await photoLibrary.PickPhotoAsync())
{
if (stream != null)
{
libraryBitmap = SKBitmap.Decode(stream);
canvasView.InvalidateSurface();
}
}
};
canvasView.GestureRecognizers.Add(tapRecognizer);
Beachten Sie, dass der Tapped
Handler auch die InvalidateSurface
Methode des SKCanvasView
Objekts aufruft. Dadurch wird ein neuer Aufruf des PaintSurface
Handlers generiert.
Anzeigen der Bitmaps
Der PaintSurface
Handler muss drei Bitmaps anzeigen. Der Handler geht davon aus, dass sich das Telefon im Hochformat befindet und den Zeichenbereich vertikal in drei gleiche Teile unterteilt.
Die erste Bitmap wird mit der einfachsten DrawBitmap
Methode angezeigt. Sie müssen lediglich die X- und Y-Koordinaten angeben, wobei die obere linke Ecke der Bitmap positioniert werden soll:
public void DrawBitmap (SKBitmap bitmap, Single x, Single y, SKPaint paint = null)
Obwohl ein SKPaint
Parameter definiert ist, weist er einen Standardwert null
auf und Sie können ihn ignorieren. Die Pixel der Bitmap werden einfach mit einer 1:1-Zuordnung auf die Pixel der Anzeigeoberfläche übertragen. Im nächsten Abschnitt zu SkiaSharp Transparency wird eine Anwendung für dieses SKPaint
Argument angezeigt.
Ein Programm kann die Pixelabmessungen einer Bitmap mit den Width
Eigenschaften Height
abrufen. Mit diesen Eigenschaften kann das Programm Koordinaten berechnen, um die Bitmap in der Mitte des oberen Drittels des Zeichenbereichs zu positionieren:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
if (webBitmap != null)
{
float x = (info.Width - webBitmap.Width) / 2;
float y = (info.Height / 3 - webBitmap.Height) / 2;
canvas.DrawBitmap(webBitmap, x, y);
}
...
}
Die anderen beiden Bitmaps werden mit einer Version von DrawBitmap
einem SKRect
Parameter angezeigt:
public void DrawBitmap (SKBitmap bitmap, SKRect dest, SKPaint paint = null)
Eine dritte Version von DrawBitmap
zwei SKRect
Argumenten zum Angeben einer rechteckigen Teilmenge der anzuzeigenden Bitmap, aber diese Version wird in diesem Artikel nicht verwendet.
Hier sehen Sie den Code zum Anzeigen der Bitmap, die aus einer eingebetteten Ressourcenbitmap geladen wurde:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
if (resourceBitmap != null)
{
canvas.DrawBitmap(resourceBitmap,
new SKRect(0, info.Height / 3, info.Width, 2 * info.Height / 3));
}
...
}
Die Bitmap wird auf die Abmessungen des Rechtecks gestreckt, weshalb der Affen in diesen Screenshots horizontal gestreckt wird:
Das dritte Bild , das Sie nur sehen können, wenn Sie das Programm ausführen und ein Foto aus Ihrer eigenen Bildbibliothek laden, wird auch innerhalb eines Rechtecks angezeigt, aber die Position und Größe des Rechtecks werden an Standard seitenverhältnis der Bitmap angepasst. Diese Berechnung ist etwas mehr beteiligt, da es eine Berechnung eines Skalierungsfaktors erfordert, der auf der Größe der Bitmap und des Zielrechtecks basiert und das Rechteck in diesem Bereich zentriert wird:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
if (libraryBitmap != null)
{
float scale = Math.Min((float)info.Width / libraryBitmap.Width,
info.Height / 3f / libraryBitmap.Height);
float left = (info.Width - scale * libraryBitmap.Width) / 2;
float top = (info.Height / 3 - scale * libraryBitmap.Height) / 2;
float right = left + scale * libraryBitmap.Width;
float bottom = top + scale * libraryBitmap.Height;
SKRect rect = new SKRect(left, top, right, bottom);
rect.Offset(0, 2 * info.Height / 3);
canvas.DrawBitmap(libraryBitmap, rect);
}
else
{
using (SKPaint paint = new SKPaint())
{
paint.Color = SKColors.Blue;
paint.TextAlign = SKTextAlign.Center;
paint.TextSize = 48;
canvas.DrawText("Tap to load bitmap",
info.Width / 2, 5 * info.Height / 6, paint);
}
}
}
Wenn noch keine Bitmap aus der Bildbibliothek geladen wurde, zeigt der else
Block Text an, um den Benutzer auf den Bildschirm zu tippen.
Sie können Bitmaps mit verschiedenen Transparenzgraden anzeigen, und im nächsten Artikel zu SkiaSharp Transparency wird beschrieben, wie das geht.