Porter 임신 blend 모드Porter-Duff blend modes

샘플 다운로드 샘플 다운로드Download Sample Download the sample

Thomas Porter Tom 임신 Lucasfilm 근무 하면서 합성는 대 수를 개발한 후 Porter 임신 blend 모드 라고 합니다.The Porter-Duff blend modes are named after Thomas Porter and Tom Duff, who developed an algebra of compositing while working for Lucasfilm. 백서 합치기 디지털 이미지 1984 년 7 월호에 게시 된 컴퓨터 그래픽, 253을 259 페이지입니다.Their paper Compositing Digital Images was published in the July 1984 issue of Computer Graphics, pages 253 to 259. 이러한 혼합 모드는 합치기를 복합 장면에 다양 한 이미지를 구축 하는 데 필요한:These blend modes are essential for compositing, which is assembling various images into a composite scene:

샘플 Porter 임신Porter-Duff Sample

Porter 임신 개념Porter-Duff concepts

갈색 사각형의 왼쪽 및 위쪽의 2/3 화면에 표시를 차지 한다고 가정 합니다.Suppose a brownish rectangle occupies the left and top two-thirds of your display surface:

대상 Porter 임신Porter-Duff Destination

이 영역 라고 합니다 대상 또는 경우에 따라 합니다 백그라운드 또는 밑그림.This area is called the destination or sometimes the background or backdrop.

대상의 크기가 같은 다음 영역을 그릴 하려고 합니다.You wish to draw the following rectangle, which is the same size of the destination. 사각형은 오른쪽 아래 2 / 3 차지 하는 파랑 추가 영역을 제외 하 고 투명 합니다.The rectangle is transparent except for a bluish area that occupies the right and bottom two-thirds:

원본 Porter 임신Porter-Duff Source

이것을 합니다 원본 또는 경우에 따라 합니다 _포그라운드_합니다.This is called the source or sometimes the foreground.

대상에 소스를 표시할 때 예상 대로 다음과 같습니다.When you display the source on the destination, here's what you expect:

소스 Porter 임신Porter-Duff Source Over

원본의 투명 한 픽셀 배경을 파랑 추가 소스 픽셀 백그라운드 모호 하 게 하는 동안를 통해 볼 수 있습니다.The transparent pixels of the source allow the background to show through, while the bluish source pixels obscure the background. 일반적인 경우는 및에서 SkiaSharp로 라고 SKBlendMode.SrcOver합니다.That's the normal case, and it is referred to in SkiaSharp as SKBlendMode.SrcOver. 값의 기본 설정은 인지 합니다 BlendMode 속성 때는 SKPaint 개체가 처음 인스턴스화입니다.That value is the default setting of the BlendMode property when an SKPaint object is first instantiated.

그러나 다른 효과 대 한 다른 blend 모드를 지정 하는 것이 같습니다.However, it's possible to specify a different blend mode for a different effect. 지정 하는 경우 SKBlendMode.DstOver, 원본 및 대상의 교차 영역에서 대상 소스 대신 나타납니다.If you specify SKBlendMode.DstOver, then in the area where the source and destination intersect, the destination appears instead of the source:

통해 대상 Porter 임신Porter-Duff Destination Over

SKBlendMode.DstIn blend 모드에서는 원본과 대상 교차 하는 대상 색을 사용 하는 영역만 표시 됩니다.The SKBlendMode.DstIn blend mode displays only the area where the destination and source intersect using the destination color:

대상에 Porter 임신Porter-Duff Destination In

혼합 모드 SKBlendMode.Xor (배타적 OR) 하면 두 가지 영역 겹치는 표시할 아무 작업도 수행 합니다.The blend mode of SKBlendMode.Xor (exclusive OR) causes nothing to appear where the two areas overlap:

Porter 임신 전용 또는Porter-Duff Exclusive Or

색이 지정 된 대상 및 소스 사각형 대상 및 소스 사각형의 현재 상태에 해당 하는 다양 한 방법으로 색칠 할 수 있는 4 개의 고유 영역으로 화면을 효과적으로 나눕니다.The colored destination and source rectangles effectively divide the display surface into four unique areas that can be colored in various ways corresponding to the presence of the destination and source rectangles:

Porter 임신Porter-Duff

왼쪽 및 오른쪽 위 사각형은 해당 영역에 대상 및 원본 투명 한 있기 때문에 항상 비어 있습니다.The upper-right and lower-left rectangles are always blank because both the destination and source are transparent in those areas. 대상 색 영역 대상 색과 나타나거나 전혀 나타나지 색칠 할 하거나 수 있도록 왼쪽 영역을 차지 합니다.The destination color occupies the upper-left area, so that area can either be colored with the destination color or not at all. 마찬가지로, 소스 색 또는 전혀 소스 색으로 영역을 색칠 할 수 있도록 오른쪽 아래 영역을 차지 합니다.Similarly, the source color occupies the lower-right area, so that area can be colored with the source color or not at all. 대상 색, 소스 색 또는 전혀 사용 하지 않을 중간에서 원본과 대상의 교집합을 색칠 할 수 있습니다.The intersection of the destination and source in the middle can be colored with the destination color, the source color, or not at all.

조합 총 수는 (센터용), 3 또는 12 시간 (오른쪽 아래)에 대 한 2 시간 (왼쪽 위)에 2입니다.The total number of combinations is 2 (for the upper-left) times 2 (for the lower-right) times 3 (for the center), or 12. 이들은 12 기본 Porter 임신 혼합 모드입니다.These are the 12 basic Porter-Duff compositing modes.

