[Xamarin] SkiaSharp 사용하기

2017. 11. 10. 15:21Mobile/Xamarin

세상에는 다양한 Graphic API가 존재하며 이를 통해 차트를 표현하기도 하고 역동적인 애니매이션을 표현하기도 합니다. 각 OS 플렛폼들은 독자적인 Graphic API를 제공하는데 iOS의 경우 CoreGraphics, Android는 Graphics, Windows에는 Media와 Imaging API가 존재합니다. 뿐만아니라 하드웨어 가속을 지원하는 API로는 OpenGL, OpenGL ES, DirectX 등이 존재합니다. 이러한 API들은 서로 다른 문법과 기술을 사용하기 때문에 작성된 코드를 다른 플렛폼으로 공유하는 것은 불가능에 가깝습니다.

이러한 문제를 해결하기 위해 구글에서는 Skia Graphic Library를 오픈소스(BSD)로 공개하였습니다. Skia의 내부 코드는 C++로 작성되었기 때문에 충분히 빠른 성능을 보장하며 작성된 Skia 코드는 다양한 플렛폼에서 실행될 수 있습니다. Android, iOS, Windows, Mac 뿐만 아니라 Google Chrome, Chrome OS, Android, Mozilla Firefox, Firefox OS, Android, Sublime Text3, BlackBerry PlayBook 등 다양한 플렛폼을 지원하며 Xamarin, Xamarin.Forms에서도 Skia를 사용하실 수 있습니다.

Xamarin.Forms에서 SkiaSharp 설치

Nuget에서 Skia를 검색하시면 아래와 같은 패키지가 검색됩니다.

  • SkiaSharp: Skia를 C#에서 이용할 수 있도록 지원하며 핵심 라이브러리 입니다. 이 라이브러리는 Windows Desktop, WPF, UWP, NET Standard 1.3, .NET Core를 지원하며 Xamarin을 통해 macOS, iOS, tvOS, Android에서도 이용하실 수 있습니다.
  • SkiaSharp.Views.Forms: Xamarin.Forms 프로젝트를 위한 패키지 입니다. Xamarin.Forms에서는 이 패키지만 설치하셔도 됩니다.
  • SkiaSharp.Views: Xamarin.Forms가 아닌 WPF 등 다른 플렛폼을 이용하실 경우 설치하시면 됩니다. Skia를 화면에 그리기 위한 Views나 Layer를 제공합니다.
  • SkiaSharp.Svg: Skia를 통해 간단한 SVG를 읽고 화면에 출력하실 수 있습니다.
  • SkiaSharp.Extended: Skia 개발에 도움이 될만한 다양한 확장 메서드를 제공합니다.

Xamarin.Forms 사용자는 Xamarin.Forms 솔루션의 각 프로젝트 별로 SkiaSharp.Views.Forms를 설치하시면 됩니다.

SkiaSharp View 추가

Xamarin.Forms의 XAML에 Skia가 그려질 Canvas를 선언해야 합니다. View는 SKCanvasView(CPU연산 기반)와 SKGLView(GPU연산 기반)가 제공되며 여기서는 SKCanvasView를 사용합니다.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="xfSampleCharts.Views.SkiaSharpPage"
    xmlns:sk="clr-namespace:SkiaSharp;assembly=SkiaSharp"
    xmlns:skv="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
    Title="SkiaSharp">
    <ContentPage.Content>
        <Grid>
            <skv:SKCanvasView x:Name="skCanvas" PaintSurface="SkCanvas_PaintSurface" />
        </Grid>
    </ContentPage.Content>
</ContentPage>

아래는 Code Behind 파일 코드입니다.

using SkiaSharp;
using SkiaSharp.Views.Forms;
 
private void SkCanvas_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e)
{
    //Drawing 코드는 여기에 위치합니다.
}

만약 지금 앱을 실행하시면 알수 없는 도형이나 픽셀이 나타날 수 있습니다. 아직 Canvas를 초기화하지 않았기 때문에 메모리에 남아있는 Garbage값이 화면에 나타나는 것 입니다.

그리기 객체

위에서 Canvas를 추가하였으므로 이제 화면에 그리기만 하면됩니다. 그리기 작업은 SKSurface, SKCanvas, SKaint를 통해 진행되는데 각각 무엇인지 알아봅시다.

