Udostępnij za pośrednictwem


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:

Wyświetlanie dwóch map bitowych

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 HttpClientprogramem , 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ę InvalidateSurfaceSKCanvasView 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 DrawBitmapSKRect :

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:

Potrójny zrzut ekranu przedstawiający stronę Podstawowa mapa bitowa

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ć.