끝부분 합치기 디지털 이미지 (256 페이지) Porter 임신 라는 13 모드를 추가 plus (해당 하는 SkiaSharp SKBlendMode.Plus 멤버 및 W3C 더 밝게 모드 (W3C와 혼동 하지입니다 밝게 모드입니다.) 이 Plus 모드 추가 된 대상 및 원본 색상으로 프로세스를 곧 자세히 설명 합니다.Towards the end of Compositing Digital Images (page 256), Porter and Duff add a 13th mode called plus (corresponding to the SkiaSharp SKBlendMode.Plus member and the W3C Lighter mode (which is not to be confused with the W3C Lighten mode.) This Plus mode adds the destination and source colors, a process that will be described in more detail shortly.

Skia 추가 호출을 14 모드 Modulate 매우 비슷한 Plus 제외 하 고 대상 및 소스 색을 곱합니다.Skia adds a 14th mode called Modulate that is very similar to Plus except that the destination and source colors are multiplied. 추가 Porter 임신 blend 모드로 처리할 수 있습니다.It can be treated as an additional Porter-Duff blend mode.

SkiaSharp에 정의 된 대로 14 Porter 임신 모드는 다음과 같습니다.Here are the 14 Porter-Duff modes as defined in SkiaSharp. 테이블 위의 다이어그램에는 세 가지 비어 있지 않은 영역이의 각 색은 방법을 보여 줍니다.The table shows how they color each of the three non-blank areas in the diagram above:

모드Mode 대상Destination 교집합Intersection 소스Source
Clear
Src 소스Source XX
Dst XX 대상Destination
SrcOver XX 소스Source XX
DstOver XX 대상Destination XX
SrcIn 소스Source
DstIn 대상Destination
SrcOut XX
DstOut XX
SrcATop XX 소스Source
DstATop 대상Destination XX
Xor XX XX
Plus XX SumSum XX
Modulate 제품Product

이러한 혼합 모드가 대칭으로 나타납니다.These blend modes are symmetrical. 원본 및 대상 교환할 수 있으며 모든 모드는 계속 사용할 수 있습니다.The source and destination can be exchanged and all the modes are still available.

모드의 명명 규칙에는 몇 가지 간단한 규칙을 따릅니다.The naming convention of the modes follows a few simple rules:

  • SrcDst 자체로 원본 또는 대상 픽셀만 표시 되는 것을 의미 합니다.Src or Dst by itself means that only the source or destination pixels are visible.
  • 합니다 위에 접미사의 교차 부분에서 표시 되는 사항을 나타냅니다.The Over suffix indicates what is visible in the intersection. 원본 또는 대상 "끝" 다른 그려집니다.Either the source or destination is drawn "over" the other.
  • 합니다 에서 접미사 의미 교차 부분만 색입니다.The In suffix means that only the intersection is colored. 출력 소스 또는 대상 "에 있는" 다른 부분만으로 제한 됩니다.The output is restricted to only the part of the source or destination that is "in" the other.
  • 합니다 Out 접미사 의미 교집합 색상이 지정 되지 않습니다.The Out suffix means that the intersection is not colored. 출력은 부분에만 소스 또는 대상 "out" 교집합입니다.The output is only the part of the source or destination that is "out" of the intersection.
  • 위에 접미사는 합한 에서 하 고 아웃. 다른 원본 또는 대상 "위에"는 영역을 포함 합니다.The ATop suffix is the union of In and Out. It includes the area where the source or destination is "atop" of the other.

사용 하 여 차이점을 확인 합니다 PlusModulate 모드입니다.Notice the difference with the Plus and Modulate modes. 이러한 모드는 원본 및 대상 픽셀에서 다른 유형의 계산을 수행 합니다.These modes are performing a different type of calculation on the source and destination pixels. 곧 자세히 설명 되어는 있습니다.They are described in more detail shortly.

합니다 Porter 임신 표 페이지 표 형태로 한 화면에 모든 14 모드를 보여 줍니다.The Porter-Duff Grid page shows all 14 modes on one screen in the form of a grid. 각 모드는 별도의 인스턴스가 SKCanvasView합니다.Each mode is a separate instance of SKCanvasView. 따라서 클래스에서 파생 됩니다 SKCanvasView 라는 PorterDuffCanvasView합니다.For that reason, a class is derived from SKCanvasView named PorterDuffCanvasView. 정적 생성자의 왼쪽 위 영역에 갈색 사각형이 하나 및 파랑 추가 사각형을 사용 하 여 동일한 크기의 두 비트맵을 만듭니다.The static constructor creates two bitmaps of the same size, one with a brownish rectangle in its upper-left area and another with a bluish rectangle:

class PorterDuffCanvasView : SKCanvasView
{
    static SKBitmap srcBitmap, dstBitmap;

    static PorterDuffCanvasView()
    {
        dstBitmap = new SKBitmap(300, 300);
        srcBitmap = new SKBitmap(300, 300);

        using (SKPaint paint = new SKPaint())
        {
            using (SKCanvas canvas = new SKCanvas(dstBitmap))
            {
                canvas.Clear();
                paint.Color = new SKColor(0xC0, 0x80, 0x00);
                canvas.DrawRect(new SKRect(0, 0, 200, 200), paint);
            }
            using (SKCanvas canvas = new SKCanvas(srcBitmap))
            {
                canvas.Clear();
                paint.Color = new SKColor(0x00, 0x80, 0xC0);
                canvas.DrawRect(new SKRect(100, 100, 300, 300), paint);
            }
        }
    }
    ···
}

인스턴스 생성자에는 매개 변수 형식 SKBlendMode합니다.The instance constructor has a parameter of type SKBlendMode. 이 매개 변수를 필드에 저장합니다.It saves this parameter in a field.

class PorterDuffCanvasView : SKCanvasView
{
    ···
    SKBlendMode blendMode;

    public PorterDuffCanvasView(SKBlendMode blendMode)
    {
        this.blendMode = blendMode;
    }

    protected override void OnPaintSurface(SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Find largest square that fits
        float rectSize = Math.Min(info.Width, info.Height);
        float x = (info.Width - rectSize) / 2;
        float y = (info.Height - rectSize) / 2;
        SKRect rect = new SKRect(x, y, x + rectSize, y + rectSize);

        // Draw destination bitmap
        canvas.DrawBitmap(dstBitmap, rect);

        // Draw source bitmap
        using (SKPaint paint = new SKPaint())
        {
            paint.BlendMode = blendMode;
            canvas.DrawBitmap(srcBitmap, rect, paint);
        }

        // Draw outline
        using (SKPaint paint = new SKPaint())
        {
            paint.Style = SKPaintStyle.Stroke;
            paint.Color = SKColors.Black;
            paint.StrokeWidth = 2;
            rect.Inflate(-1, -1);
            canvas.DrawRect(rect, paint);
        }
    }
}

OnPaintSurface 재정의 두 비트맵을 그립니다.The OnPaintSurface override draws the two bitmaps. 첫 번째 일반적으로 그려집니다.The first is drawn normally:

canvas.DrawBitmap(dstBitmap, rect);

두 번째 그릴를 SKPaint 개체 위치를 BlendMode 생성자 인수에 속성이 설정 되어:The second is drawn with an SKPaint object where the BlendMode property has been set to the constructor argument:

using (SKPaint paint = new SKPaint())
{
    paint.BlendMode = blendMode;
    canvas.DrawBitmap(srcBitmap, rect, paint);
}

나머지는 OnPaintSurface 재정의를 해당 크기를 나타내는 비트맵 주위에 사각형을 그립니다.The remainder of the OnPaintSurface override draws a rectangle around the bitmap to indicate their sizes.

PorterDuffGridPage 클래스의 14 인스턴스를 만듭니다 PorterDurffCanvasView, 각 멤버에 대 한 하나는 blendModes 배열입니다.The PorterDuffGridPage class creates fourteen instances of PorterDurffCanvasView, one for each member of the blendModes array. 순서는 SKBlendModes 서로 인접 한 비슷한 모드를 배치 하기 위해 배열의 멤버는 테이블 보다 약간 다릅니다.The order of the SKBlendModes members in the array is a little different than the table in order to position similar modes adjacent to each other. 14 인스턴스의 PorterDuffCanvasView 의 레이블과 함께 구성 되는 Grid:The 14 instances of PorterDuffCanvasView are organized along with labels in a Grid:

public class PorterDuffGridPage : ContentPage
{
    public PorterDuffGridPage()
    {
        Title = "Porter-Duff Grid";

        SKBlendMode[] blendModes =
        {
            SKBlendMode.Src, SKBlendMode.Dst, SKBlendMode.SrcOver, SKBlendMode.DstOver,
            SKBlendMode.SrcIn, SKBlendMode.DstIn, SKBlendMode.SrcOut, SKBlendMode.DstOut,
            SKBlendMode.SrcATop, SKBlendMode.DstATop, SKBlendMode.Xor, SKBlendMode.Plus,
            SKBlendMode.Modulate, SKBlendMode.Clear
        };

        Grid grid = new Grid
        {
            Margin = new Thickness(5)
        };

        for (int row = 0; row < 4; row++)
        {
            grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
        }

        for (int col = 0; col < 3; col++)
        {
            grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star });
        }

        for (int i = 0; i < blendModes.Length; i++)
        {
            SKBlendMode blendMode = blendModes[i];
            int row = 2 * (i / 4);
            int col = i % 4;

            Label label = new Label
            {
                Text = blendMode.ToString(),
                HorizontalTextAlignment = TextAlignment.Center
            };
            Grid.SetRow(label, row);
            Grid.SetColumn(label, col);
            grid.Children.Add(label);

            PorterDuffCanvasView canvasView = new PorterDuffCanvasView(blendMode);

            Grid.SetRow(canvasView, row + 1);
            Grid.SetColumn(canvasView, col);
            grid.Children.Add(canvasView);
        }

        Content = grid;
    }
}

