다음을 통해 공유


SkiaSharp의 비트맵 기본 사항

다양한 소스에서 비트맵을 로드하고 표시합니다.

SkiaSharp의 비트맵 지원은 매우 광범위합니다. 이 문서에서는 비트맵을 로드하는 방법과 표시하는 방법 등 기본 사항만 다룹니다.

두 비트맵의 표시

비트맵에 대한 훨씬 더 심층적인 탐색은 SkiaSharp 비트맵 섹션에서 찾을 수 있습니다.

SkiaSharp 비트맵은 형식 SKBitmap의 개체입니다. 비트맵을 만드는 방법에는 여러 가지가 있지만 이 문서에서는 .NET Stream 개체에서 비트맵을 SKBitmap.Decode 로드하는 메서드로 제한합니다.

SkiaSharpFormsDemos 프로그램의 기본 비트맵 페이지는 세 가지 소스에서 비트맵을 로드하는 방법을 보여 줍니다.

  • 인터넷을 통해
  • 실행 파일에 포함된 리소스에서
  • 사용자의 사진 라이브러리에서

이러한 세 소스에 대한 세 SKBitmap 가지 개체는 클래스의 BasicBitmapsPage 필드로 정의됩니다.

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;
        ...
    }
    ...
}

웹에서 비트맵 로드

URL을 기반으로 비트맵을 로드하려면 클래스를 HttpClient 사용할 수 있습니다. 인스턴스를 하나 HttpClient 만 인스턴스화하고 다시 사용하므로 필드로 저장해야 합니다.

HttpClient httpClient = new HttpClient();

iOS 및 Android 애플리케이션을 사용하는 HttpClient 경우 TLS(전송 계층 보안) 1.2문서에 설명된 대로 프로젝트 속성을 설정하려고 합니다.

연산HttpClient자를 사용하는 await 것이 가장 편리하기 때문에 생성자에서 BasicBitmapsPage 코드를 실행할 수 없습니다. 대신 재정의의 OnAppearing 일부입니다. 여기서 URL은 샘플 비트맵이 있는 Xamarin 웹 사이트의 영역을 가리킵니다. 웹 사이트의 패키지를 사용하면 비트맵의 크기를 특정 너비로 조정하기 위한 사양을 추가할 수 있습니다.

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
    {
    }
}

Android 운영 체제는 기본 스레드에서 긴 작업을 수행하므로 메서드에서 GetStreamAsyncSKBitmap.Decode 반환된 항목을 사용할 Stream 때 예외가 발생합니다. 이러한 이유로 비트맵 파일의 내용은 .를 사용하여 CopyToAsync개체에 MemoryStream 복사됩니다.

정적 SKBitmap.Decode 메서드는 비트맵 파일 디코딩을 담당합니다. JPEG, PNG 및 GIF 비트맵 형식으로 작동하고 결과를 내부 SkiaSharp 형식으로 저장합니다. 이 시점에서 SKCanvasView 처리기가 디스플레이를 업데이트할 수 있도록 PaintSurface 무효화해야 합니다.

비트맵 리소스 로드

코드 측면에서 비트맵을 로드하는 가장 쉬운 방법은 애플리케이션에 비트맵 리소스를 직접 포함하는 것입니다. SkiaSharpFormsDemos 프로그램에는 이름이 monkey.png 파일을 포함하여 여러 비트맵 파일이 포함된 Media라는 폴더가 포함되어 있습니다. 프로그램 리소스로 저장된 비트맵의 경우 속성 대화 상자를 사용하여 파일에 포함된 리소스빌드 작업을 제공해야 합니다.

포함된 각 리소스에는 프로젝트 이름, 폴더 및 파일 이름으로 구성된 리소스 ID 가 있으며, 모두 마침표 (SkiaSharpFormsDemos.Media.monkey.png)로 연결됩니다. 해당 리소스 ID를 클래스 메서드의 Assembly 인수로 지정하여 이 리소스에 GetManifestResourceStream 액세스할 수 있습니다.

string resourceID = "SkiaSharpFormsDemos.Media.monkey.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;

using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
    resourceBitmap = SKBitmap.Decode(stream);
}

Stream 개체는 메서드에 SKBitmap.Decode 직접 전달할 수 있습니다.

사진 라이브러리에서 비트맵 로드

