Podstawy mapy bitowej w języku SkiaSharp
Załaduj mapy bitowe z różnych źródeł i wyświetl je.
Obsługa map bitowych w SkiaSharp jest dość obszerna. W tym artykule opisano tylko podstawowe informacje — sposób ładowania map bitowych i sposobu ich wyświetlania:
Znacznie głębszą eksplorację map bitowych można znaleźć w sekcji Mapy bitowe SkiaSharp.
Mapa bitowa SkiaSharp jest obiektem typu SKBitmap
. Istnieje wiele sposobów tworzenia mapy bitowej, ale ten artykuł ogranicza się do SKBitmap.Decode
metody, która ładuje mapę bitową z obiektu platformy .NET Stream
.
Strona Podstawowa mapa bitowa w programie SkiaSharpFormsDemos pokazuje, jak ładować mapy bitowe z trzech różnych źródeł:
- Z Internetu
- Z zasobu osadzonego w pliku wykonywalnym
- Z biblioteki zdjęć użytkownika
Trzy SKBitmap
obiekty dla tych trzech źródeł są definiowane jako pola w BasicBitmapsPage
klasie:
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;
...
}
...
}
Ładowanie mapy bitowej z Internetu
Aby załadować mapę bitową na podstawie adresu URL, możesz użyć HttpClient
klasy . Należy utworzyć wystąpienie tylko jednego wystąpienia HttpClient
i użyć go ponownie, więc zapisz je 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.
Ponieważ najwygodniejsze jest użycie await
operatora z HttpClient
programem , nie można wykonać kodu w konstruktorze BasicBitmapsPage
. Zamiast tego jest częścią OnAppearing
przesłonięcia. Adres URL tutaj wskazuje obszar w witrynie internetowej platformy Xamarin z przykładowymi mapami bitowymi. Pakiet w witrynie internetowej umożliwia dołączenie specyfikacji do zmiany rozmiaru mapy bitowej na określoną szerokość:
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
{
}
}
System operacyjny Android zgłasza wyjątek podczas używania Stream
zwracanego elementu z GetStreamAsync
metody SKBitmap.Decode
, ponieważ wykonuje długotrwałą operację w wątku głównym. Z tego powodu zawartość pliku mapy bitowej jest kopiowana do MemoryStream
obiektu przy użyciu polecenia CopyToAsync
.
Metoda statyczna SKBitmap.Decode
jest odpowiedzialna za dekodowanie plików map bitowych. Działa z formatami map bitowych JPEG, PNG i GIF oraz zapisuje wyniki w wewnętrznym formacie SkiaSharp. W tym momencie należy unieważnić program SKCanvasView
obsługi w celu PaintSurface
zaktualizowania ekranu.
Ładowanie zasobu mapy bitowej
Jeśli chodzi o kod, najprostszym podejściem do ładowania map bitowych jest dołączenie zasobu mapy bitowej bezpośrednio w aplikacji. Program SkiaSharpFormsDemos zawiera folder o nazwie Media zawierający kilka plików map bitowych, w tym jeden o nazwie monkey.png. W przypadku map bitowych przechowywanych jako zasoby programu należy użyć okna dialogowego Właściwości, aby nadać plikowi akcję kompilacji zasobu osadzonego!
Każdy zasób osadzony ma identyfikator zasobu, który składa się z nazwy projektu, folderu i nazwy pliku, wszystkie połączone kropkami: SkiaSharpFormsDemos.Media.monkey.png. Dostęp do tego zasobu można uzyskać, określając ten identyfikator zasobu jako argument GetManifestResourceStream
metody Assembly
klasy:
string resourceID = "SkiaSharpFormsDemos.Media.monkey.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
resourceBitmap = SKBitmap.Decode(stream);
}
Ten Stream
obiekt można przekazać bezpośrednio do SKBitmap.Decode
metody .
Ładowanie mapy bitowej z biblioteki zdjęć
Użytkownik może również załadować zdjęcie z biblioteki obrazów urządzenia. Ten obiekt nie jest zapewniany Xamarin.Forms samodzielnie. Zadanie wymaga usługi zależności, takiej jak ta opisana w artykule Wybieranie zdjęcia z biblioteki obrazów.
Plik IPhotoLibrary.cs w projekcie SkiaSharpFormsDemos i trzy pliki PhotoLibrary.cs w projektach platformy zostały dostosowane z tego artykułu. Ponadto plik MainActivity.cs systemu Android został zmodyfikowany zgodnie z opisem w artykule, a projekt systemu iOS otrzymał uprawnienia dostępu do biblioteki zdjęć z dwoma wierszami w dolnej części pliku info.plist.
Konstruktor BasicBitmapsPage
dodaje element TapGestureRecognizer
do SKCanvasView
elementu , aby otrzymywać powiadomienia o naciśnięciach. Po otrzymaniu naciśnięcia Tapped
program obsługi uzyskuje dostęp do usługi zależności selektora obrazów i wywołuje metodę PickPhotoAsync
. Stream
Jeśli obiekt zostanie zwrócony, zostanie przekazany do SKBitmap.Decode
metody :
// 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);
Zwróć uwagę, że Tapped
procedura obsługi wywołuje również metodę InvalidateSurface
SKCanvasView
obiektu. Spowoduje to wygenerowanie nowego wywołania PaintSurface
programu obsługi.
Wyświetlanie map bitowych
Procedura PaintSurface
obsługi musi wyświetlać trzy mapy bitowe. Procedura obsługi zakłada, że telefon jest w trybie pionowym i dzieli kanwę w pionie na trzy równe części.
Pierwsza mapa bitowa jest wyświetlana przy użyciu najprostszej DrawBitmap
metody. Wystarczy określić współrzędne X i Y, w których ma być umieszczony lewy górny róg mapy bitowej:
public void DrawBitmap (SKBitmap bitmap, Single x, Single y, SKPaint paint = null)
SKPaint
Chociaż parametr jest zdefiniowany, ma wartość null
domyślną i można go zignorować. Piksele mapy bitowej są po prostu przenoszone do pikseli powierzchni wyświetlania z mapowaniem jeden do jednego. Aplikacja dla tego SKPaint
argumentu zostanie wyświetlona w następnej sekcji dotyczącej przezroczystości SkiaSharp.
Program może uzyskać wymiary pikseli mapy bitowej z właściwościami Width
i Height
. Te właściwości umożliwiają programowi obliczanie współrzędnych w celu położenia mapy bitowej w środku górnej trzeciej kanwy:
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);
}
...
}
Pozostałe dwie mapy bitowe są wyświetlane z wersją parametru DrawBitmap
SKRect
:
public void DrawBitmap (SKBitmap bitmap, SKRect dest, SKPaint paint = null)
Trzecia wersja programu DrawBitmap
ma dwa SKRect
argumenty służące do określania prostokątnego podzestawu mapy bitowej do wyświetlenia, ale ta wersja nie jest używana w tym artykule.
Oto kod umożliwiający wyświetlenie mapy bitowej załadowanej z osadzonej mapy bitowej zasobów:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
...
if (resourceBitmap != null)
{
canvas.DrawBitmap(resourceBitmap,
new SKRect(0, info.Height / 3, info.Width, 2 * info.Height / 3));
}
...
}
Mapa bitowa jest rozciągana na wymiary prostokąta, dlatego małpa jest rozciągnięta poziomo na tych zrzutach ekranu:
Trzeci obraz — który można zobaczyć tylko w przypadku uruchomienia programu i załadowania zdjęcia z własnej biblioteki obrazów — jest również wyświetlany w prostokątze, ale położenie i rozmiar prostokąta są dostosowywane w celu zachowania współczynnika proporcji mapy bitowej. To obliczenie jest nieco bardziej zaangażowane, ponieważ wymaga obliczenia współczynnika skalowania na podstawie rozmiaru mapy bitowej i prostokąta docelowego oraz wyśrodkowania prostokąta w tym obszarze:
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);
}
}
}
Jeśli mapa bitowa nie została jeszcze załadowana z biblioteki obrazów, else
blok wyświetla jakiś tekst, aby monitować użytkownika o naciśnięcie ekranu.
Możesz wyświetlać mapy bitowe o różnym stopniu przezroczystości, a w następnym artykule na temat Przezroczystości SkiaSharp opisano, jak to zrobić.