결과 다음과 같습니다.Here's the result:

Porter 임신 그리드Porter-Duff Grid

투명도 Porter 임신 blend 모드를 적절 하 게 작동 하는 데 중요 임을 직접 확인 해야 합니다.You'll want to convince yourself that transparency is crucial to the proper functioning of the Porter-Duff blend modes. 합니다 PorterDuffCanvasView 를 세 번 호출의 합계를 포함 하는 클래스는 Canvas.Clear 메서드.The PorterDuffCanvasView class contains a total of three calls to the Canvas.Clear method. 모든 픽셀을 모두 투명 하 게 설정 하는 매개 변수가 없는 메서드를 사용 합니다.All of them use the parameterless method, which sets all the pixels to transparent:

canvas.Clear();

픽셀 불투명 흰색으로 설정 되어 있도록 해당 호출을 변경해 보세요.Try changing any of those calls so that the pixels are set to opaque white:

canvas.Clear(SKColors.White);

해당 변경 내용을 다음 작동 하는 것 처럼 보이고 일부 blend 모드 있지만 일부는 그렇지 않습니다.Following that change, some of the blend modes will seem to work, but others will not. 소스 비트맵의 배경색을 흰색으로 설정 하는 경우 해당 SrcOver 모드에에서 있기 때문에 투명 한 픽셀 없습니다 소스 비트맵을 통과해 표시 대상 수 있도록 작동 하지 않습니다.If you set the background of the source bitmap to white, then the SrcOver mode doesn't work because there's no transparent pixels in the source bitmap to let the destination show through. 대상 비트맵을 다음 흰색 캔버스의 배경색을 설정 하는 경우 DstOver 대상에는 모든 투명 한 픽셀 없기 때문에 작동 하지 않습니다.If you set the background of the destination bitmap or the canvas to white, then DstOver doesn't work because the destination doesn't have any transparent pixels.

비트맵을 바꾸려면 유혹이 있을 수 있습니다는 Porter 임신 그리드 페이지에 간단한 DrawRect 호출 합니다.There might be a temptation to replace the bitmaps in the Porter-Duff Grid page with simpler DrawRect calls. 소스 사각형 아니라 대상 사각형에 대 한 작동 합니다.That will work for the destination rectangle but not for the source rectangle. 소스 사각형 이상의 파랑 추가 색 영역 범위가 포함 되어야 합니다.The source rectangle must encompass more than just the bluish-colored area. 소스 사각형에는 대상의 색이 지정 된 영역에 해당 하는 투명 한 영역을 포함 해야 합니다.The source rectangle must include a transparent area that corresponds to the colored area of the destination. 그런 후에 모드 작업을 조화 이러한 합니다.Only then will these blend modes work.

Porter 임신 매트 사용Using mattes with Porter-Duff

Brick-Wall 합치기 페이지 클래식 합치기 작업의 예를 보여 줍니다. 그림 제거 해야 하는 백그라운드를 사용 하 여 비트맵을 포함 하 여 여러 조각에서 조합할 수 해야 합니다.The Brick-Wall Compositing page shows an example of a classic compositing task: A picture needs to be assembled from several pieces, including a bitmap with a background that needs to be eliminated. 다음은 SeatedMonkey.jpg 문제가 있는 배경 비트맵:Here's the SeatedMonkey.jpg bitmap with the problematic background:

Monkey 장착Seated Monkey

해당으로 합치기를 위한 준비 매트 만들어진 있는 이미지를 표시 하려는 경우에 검은색 및 투명 하 게 다른 비트 멥 인 합니다.In preparation for compositing, a corresponding matte was created, which is another bitmap that is black where you want the image to appear and transparent otherwise. 이 파일의 이름은 SeatedMonkeyMatte.png 의 리소스 간에 이며 합니다 미디어 폴더에는 SkiaSharpFormsDemos 샘플 :This file is named SeatedMonkeyMatte.png and is among the resources in the Media folder in the SkiaSharpFormsDemos sample:

Monkey 매트 장착Seated Monkey Matte

이것이 되지 는 전문적 만든된 매트 합니다.This is not an expertly created matte. 최적으로 매트 부분적으로 투명 한 검정 픽셀의 가장자리 픽셀을 포함 해야 하 고이 매트 하지 않습니다.Optimally, the matte should include partially transparent pixels around the edge of the black pixels, and this matte does not.

에 대 한 XAML 파일을 Brick-Wall 합치기 페이지를 인스턴스화하는 SKCanvasViewButton 사용자를 최종 이미지를 작성 하는 과정을 안내 하는:The XAML file for the Brick-Wall Compositing page instantiates an SKCanvasView and a Button that guides the user through the process of composing the final image:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.BrickWallCompositingPage"
             Title="Brick-Wall Compositing">

    <StackLayout>
        <skia:SKCanvasView x:Name="canvasView"
                           VerticalOptions="FillAndExpand"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <Button Text="Show sitting monkey"
                HorizontalOptions="Center"
                Margin="0, 10"
                Clicked="OnButtonClicked" />

    </StackLayout>