1. SKSurface: SKSurface 인스턴스는 그리기를 위한 메모리 영역일 수 도 있고 OpenGL Framebuffer 개체의 Framebuffer ID일수도 있고 텍스쳐 오브젝트 일수도 있습니다. 무엇이든 간에 SKSurface는 화면에 그려지는 영역을 말합니다. SKSurface 인스턴스 생성은 SKSurface.Create 메서드를 통해 생성될 수 있습니다.

2. SKCanvas: 개발자가 작성한 Skia Drawing 명령을 SKSurface에 그리는데 적합한 명령으로 변환합니다. 예를들면 SKCanvas의 DrawRect, DrawPath 명령을 사용하면 SKCanvas는 SKSurface에 도형과 선을 그리는데 필요한 그래픽 명령을 생성하게 됩니다. 일반적으로 SKCanvas는 SKSurface.Canvas 속성을 통해서 생성하게 됩니다.

  • 도형 그리기: DrawRect, DrawOval, DrawPath
  • 문자 그리기:  DrawText
  • 이미지 그리기: DrawBitmap, DrawBitmapLattice
  • 기타: 회전(RotateDegress), 비틀기(Skew), 자르기(ClipRect)

3. SKPaint: SKCanvas를 통해 생성된 개체들이 화면에 어떻게 나타나야 하는지에 관한 명령을 제공합니다. 예를들어 SKCanvas.DrawRect를 통해 사각형 10개를 생성했다면 SKPaint를 통해 색상, 외곽선, 스타일 등을 다르게 설정 할 수 있습니다.

  • 스타일: IsAntialias, Color, Style, StrokeWidth
  • 텍스트: Typeface, UnderlineText, TextSize, TextAlign가 있습니다. 또한
  • 기타: 쉐이더, 마스크, 컬러필터, 이미지필터, 블렌드 모드 외

Canvas 초기화

이제 화면에 직접 그려봅시다. OnPainting 이벤트에서 그리기를 진행하게 됩니다. 그리기 전에 가장 먼저 해야할 일은 화면을 초기화하는 것입니다.

private void SkCanvas_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e)
{
    SKSurface surface = e.Surface;
    SKCanvas canvas = surface.Canvas;

    //화면을 흰색 바탕으로 초기화 합니다.
    canvas.Clear(SKColors.White);
}

도형 그리기

여기서는 원을 그려봅시다. SKCanvas.DrawCircle(cx, cy, radius, paint)를 통해 원을 그릴 수 있으며 SKPaint를 통해 색상이나 외곽선을 변경하실 수 있습니다.

//파랑색 원
SKPaint circleBlueFill = new SKPaint
{
    IsAntialias = true,
    Style = SKPaintStyle.Fill,
    Color = SKColors.Blue
};
canvas.DrawCircle(100, 100, 40, circleBlueFill);

//붉은색 원형 외곽선
SKPaint circleRedBorder = new SKPaint
{
    IsAntialias = true,
    Style = SKPaintStyle.Stroke,
    Color = SKColors.Red,
    StrokeWidth = 5
};
canvas.DrawCircle(100, 100, 40, circleRedBorder);

선 그리기

선은 SKPathSKCanvas.DrawPath(path, paint) 메서드를 통해 그릴 수 있습니다.

//녹색 X 선
SKPaint pathStroke = new SKPaint
{
    IsAntialias = true,
    Style = SKPaintStyle.Stroke,
    Color = SKColors.Green,
    StrokeWidth = 5
};
SKPath path = new SKPath();
path.MoveTo(160, 60);
path.LineTo(240, 140);
path.MoveTo(240, 60);
path.LineTo(160, 140);
canvas.DrawPath(path, pathStroke);

문자열 그리기

문자열은 SKCanvas.DrawText(text, x, y, paint)를 통해서 그릴 수 있습니다.

//문자그리기
SKPaint textPaint = new SKPaint
{
    IsAntialias = true,
    Style = SKPaintStyle.Fill,
    Color = SKColors.Orange,
    TextSize = 80
};
canvas.DrawText("SkiaSharp", 60, 160 + 80, textPaint);

References