사용자가 디바이스의 사진 라이브러리에서 사진을 로드할 수도 있습니다. 이 시설은 그 자체로 제공되지 Xamarin.Forms 않습니다. 이 작업에는 그림 라이브러리에서 사진 선택 문서에 설명된 것과 같은 종속성 서비스가 필요합니다.

SkiaSharpFormsDemos 프로젝트의 IPhotoLibrary.cs 파일플랫폼 프로젝트의 세 PhotoLibrary.cs 파일이 해당 문서에서 수정되었습니다. 또한 Android MainActivity.cs 파일이 문서에 설명된 대로 수정되었으며 iOS 프로젝트에 info.plist 파일 아래쪽에 두 줄로 된 사진 라이브러리에 액세스할 수 있는 권한이 부여되었습니다.

BasicBitmapsPage 생성자는 탭 알림을 받을 값을 추가 SKCanvasViewTapGestureRecognizer 합니다. 탭 Tapped 을 받으면 처리기는 그림 선택 종속성 서비스 및 호출 PickPhotoAsync에 대한 액세스를 가져옵니다. 개체가 Stream 반환되면 메서드에 SKBitmap.Decode 전달됩니다.

// 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);

처리기는 Tapped 개체의 메서드도 호출 InvalidateSurface 합니다 SKCanvasView . 그러면 처리기에 대한 새 호출이 PaintSurface 생성됩니다.

비트맵 표시

PaintSurface 처리기는 세 개의 비트맵을 표시해야 합니다. 처리기는 휴대폰이 세로 모드에 있다고 가정하고 캔버스를 세로로 세로로 세로로 나눕니다.

첫 번째 비트맵은 가장 DrawBitmap 간단한 메서드와 함께 표시됩니다. 비트맵의 왼쪽 위 모서리를 배치할 X 및 Y 좌표만 지정하면 됩니다.

public void DrawBitmap (SKBitmap bitmap, Single x, Single y, SKPaint paint = null)

SKPaint 매개 변수는 정의되어 있지만 기본값 null 이 있으며 무시해도 됩니다. 비트맵의 픽셀은 일대일 매핑을 사용하여 디스플레이 화면의 픽셀로 전송됩니다. SkiaSharp 투명도의 다음 섹션에서 이 SKPaint 인수에 대한 애플리케이션을 볼 수 있습니다.

프로그램은 및 속성을 사용하여 비트맵의 픽셀 차원을 WidthHeight 가져올 수 있습니다. 이러한 속성을 사용하면 프로그램에서 좌표를 계산하여 비트맵을 캔버스의 3분의 1 위에 배치할 수 있습니다.

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);
    }
    ...
}

다른 두 비트맵은 매개 변수가 있는 버전 DrawBitmap 과 함께 SKRect 표시됩니다.

public void DrawBitmap (SKBitmap bitmap, SKRect dest, SKPaint paint = null)

세 번째 버전 DrawBitmap 에는 표시할 비트맵의 사각형 하위 집합을 지정하기 위한 두 개의 SKRect 인수가 있지만 이 문서에서는 해당 버전이 사용되지 않습니다.

포함된 리소스 비트맵에서 로드된 비트맵을 표시하는 코드는 다음과 같습니다.

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
    if (resourceBitmap != null)
    {
        canvas.DrawBitmap(resourceBitmap,
            new SKRect(0, info.Height / 3, info.Width, 2 * info.Height / 3));
    }
    ...
}

비트맵은 사각형의 크기로 확장되므로 원숭이가 다음 스크린샷에서 수평으로 늘어나게 됩니다.

기본 비트맵 페이지의 삼중 스크린샷

프로그램을 실행하고 자신의 사진 라이브러리에서 사진을 로드하는 경우에만 볼 수 있는 세 번째 이미지는 사각형 내에 표시되지만 사각형의 위치와 크기는 비트맵의 가로 세로 비율을 기본 있도록 조정됩니다. 비트맵 및 대상 사각형의 크기에 따라 배율 인수를 계산하고 해당 영역의 사각형을 가운데에 배치해야 하므로 이 계산은 좀 더 복잡합니다.

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);
        }
    }
}

그림 라이브러리 else 에서 아직 비트맵을 로드하지 않은 경우 블록에 화면을 탭하라는 메시지를 표시하는 일부 텍스트가 표시됩니다.

다양한 수준의 투명도로 비트맵을 표시할 수 있으며 SkiaSharp 투명도에 대한 다음 문서에서 방법을 설명합니다.