</ContentPage>

코드 숨김 파일을 로드 해야 하 고 처리 하는 두 비트맵 합니다 Clicked 의 이벤트는 Button합니다.The code-behind file loads the two bitmaps that it needs and handles the Clicked event of the Button. 에 대 한 모든 Button 를 클릭 합니다 step 필드는 증가 하며 새 Text 속성에 대 한는 Button합니다.For every Button click, the step field is incremented and a new Text property is set for the Button. step 5에 도달 하면 0으로 다시 설정 됩니다.When step reaches 5, it is set back to 0:

public partial class BrickWallCompositingPage : ContentPage
{
    SKBitmap monkeyBitmap = BitmapExtensions.LoadBitmapResource(
        typeof(BrickWallCompositingPage), 
        "SkiaSharpFormsDemos.Media.SeatedMonkey.jpg");

    SKBitmap matteBitmap = BitmapExtensions.LoadBitmapResource(
        typeof(BrickWallCompositingPage), 
        "SkiaSharpFormsDemos.Media.SeatedMonkeyMatte.png");

    int step = 0;

    public BrickWallCompositingPage ()
    {
        InitializeComponent ();
    }

    void OnButtonClicked(object sender, EventArgs args)
    {
        Button btn = (Button)sender;
        step = (step + 1) % 5;

        switch (step)
        {
            case 0: btn.Text = "Show sitting monkey"; break;
            case 1: btn.Text = "Draw matte with DstIn"; break;
            case 2: btn.Text = "Draw sidewalk with DstOver"; break;
            case 3: btn.Text = "Draw brick wall with DstOver"; break;
            case 4: btn.Text = "Reset"; break;
        }

        canvasView.InvalidateSurface();
    }
    
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();
        ···
    }
}

프로그램을 처음 실행 하면 아무 것 제외 하 고 표시 된 Button:When the program first runs, nothing is visible except the Button:

Brick-Wall 혼합 단계 0Brick-Wall Compositing Step 0

키를 눌러 합니다 Button 하면 한 번 step 1로 증가 하며 PaintSurface 처리기는 이제 표시 SeatedMonkey.jpg:Pressing the Button once causes step to increment to 1, and the PaintSurface handler now displays SeatedMonkey.jpg:

public partial class BrickWallCompositingPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        float x = (info.Width - monkeyBitmap.Width) / 2;
        float y = info.Height - monkeyBitmap.Height;

        // Draw monkey bitmap
        if (step >= 1)
        {
            canvas.DrawBitmap(monkeyBitmap, x, y);
        }
        ···
    }
}

방법이 없는 SKPaint 개체 이므로 blend 모드 없음.There's no SKPaint object and hence no blend mode. 비트맵 화면 맨 아래에 나타납니다.The bitmap appears at the bottom of the screen:

Brick-Wall 합치기 1 단계Brick-Wall Compositing Step 1

키를 눌러 합니다 Button 다시 및 step 2로 증가 합니다.Press the Button again and step increments to 2. 이 중요 한 단계를 표시 합니다 SeatedMonkeyMatte.png 파일:This is the crucial step of displaying the SeatedMonkeyMatte.png file:

public partial class BrickWallCompositingPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        // Draw matte to exclude monkey's surroundings
        if (step >= 2)
        {
            using (SKPaint paint = new SKPaint())
            {
                paint.BlendMode = SKBlendMode.DstIn;
                canvas.DrawBitmap(matteBitmap, x, y, paint);
            }
        }
        ···
    }
}

Blend 모드가 SKBlendMode.DstIn, 즉, 대상은 원본의 불투명 영역에 해당 하는 영역에서 유지 됩니다.The blend mode is SKBlendMode.DstIn, which means that the destination will be preserved in areas corresponding to non-transparent areas of the source. 원래 비트맵에 해당 하는 대상 사각형의 나머지 부분 투명해 집니다.The remainder of the destination rectangle corresponding to the original bitmap becomes transparent:

Brick-Wall 합치기 2 단계Brick-Wall Compositing Step 2

배경 제거 되었습니다.The background has been removed.

다음 단계는 monkey 하나 더 있는데요는 인도 유사한 사각형을 그리려면입니다.The next step is to draw a rectangle that resembles a sidewalk that the monkey is sitting on. 이 인도의 모양을 기반으로 두 셰이더 조합: 단색 셰이더 및 Perlin 노이즈 셰이더:The appearance of this sidewalk is based on a composition of two shaders: a solid color shader and a Perlin noise shader:

public partial class BrickWallCompositingPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        const float sidewalkHeight = 80;
        SKRect rect = new SKRect(info.Rect.Left, info.Rect.Bottom - sidewalkHeight,
                                 info.Rect.Right, info.Rect.Bottom);

        // Draw gravel sidewalk for monkey to sit on
        if (step >= 3)
        {
            using (SKPaint paint = new SKPaint())
            {
                paint.Shader = SKShader.CreateCompose(
                                    SKShader.CreateColor(SKColors.SandyBrown),
                                    SKShader.CreatePerlinNoiseTurbulence(0.1f, 0.3f, 1, 9));

                paint.BlendMode = SKBlendMode.DstOver;
                canvas.DrawRect(rect, paint);
            }
        }
        ···
    }
}

이 인도 monkey 뒤 야, blend 모드 이므로 DstOver합니다.Because this sidewalk must go behind the monkey, the blend mode is DstOver. 대상만 있는 배경은 투명 하 게 표시 됩니다.The destination appears only where the background is transparent:

Brick-Wall 합치기 3 단계Brick-Wall Compositing Step 3

마지막 단계는 brick 벽을 추가 합니다.The final step is adding a brick wall. 정적 속성으로 사용 가능한 brick-wall 비트맵 타일 사용 BrickWallTileAlgorithmicBrickWallPage 클래스입니다.The program uses the brick-wall bitmap tile available as the static property BrickWallTile in the AlgorithmicBrickWallPage class. 좌표에 추가 되는 SKShader.CreateBitmap 아래쪽 행에는 전체 타일 있도록 타일을 이동할 호출:A translation transform is added to the SKShader.CreateBitmap call to shift the tiles so that the bottom row is a full tile:

public partial class BrickWallCompositingPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        // Draw bitmap tiled brick wall behind monkey
        if (step >= 4)
        {
            using (SKPaint paint = new SKPaint())
            {
                SKBitmap bitmap = AlgorithmicBrickWallPage.BrickWallTile;
                float yAdjust = (info.Height - sidewalkHeight) % bitmap.Height;

                paint.Shader = SKShader.CreateBitmap(bitmap,
                                                     SKShaderTileMode.Repeat,
                                                     SKShaderTileMode.Repeat,
                                                     SKMatrix.MakeTranslation(0, yAdjust));
                paint.BlendMode = SKBlendMode.DstOver;
                canvas.DrawRect(info.Rect, paint);
            }
        }
    }
}

편의 위해 합니다 DrawRect 호출 전체 캔버스를 통해이 셰이더를 표시 하지만 DstOver 모드만 여전히 투명 한 캔버스 영역에는 출력 제한:For convenience, the DrawRect call displays this shader over the entire canvas, but the DstOver mode limits the output to only the area of the canvas that is still transparent:

Brick-Wall 합치기 4 단계Brick-Wall Compositing Step 4

물론이 장면을 작성 하는 다른 방법은 있습니다.Obviously there are other ways to compose this scene. 이 백그라운드에서 시작 및 앞으로 진행 되 고 빌드될 수 있습니다.It could be built up starting at the background and progressing to the foreground. 하지만 혼합 모드를 사용 하 여 좀 더 유연 합니다.But using the blend modes gives you more flexibility. 특히 매트를 사용 하면 구성 된 장면에서 제외할 비트맵의 배경색입니다.In particular, the use of the matte allows the background of a bitmap to be excluded from the composed scene.

문서에서 설명한 대로 경로 및 지역 클리핑SKCanvas 클리핑에 해당 하는 클래스를 정의 합니다 ClipRect , ClipPath , 및 ClipRegion 메서드.As you learned in the article Clipping with Paths and Regions, the SKCanvas class defines three types of clipping, corresponding to the ClipRect, ClipPath, and ClipRegion methods. Porter 임신 blend 모드는 다른 형식의 이미지를 그릴 수 있는, 비트맵을 포함 하 여 아무 것도 제한 수 있는 클리핑을 추가 합니다.The Porter-Duff blend modes add another type of clipping, which allows restricting an image to anything that you can draw, including bitmaps. 에 사용 되는 매트 Brick-Wall 합치기 기본적으로 클리핑 영역을 정의 합니다.The matte used in Brick-Wall Compositing essentially defines a clipping area.

그라데이션 투명도 및 전환Gradient transparency and transitions

Porter 임신 예가이 문서의 모든 것을 의미 했습니다 불투명 한 픽셀 및 투명 한 픽셀을 부분적으로 투명 한 픽셀의로 구성 된 이미지는 앞에 표시 된 모드를 혼합 됩니다.The examples of the Porter-Duff blend modes shown earlier in this article have all involved images that consisted of opaque pixels and transparent pixels, but not partially transparent pixels. Blend 모드 함수 픽셀 들도 정의 됩니다.The blend-mode functions are defined for those pixels as well. 다음 표는는 Skia 있는 표기법을 사용 하는 좀 더 공식적인 Porter 임신 blend 모드 정의 SkBlendMode 참조합니다.The following table is a more formal definition of the Porter-Duff blend modes that uses notation found in the Skia SkBlendMode Reference. (때문 SkBlendMode 참조 Skia 참조는 c + + 구문을 사용 합니다.)(Because SkBlendMode Reference is a Skia reference, C++ syntax is used.)

개념적으로 각 픽셀의 빨간색, 녹색, 파랑 및 알파 구성 요소 범위에서 부동 소수점 숫자 0에서 1 바이트에서 변환 됩니다.Conceptually, the red, green, blue, and alpha components of each pixel are converted from bytes to floating-point numbers in the range of 0 to 1. 알파 채널의 0은 완전히 투명 하 고 1은 완전히 불투명For the alpha channel, 0 is fully transparent and 1 is fully opaque

아래 표에 표기법은 다음 약어를 사용 합니다.The notation in the table below uses the following abbreviations:

  • Da 대상의 알파 채널Da is the destination alpha channel
  • Dc 대상인 RGB 색Dc is the destination RGB color
  • Sa 는 원본 알파 채널Sa is the source alpha channel
  • Sc 원본인 RGB 색Sc is the source RGB color

RGB 색은 알파 값이 미리 곱해집니다.The RGB colors are pre-multiplied by the alpha value. 예를 들어 경우 Sc 순수한 빨간색을 나타내는 있지만 Sa 가 0x80, RGB 색 (0x80, 0, 0) 합니다.For example, if Sc represents pure red but Sa is 0x80, then the RGB color is (0x80, 0, 0). 하는 경우 Sa 가 0 이면 모든 RGB 구성 요소는 0입니다.If Sa is 0, then all the RGB components are also zero.

결과 알파 채널 및 쉼표로 구분 된 RGB 색을 사용 하 여는 대괄호 안에 표시 됩니다. [알파, 색상] 합니다.The result is shown in brackets with the alpha channel and the RGB color separated by a comma: [alpha, color]. 색에 대 한 계산 빨강, 녹색 및 파랑 구성 요소에 대해 개별적으로 수행 됩니다.For the color, the calculation is performed separately for the red, green, and blue components:

모드Mode 작업Operation
Clear [0, 0][0, 0]
Src [Sa를 Sc][Sa, Sc]
Dst [Da Dc][Da, Dc]
SrcOver [Sa + Da· (1 일 – Sa) Sc + Dc· (1-Sa)[Sa + Da·(1 – Sa), Sc + Dc·(1 – Sa)
DstOver [Da + Sa· (1-Da) Dc + Sc· (1-Da)[Da + Sa·(1 – Da), Dc + Sc·(1 – Da)
SrcIn [Sa· Da Sc· Da][Sa·Da, Sc·Da]
DstIn [Da· Sa, Dc· Sa][Da·Sa, Dc·Sa]
SrcOut [Sa· (1-Da) Sc· (1-Da)][Sa·(1 – Da), Sc·(1 – Da)]
DstOut [Da· (1 일 – Sa) Dc· (1 일 – Sa)][Da·(1 – Sa), Dc·(1 – Sa)]
SrcATop [Da Sc· Da + Dc· (1 일 – Sa)][Da, Sc·Da + Dc·(1 – Sa)]
DstATop [Sa Dc· Sa + Sc· (1-Da)][Sa, Dc·Sa + Sc·(1 – Da)]
Xor [Sa + Da – 2· Sa· Da Sc· (1-Da) + Dc· (1 일 – Sa)][Sa + Da – 2·Sa·Da, Sc·(1 – Da) + Dc·(1 – Sa)]
Plus [Sa + Da, Sc + Dc][Sa + Da, Sc + Dc]
Modulate [Sa· Da Sc· Dc][Sa·Da, Sc·Dc]

이러한 작업은 분석할 때 쉽게 Da 하 고 Sa 는 0 또는 1입니다.These operations are easier to analyze when Da and Sa are either 0 or 1. 기본값에 대 한 예를 들어 SrcOver 모드 경우 Sa 0 이면 Sc 가 0이 고, 결과 이기도 [Da, Dc], 대상 알파 및 색입니다.For example, for the default SrcOver mode, if Sa is 0, then Sc is also 0, and the result is [Da, Dc], the destination alpha and color. 하는 경우 Sa 가 1 이면 결과 [Sa, Sc], 원본 알파 및 색, 또는 [1, Sc] 합니다.If Sa is 1, then the result is [Sa, Sc], the source alpha and color, or [1, Sc].

합니다 PlusModulate 모드는 다른 기존과 약간 다를 새 색의 원본 및 대상 조합에서 발생할 수 있습니다.The Plus and Modulate modes are a little different from the others in that new colors can result from the combination of the source and the destination. Plus 바이트 구성 요소 또는 부동 소수점 구성 요소를 사용 하 여 모드를 해석할 수 있습니다.The Plus mode can be interpreted either with byte components or floating-point components. Porter 임신 그리드 대상 색이 이전에 표시 되는 페이지 (0xC0, 0x80, 0x00) 소스 색 이며 (0x00, 0x80, 0xC0).In the Porter-Duff Grid page shown earlier, the destination color is (0xC0, 0x80, 0x00) and the source color is (0x00, 0x80, 0xC0). 각 쌍 구성 요소에 추가 되지만 합계 0xFF에서 범위로 제한 됩니다.Each pair of components is added but the sum is clamped at 0xFF. 결과 색인 (0xC0, 0xFF 0xC0) 합니다.The result is the color (0xC0, 0xFF, 0xC0). 교차 부분에서 표시 된 색입니다.That's the color shown in the intersection.

에 대 한는 Modulate 모드 RGB 값에 부동 소수점 변환 해야 합니다.For the Modulate mode, the RGB values must be converted to floating-point. 대상 색이 (0.75, 0.5, 0) 소스 이며 (0, 0.5, 0.75) 합니다.The destination color is (0.75, 0.5, 0) and the source is (0, 0.5, 0.75). RGB 구성 요소는 각 함께 곱하고 결과가 (0, 0.25, 0) 합니다.The RGB components are each multiplied together, and the result is (0, 0.25, 0). 교차 부분에서 표시 된 색상입니다 합니다 Porter 임신 표 이 모드에 대 한 페이지.That's the color shown in the intersection in the Porter-Duff Grid page for this mode.

합니다 Porter 임신 투명도 페이지를 사용 하면 Porter 임신 blend 모드 부분적으로 투명 한 그래픽 개체에 대해 작동 하는 방법을 검사할 수 있습니다.The Porter-Duff Transparency page allows you to examine how the Porter-Duff blend modes operate on graphical objects that are partially transparent. XAML 파일에 포함 된 Picker Porter 임신 모드를 사용 하 여:The XAML file includes a Picker with the Porter-Duff modes:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp;assembly=SkiaSharp"
             xmlns:skiaviews="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.PorterDuffTransparencyPage"
             Title="Porter-Duff Transparency">

    <StackLayout>
        <skiaviews:SKCanvasView x:Name="canvasView"
                                VerticalOptions="FillAndExpand"
                                PaintSurface="OnCanvasViewPaintSurface" />

        <Picker x:Name="blendModePicker"
                Title="Blend Mode"
                Margin="10"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKBlendMode}">
                    <x:Static Member="skia:SKBlendMode.Clear" />
                    <x:Static Member="skia:SKBlendMode.Src" />
                    <x:Static Member="skia:SKBlendMode.Dst" />
                    <x:Static Member="skia:SKBlendMode.SrcOver" />
                    <x:Static Member="skia:SKBlendMode.DstOver" />
                    <x:Static Member="skia:SKBlendMode.SrcIn" />
                    <x:Static Member="skia:SKBlendMode.DstIn" />
                    <x:Static Member="skia:SKBlendMode.SrcOut" />
                    <x:Static Member="skia:SKBlendMode.DstOut" />
                    <x:Static Member="skia:SKBlendMode.SrcATop" />
                    <x:Static Member="skia:SKBlendMode.DstATop" />
                    <x:Static Member="skia:SKBlendMode.Xor" />
                    <x:Static Member="skia:SKBlendMode.Plus" />
                    <x:Static Member="skia:SKBlendMode.Modulate" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                3
            </Picker.SelectedIndex>
        </Picker>
    </StackLayout>
</ContentPage>

코드 숨김 파일 선형 그라데이션을 사용 하 여 동일한 크기의 사각형 두 개를 채웁니다.The code-behind file fills two rectangles of the same size using a linear gradient. 대상 그라데이션 왼쪽 아래 오른쪽 위에서 것입니다.The destination gradient is from the upper right to the lower left. 오른쪽 위 모서리에서 갈색 하지만 다음 중심 쪽으로 투명으로 페이드 시작 되며 왼쪽 아래 모서리에서 이루어집니다.It is brownish in the upper-right corner but then towards the center begins fading to transparent, and is transparent in the lower-left corner.

소스 사각형 왼쪽 위에서 오른쪽 아래로 그라데이션을 있습니다.The source rectangle has a gradient from the upper left to the lower right. 왼쪽 위 모퉁이 파랑 추가 하지만 다시 투명으로 흐려 지 이며 오른쪽 아래 모서리에 투명 합니다.The upper-left corner is bluish but again fades to transparent, and is transparent in the lower-right corner.

public partial class PorterDuffTransparencyPage : ContentPage
{
    public PorterDuffTransparencyPage()
    {
        InitializeComponent();
    }

    void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Make square display rectangle smaller than canvas
        float size = 0.9f * Math.Min(info.Width, info.Height);
        float x = (info.Width - size) / 2;
        float y = (info.Height - size) / 2;
        SKRect rect = new SKRect(x, y, x + size, y + size);

        using (SKPaint paint = new SKPaint())
        {
            // Draw destination
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(rect.Right, rect.Top),
                                new SKPoint(rect.Left, rect.Bottom),
                                new SKColor[] { new SKColor(0xC0, 0x80, 0x00),
                                                new SKColor(0xC0, 0x80, 0x00, 0) },
                                new float[] { 0.4f, 0.6f },
                                SKShaderTileMode.Clamp);

            canvas.DrawRect(rect, paint);

            // Draw source
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(rect.Left, rect.Top),
                                new SKPoint(rect.Right, rect.Bottom),
                                new SKColor[] { new SKColor(0x00, 0x80, 0xC0), 
                                                new SKColor(0x00, 0x80, 0xC0, 0) },
                                new float[] { 0.4f, 0.6f },
                                SKShaderTileMode.Clamp);

            // Get the blend mode from the picker
            paint.BlendMode = blendModePicker.SelectedIndex == -1 ? 0 :
                                    (SKBlendMode)blendModePicker.SelectedItem;

            canvas.DrawRect(rect, paint);

            // Stroke surrounding rectangle
            paint.Shader = null;
            paint.BlendMode = SKBlendMode.SrcOver;
            paint.Style = SKPaintStyle.Stroke;
            paint.Color = SKColors.Black;
            paint.StrokeWidth = 3;
            canvas.DrawRect(rect, paint);
        }
    }
}

이 프로그램 이외의 비트맵 그래픽 개체를 사용 하 여 Porter 임신 blend 모드를 사용할 수 있도록 하는 방법을 보여 줍니다.This program demonstrates that the Porter-Duff blend modes can be used with graphic objects other than bitmaps. 그러나 소스는 투명 한 영역을 포함 해야 합니다.However, the source must include a transparent area. 여기서 그라데이션의 사각형을 채우는 하지만 그라데이션의 부분은 투명 때문입니다.This is the case here because the gradient fills the rectangle, but part of the gradient is transparent.

세 가지 예는 다음과 같습니다.Here are three examples:

Porter 임신 투명도Porter-Duff Transparency

원본과 대상의 구성은 원래 Porter 임신 255 페이지에 표시 된 다이어그램 매우 비슷합니다 합치기 디지털 이미지 것을 보여 줍니다 문서 있지만이 페이지는 혼합 모드는 투명도 부분 영역에 대 한 잘 작동 합니다.The configuration of the destination and source is very similar to the diagrams shown in page 255 of the original Porter-Duff Compositing Digital Images paper, but this page demonstrates that the blend modes are well-behaved for areas of partial transparency.

몇 가지 다양 한 효과 대 한 투명 한 그라데이션에 사용할 수 있습니다.You can use transparent gradients for some different effects. 설명한 기술을 비슷합니다는 한 가지 방법은 마스킹하는 마스킹에 대 한 방사형 그라데이션을 섹션의 SkiaSharp 순환 그라데이션 페이지합니다.One possibility is masking, which is similar to the technique shown in the Radial gradients for masking section of the SkiaSharp circular gradients page. 많은 합니다 합치기 마스크 페이지는 이전 프로그램와 유사 합니다.Much of the Compositing Mask page is similar to that earlier program. 비트맵 리소스를 로드 하 고 표시 하는 사각형을 결정 합니다.It loads a bitmap resource and determines a rectangle in which to display it. 방사형 그라데이션 미리 결정된 된 중심 및 반지름에 따라 만들어집니다.A radial gradient is created based on a pre-determined center and radius:

public class CompositingMaskPage : ContentPage
{
    SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
        typeof(CompositingMaskPage),
        "SkiaSharpFormsDemos.Media.MountainClimbers.jpg");

    static readonly SKPoint CENTER = new SKPoint(180, 300);
    static readonly float RADIUS = 120;

    public CompositingMaskPage ()
    {
        Title = "Compositing Mask";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Find rectangle to display bitmap
        float scale = Math.Min((float)info.Width / bitmap.Width,
                               (float)info.Height / bitmap.Height);

        SKRect rect = SKRect.Create(scale * bitmap.Width, scale * bitmap.Height);

        float x = (info.Width - rect.Width) / 2;
        float y = (info.Height - rect.Height) / 2;
        rect.Offset(x, y);

        // Display bitmap in rectangle
        canvas.DrawBitmap(bitmap, rect);

        // Adjust center and radius for scaled and offset bitmap
        SKPoint center = new SKPoint(scale * CENTER.X + x,
                                        scale * CENTER.Y + y);
        float radius = scale * RADIUS;

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateRadialGradient(
                                center,
                                radius,
                                new SKColor[] { SKColors.Black,
                                                SKColors.Transparent },
                                new float[] { 0.6f, 1 },
                                SKShaderTileMode.Clamp);

            paint.BlendMode = SKBlendMode.DstIn;

            // Display rectangle using that gradient and blend mode
            canvas.DrawRect(rect, paint);
        }

        canvas.DrawColor(SKColors.Pink, SKBlendMode.DstOver);
    }
}

이 프로그램을 사용 하 여 차이가 그라데이션의 가운데에 검은색을 사용 하 여 시작 하 고 투명도 사용 하 여 종료 합니다.The difference with this program is that the gradient begins with black in the center and ends with transparency. blend 모드를 사용 하 여 비트맵에 표시 됩니다 DstIn를 투명 하 게 되지 않는 원본 영역에만 대상을 보여 줍니다.It is displayed on the bitmap with a blend mode of DstIn, which shows the destination only in the areas of the source that are not transparent.

뒤를 DrawRect 호출 캔버스의 전체 화면 방사형 그라데이션 정의한 원 제외 하 고 투명 하 게 됩니다.After the DrawRect call, the entire surface of the canvas is transparent except for the circle defined by the radial gradient. 마지막 호출 됩니다.A final call is made:

canvas.DrawColor(SKColors.Pink, SKBlendMode.DstOver);

캔버스의 모든 투명 한 영역에 분홍색이 지정 됩니다.All the transparent areas of the canvas are colored pink:

합성 마스크Compositing Mask

또한 한 이미지의 전환에 대 한 Porter 임신 모드 및 부분적으로 투명 한 그라데이션을 사용할 수 있습니다.You can also use Porter-Duff modes and partially transparent gradients for transitions from one image to another. 그라데이션 전환 페이지에는 Slider 0에서 1로의 전환에 진행률 수준을 나타낼 및 Picker 원하는 전환의 유형을 선택할 수:The Gradient Transitions page includes a Slider to indicate a progress level in the transition from 0 to 1, and a Picker to choose the type of transition you want:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.GradientTransitionsPage"
             Title="Gradient Transitions">
    
    <StackLayout>
        <skia:SKCanvasView x:Name="canvasView"
                           VerticalOptions="FillAndExpand"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <Slider x:Name="progressSlider"
                Margin="10, 0"
                ValueChanged="OnSliderValueChanged" />

        <Label Text="{Binding Source={x:Reference progressSlider},
                              Path=Value,
                              StringFormat='Progress = {0:F2}'}"
               HorizontalTextAlignment="Center" />

        <Picker x:Name="transitionPicker" 
                Title="Transition" 
                Margin="10"
                SelectedIndexChanged="OnPickerSelectedIndexChanged" />
        
    </StackLayout>
</ContentPage>

코드 숨김 파일 전환을 보여 주기 위해 두 비트맵 리소스를 로드 합니다.The code-behind file loads two bitmap resources to demonstrate the transition. 이들은에 사용 된 동일한 두 개의 이미지를 비트맵 주만에 이 문서의 앞부분에서 페이지입니다.These are the same two images used in the Bitmap Dissolve page earlier in this article. 또한 코드를 세 가지 유형의 그라데이션에 해당 하는 세 멤버가 포함 된 열거형을 정의 — 선형 이며, 방사형 및 스윕 합니다.The code also defines an enumeration with three members corresponding to three types of gradients — linear, radial, and sweep. 이러한 값이 로드 되는 Picker:These values are loaded into the Picker:

public partial class GradientTransitionsPage : ContentPage
{
    SKBitmap bitmap1 = BitmapExtensions.LoadBitmapResource(
        typeof(GradientTransitionsPage),
        "SkiaSharpFormsDemos.Media.SeatedMonkey.jpg");

    SKBitmap bitmap2 = BitmapExtensions.LoadBitmapResource(
        typeof(GradientTransitionsPage),
        "SkiaSharpFormsDemos.Media.FacePalm.jpg");

    enum TransitionMode
    {
        Linear,
        Radial,
        Sweep
    };

    public GradientTransitionsPage ()
    {
        InitializeComponent ();

        foreach (TransitionMode mode in Enum.GetValues(typeof(TransitionMode)))
        {
            transitionPicker.Items.Add(mode.ToString());
        }

        transitionPicker.SelectedIndex = 0;
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }
    ···
}

코드 숨김 파일을 만드는 세 가지 SKPaint 개체입니다.The code-behind file creates three SKPaint objects. paint0 개체 blend 모드를 사용 하지 않습니다.The paint0 object doesn't use a blend mode. 이 그리기 개체에 표시 된 대로 투명 검정으로 이동 하는 그라데이션 사용 하 여 사각형을 그리는 데 사용 되는 colors 배열입니다.This paint object is used to draw a rectangle with a gradient that goes from black to transparent as indicated in the colors array. 합니다 positions 의 위치를 기반으로 하는 배열은 Slider, 되지만 어느 정도 조정 합니다.The positions array is based on the position of the Slider, but adjusted somewhat. 경우는 Slider 해당 최소값 또는 최대값에 progress 값은 0 또는 1 및 두 비트맵 중 완벽 하 게 표시 되어야 합니다.If the Slider is at its minimum or maximum, the progress values are 0 or 1, and one of the two bitmaps should be fully visible. positions 배열 적절 하 게 설정 해야 해당 값에 대 한 합니다.The positions array must be set accordingly for those values.

경우는 progress 값이 0 인 경우 positions 배열-0.1 및 0 값을 포함 합니다.If the progress value is 0, then the positions array contains the values -0.1 and 0. SkiaSharp는 그렇지 않으면 해당 첫 번째 값을 0에만 black 그라데이션의 즉 0과 투명을 조정 합니다.SkiaSharp will adjust that first value to be equal to 0, which means that the gradient is black only at 0 and transparent otherwise. progress 0.5이 하 이면 배열 0.45 및 0.55 값을 포함 합니다.When progress is 0.5, then the array contains the values 0.45 and 0.55. 그라데이션의는 0.45, 0에서 검은색을 투명 하 게 전환 되 고 1 0.55에서 완전히 투명 하다.The gradient is black from 0 to 0.45, then transitions to transparent, and is fully transparent from 0.55 to 1. progress 가 1 이면는 positions 배열이 1 및 0에서 1로 black 그라데이션의 1.1입니다.When progress is 1, the positions array is 1 and 1.1, which means the gradient is black from 0 to 1.

합니다 colors 하 고 position 배열 모두의 세 가지 방법에서 사용 되 SKShader 그라데이션 만들기는 합니다.The colors and position arrays are both used in the three methods of SKShader that create a gradient. 에 따라 만들어집니다 이러한 셰이더 중 전용 된 Picker 선택:Only one of these shaders is created based on the Picker selection:

public partial class GradientTransitionsPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Assume both bitmaps are square for display rectangle
        float size = Math.Min(info.Width, info.Height);
        SKRect rect = SKRect.Create(size, size);
        float x = (info.Width - size) / 2;
        float y = (info.Height - size) / 2;
        rect.Offset(x, y);

        using (SKPaint paint0 = new SKPaint())
        using (SKPaint paint1 = new SKPaint())
        using (SKPaint paint2 = new SKPaint())
        {
            SKColor[] colors = new SKColor[] { SKColors.Black,
                                               SKColors.Transparent };

            float progress = (float)progressSlider.Value;

            float[] positions = new float[]{ 1.1f * progress - 0.1f,
                                             1.1f * progress };

            switch ((TransitionMode)transitionPicker.SelectedIndex)
            {
                case TransitionMode.Linear:
                    paint0.Shader = SKShader.CreateLinearGradient(
                                        new SKPoint(rect.Left, 0),
                                        new SKPoint(rect.Right, 0),
                                        colors,
                                        positions,
                                        SKShaderTileMode.Clamp);
                    break;

                case TransitionMode.Radial:
                    paint0.Shader = SKShader.CreateRadialGradient(
                                        new SKPoint(rect.MidX, rect.MidY),
                                        (float)Math.Sqrt(Math.Pow(rect.Width / 2, 2) +
                                                         Math.Pow(rect.Height / 2, 2)),
                                        colors,
                                        positions,
                                        SKShaderTileMode.Clamp);
                    break;

                case TransitionMode.Sweep:
                    paint0.Shader = SKShader.CreateSweepGradient(
                                        new SKPoint(rect.MidX, rect.MidY),
                                        colors,
                                        positions);
                    break;
            }

            canvas.DrawRect(rect, paint0);

            paint1.BlendMode = SKBlendMode.SrcOut;
            canvas.DrawBitmap(bitmap1, rect, paint1);

            paint2.BlendMode = SKBlendMode.DstOver;
            canvas.DrawBitmap(bitmap2, rect, paint2);
        }
    }
}

기울기는 blend 모드 없이 사각형에 표시 됩니다.That gradient is displayed in the rectangle without a blend mode. 그 후 DrawRect 호출을 캔버스에 투명 검정에서 그라데이션 단순히 포함 되어 있습니다.After that DrawRect call, the canvas simply contains a gradient from black to transparent. 검정 양이 이상을 사용 하 여 증가 Slider 값입니다.The amount of black increases with higher Slider values.

마지막 4 개 문에서 PaintSurface 처리기 두 비트맵 표시 됩니다.In the final four statements of the PaintSurface handler, the two bitmaps are displayed. SrcOut blend 모드 첫 번째 비트맵의 배경 투명 영역에만 표시 되는 것을 의미 합니다.The SrcOut blend mode means that the first bitmap is displayed only in the transparent areas of the background. DstOver 모드 두 번째 비트맵에 대 한 두 번째 비트맵 첫 번째 비트맵에 표시 되지 않습니다 해당 영역에만 표시 되는 것을 의미 합니다.The DstOver mode for the second bitmap means that the second bitmap is displayed only in those areas where the first bitmap is not displayed.

다음 스크린샷에서 50% 표시 지점에서 각각 세 개의 다른 전환 형식을 보여 줍니다.The following screenshots show the three different transitions types, each at the 50% mark:

그라데이션 전환을Gradient Transitions