Aracılığıyla paylaş


SkiaSharp bit eşlemleri oluşturma ve çizme

Bir uygulamanın Web'den, uygulama kaynaklarından ve kullanıcının fotoğraf kitaplığından bit eşlemleri nasıl yükleyebildiğini gördünüz. Uygulamanızda yeni bit eşlemler oluşturmak da mümkündür. En basit yaklaşım, oluşturucularından SKBitmapbirini içerir:

SKBitmap bitmap = new SKBitmap(width, height);

width ve height parametreleri tamsayılardır ve bit eşlemin piksel boyutlarını belirtir. Bu oluşturucu, piksel başına dört baytlık tam renkli bir bit eşlem oluşturur: kırmızı, yeşil, mavi ve alfa (opaklık) bileşenleri için her biri bir bayt.

Yeni bir bit eşlem oluşturduktan sonra bit eşlem yüzeyinde bir şey almanız gerekir. Bunu genellikle iki yoldan biriyle yaparsınız:

  • Standart Canvas çizim yöntemlerini kullanarak bit eşlem üzerinde çizim.
  • Piksel bitlerine doğrudan erişin.

Bu makalede ilk yaklaşım gösterilmektedir:

Çizim Örneği

İkinci yaklaşım, SkiaSharp Bit Eşlem Piksellerine Erişme makalesinde ele alınmalıdır.

Bit eşlem üzerinde çizim

Bit eşlem yüzeyinde çizim, video ekranındaki çizimle aynıdır. Video ekranında çizim yapmak için olay bağımsız değişkenlerinden PaintSurface bir SKCanvas nesne alırsınız. Bit eşlem üzerinde çizim yapmak için oluşturucuyu SKCanvas kullanarak bir SKCanvas nesne oluşturursunuz:

SKCanvas canvas = new SKCanvas(bitmap);

Bit eşlem üzerinde çizmeyi bitirdiğinizde, nesneyi atabilirsiniz SKCanvas . Bu nedenle, SKCanvas oluşturucu genellikle bir using deyiminde çağrılır:

using (SKCanvas canvas = new SKCanvas(bitmap))
{
    ··· // call drawing function
}

Bit eşlem daha sonra görüntülenebilir. Daha sonra, program aynı bit eşlemi temel alan yeni SKCanvas bir nesne oluşturabilir ve üzerinde biraz daha çizim yapabilir.

Örnek uygulamadaki Hello Bit Eşlem sayfası bit eşlem üzerine "Hello, Bit Eşlem!" metnini yazar ve bu bit eşlemi birden çok kez görüntüler.

oluşturucu, HelloBitmapPage metin görüntülemek için bir SKPaint nesne oluşturarak başlar. Bir metin dizesinin boyutlarını belirler ve bu boyutlara sahip bir bit eşlem oluşturur. Ardından bu bit eşlemi temel alan bir SKCanvas nesne oluşturur, öğesini çağırır Clearve ardından öğesini çağırır DrawText. Yeni oluşturulan bit eşlem rastgele veriler içerebileceğinden yeni bir bit eşlem ile çağırmak Clear her zaman iyi bir fikirdir.

Oluşturucu bit eşlemi görüntülemek için bir SKCanvasView nesne oluşturarak son bulur:

public partial class HelloBitmapPage : ContentPage
{
    const string TEXT = "Hello, Bitmap!";
    SKBitmap helloBitmap;

    public HelloBitmapPage()
    {
        Title = TEXT;

        // Create bitmap and draw on it
        using (SKPaint textPaint = new SKPaint { TextSize = 48 })
        {
            SKRect bounds = new SKRect();
            textPaint.MeasureText(TEXT, ref bounds);

            helloBitmap = new SKBitmap((int)bounds.Right,
                                       (int)bounds.Height);

            using (SKCanvas bitmapCanvas = new SKCanvas(helloBitmap))
            {
                bitmapCanvas.Clear();
                bitmapCanvas.DrawText(TEXT, 0, -bounds.Top, textPaint);
            }
        }

        // Create SKCanvasView to view result
        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(SKColors.Aqua);

        for (float y = 0; y < info.Height; y += helloBitmap.Height)
            for (float x = 0; x < info.Width; x += helloBitmap.Width)
            {
                canvas.DrawBitmap(helloBitmap, x, y);
            }
    }
}

İşleyici, PaintSurface bit eşlemi ekranın satır ve sütunlarında birden çok kez işler. İşleyicideki yöntemin Clear PaintSurface , ekran yüzeyinin SKColors.Aquaarka planını renklendiren bağımsız değişkenine sahip olduğuna dikkat edin:

Merhaba Bit Eşlem!

Su arka planının görünümü, bit eşleminin metin dışında saydam olduğunu gösterir.

Temizleme ve saydamlık

Hello Bit Eşlem sayfasının görüntüsü, programın oluşturduğu bit eşlemin siyah metin dışında saydam olduğunu gösterir. Bu nedenle ekran yüzeyinin su rengi ile gösterilir.

yöntemlerinin Clear SKCanvas belgeleri, bunları şu ifadeyle açıklar: "Tuvalin geçerli klibindeki tüm pikselleri değiştirir." "Değiştirir" sözcüğünün kullanılması, şu yöntemlerin önemli bir özelliğini ortaya koyuyor: Mevcut ekran yüzeyine bir şey eklemenin SKCanvas tüm çizim yöntemleri. Clear Yöntemler, zaten orada bulunanların yerini alır.

Clear iki farklı sürümde var:

  • Clear parametresiyle SKColor yöntemi, ekran yüzeyinin piksellerini bu rengin pikselleriyle değiştirir.

  • Clear Parametresiz yöntemi, piksellerin yerini, tüm bileşenlerin (kırmızı, yeşil, mavi ve alfa) sıfır olarak ayarlandığı renk olan renkle SKColors.Empty değiştirir. Bu renk bazen "saydam siyah" olarak adlandırılır.

Yeni bit eşlem üzerinde bağımsız değişken olmadan çağrılması Clear , bit eşlemlerin tamamının tamamen saydam olması için başlatılır. Bit eşlem üzerinde daha sonra çizilen her şey genellikle opak veya kısmen opak olur.

Deneyebileceğiniz bir şey var: Hello Bit Eşlem sayfasında, öğesine uygulanan bitmapCanvas yöntemi şu yöntemle değiştirinClear:

bitmapCanvas.Clear(new SKColor(255, 0, 0, 128));

Oluşturucu parametrelerinin SKColor sırası kırmızı, yeşil, mavi ve alfadır ve her değer 0 ile 255 arasında değişebilir. 0 alfa değerinin saydam, alfa değerinin ise 255 olduğunu unutmayın.

Değer (255, 0, 0, 128), bit eşlem piksellerini %50 opaklığa sahip kırmızı piksellere temizler. Bu, bit eşlem arka planının yarı saydam olduğu anlamına gelir. Bit eşleminin yarı saydam kırmızı arka planı, gri bir arka plan oluşturmak için ekran yüzeyinin su arka planıyla birleştirilir.

Başlatıcıya aşağıdaki atamayı ekleyerek metnin rengini saydam siyah olarak ayarlamayı SKPaint deneyin:

Color = new SKColor(0, 0, 0, 0)

Bu saydam metnin bit eşlemin tamamen saydam alanlarını oluşturacağını ve bu alanlar aracılığıyla ekran yüzeyinin su arka planını göreceğinizi düşünebilirsiniz. Ama öyle değil. Metin, bit eşlem üzerinde bulunanın üzerine çizilir. Saydam metin hiç görünmez.

Hiçbir Draw yöntem bit eşlemi daha saydam hale getirmez. Sadece Clear bunu yapabilir.

Bit eşlem renk türleri

En SKBitmap basit oluşturucu, bit eşlem için bir tamsayı piksel genişliği ve yüksekliği belirtmenize olanak tanır. Diğer SKBitmap oluşturucular daha karmaşıktır. Bu oluşturucular iki numaralandırma türünün bağımsız değişkenlerini gerektirir: SKColorType ve SKAlphaType. Diğer oluşturucular, bu bilgileri bir araya ekleyen yapısını kullanır SKImageInfo .

Sabit SKColorType listesi 9 üyeye sahiptir. Bu üyelerin her biri bit eşlem piksellerini depolamanın belirli bir yolunu açıklar:

  • Unknown
  • Alpha8 — her piksel 8 bittir ve tam saydamdan tamamen opaka kadar bir alfa değerini temsil eder
  • Rgb565 — her piksel 16 bit, kırmızı ve mavi için 5 bit ve yeşil için 6 bittir
  • Argb4444 — her piksel 16 bit, alfa, kırmızı, yeşil ve mavi için her biri 4 bittir
  • Rgba8888 — her piksel 32 bit, her biri kırmızı, yeşil, mavi ve alfa için 8 bittir
  • Bgra8888 — her piksel 32 bit, her biri mavi, yeşil, kırmızı ve alfa için 8 bittir
  • Index8 — her piksel 8 bittir ve bir dizinin bir SKColorTable
  • Gray8 — her piksel siyahtan beyaza gri bir gölgeyi temsil eden 8 bittir
  • RgbaF16 — her piksel 64 bittir ve 16 bit kayan nokta biçiminde kırmızı, yeşil, mavi ve alfa

Her pikselin 32 piksel (4 bayt) olduğu iki biçime genellikle tam renkli biçimler adı verilir. Diğer biçimlerin çoğu, video ekranlarının kendilerinin tam renk kullanamadıkları bir zamandan tarihlenir. Sınırlı renkli bit eşlemler bu ekranlar için yeterliydi ve bit eşlemlerin bellekte daha az yer kaplamasına izin verildi.

Bu günlerde programcılar neredeyse her zaman tam renkli bit eşlemler kullanır ve diğer biçimlerle uğraşmaz. Özel durum RgbaF16 , tam renk biçimlerinden bile daha fazla renk çözünürlüğü sağlayan biçimdir. Ancak, bu biçim tıbbi görüntüleme gibi özel amaçlar için kullanılır ve standart tam renkli ekranlarla kullanıldığında çok anlamlı değildir.

Bu makale serisi, üye belirtilmediğinde SKColorType kendisini SKBitmap varsayılan olarak kullanılan renk biçimleriyle kısıtlar. Bu varsayılan biçim, temel alınan platformu temel alır. tarafından Xamarin.Formsdesteklenen platformlar için varsayılan renk türü:

  • Rgba8888 iOS ve Android için
  • Bgra8888 UWP için

Tek fark bellekteki 4 bayt sırasıdır ve bu yalnızca piksel bitlerine doğrudan eriştiğinizde bir sorun haline gelir. SkiaSharp Bit Eşlem Piksellerine Erişme makalesine gelene kadar bu önemli olmayacaktır.

Numaralandırmanın SKAlphaType dört üyesi vardır:

  • Unknown
  • Opaque — bit eşlem saydamlığa sahip değil
  • Premul — renk bileşenleri alfa bileşeniyle önceden çarpılır
  • Unpremul — renk bileşenleri alfa bileşeniyle önceden çarpılmaz

Kırmızı, yeşil, mavi, alfa sırasıyla gösterilen baytlarla %50 saydamlığa sahip 4 baytlık kırmızı bit eşlem pikseli aşağıdadır:

0xFF 0x00 0x00 0x80

Bir görüntü yüzeyinde yarı saydam piksel içeren bir bit eşlem işlendiğinde, her bit eşlem pikselinin renk bileşenleri bu pikselin alfa değeriyle çarpılmalıdır ve ekran yüzeyinin ilgili pikselinin renk bileşenleri alfa değeri çıkarılarak 255 ile çarpılmalıdır. İki piksel daha sonra birleştirilebilir. Bit eşlem piksellerindeki renk bileşenleri alfa değeri tarafından önceden mulitpli edilmişse bit eşlem daha hızlı işlenebilir. Aynı kırmızı piksel aşağıdaki gibi önceden çarpılmış biçimde depolanır:

0x80 0x00 0x00 0x80

Bu performans geliştirmesi, bit eşlemlerin varsayılan olarak bir Premul biçimle oluşturulmasının nedenidirSkiaSharp. Ancak, bunu yalnızca piksel bitlerine erişip bunları değiştirdiğinizde bilmeniz gerekir.

Mevcut bit eşlemler üzerinde çizim

Üzerine çizim yapmak için yeni bir bit eşlem oluşturmak gerekmez. Var olan bir bit eşlem üzerinde de çizim yapabilirsiniz.

Monkey Moustache sayfası, MonkeyFace.png görüntüsünü yüklemek için oluşturucusunu kullanır. Ardından bu bit eşlemi temel alan bir SKCanvas nesne oluşturur ve üzerinde bir bıyık çizmek için ve SKPath nesnelerini kullanırSKPaint:

public partial class MonkeyMoustachePage : ContentPage
{
    SKBitmap monkeyBitmap;

    public MonkeyMoustachePage()
    {
        Title = "Monkey Moustache";

        monkeyBitmap = BitmapExtensions.LoadBitmapResource(GetType(),
            "SkiaSharpFormsDemos.Media.MonkeyFace.png");

        // Create canvas based on bitmap
        using (SKCanvas canvas = new SKCanvas(monkeyBitmap))
        {
            using (SKPaint paint = new SKPaint())
            {
                paint.Style = SKPaintStyle.Stroke;
                paint.Color = SKColors.Black;
                paint.StrokeWidth = 24;
                paint.StrokeCap = SKStrokeCap.Round;

                using (SKPath path = new SKPath())
                {
                    path.MoveTo(380, 390);
                    path.CubicTo(560, 390, 560, 280, 500, 280);

                    path.MoveTo(320, 390);
                    path.CubicTo(140, 390, 140, 280, 200, 280);

                    canvas.DrawPath(path, paint);
                }
            }
        }

        // Create SKCanvasView to view result
        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();
        canvas.DrawBitmap(monkeyBitmap, info.Rect, BitmapStretch.Uniform);
    }
}

Oluşturucu, işleyicisi yalnızca sonucu görüntüleyen bir SKCanvasView PaintSurface oluşturarak sonuçlanır:

Maymun Bıyığı

Bit eşlemleri kopyalama ve değiştirme

Bit eşlem üzerinde çizim yapmak için kullanabileceğiniz yöntemleri SKCanvas şunlardır DrawBitmap: . Bu, bir bit eşlemi başka bir bit eşlem üzerine çizebileceğiniz ve genellikle bir şekilde değiştirebileceğiniz anlamına gelir.

Bit eşlemi değiştirmenin en çok yönlü yolu, SkiaSharp bit eşlem piksellerine erişme makalesinde ele alınan gerçek piksel bitlerine erişmektir. Ancak, piksel bitlerine erişmeyi gerektirmeyen bit eşlemleri değiştirmek için başka birçok teknik vardır.

Örnek uygulamayla birlikte verilen bit eşlem 360 piksel genişliğinde ve 480 piksel yüksekliğindedir:

Dağ Tırmanıcıları

Soldaki maymundan bu fotoğrafı yayımlama izni almadığınız varsayın. Çözümlerden biri, pikselleştirme adlı bir teknik kullanarak maymun yüzünü gizleyebilmektir. Yüzün pikselleri renk bloklarıyla değiştirildiğinden özellikleri çıkaramazsınız. Renk blokları genellikle bu bloklara karşılık gelen piksellerin renkleri ortalaması ile özgün görüntüden türetilir. Ancak bu işlemi kendinize göre yapmanız gerekmez. Bit eşlemi daha küçük bir piksel boyutuna kopyaladığınızda otomatik olarak gerçekleşir.

Sol maymun yüzü, sol üst köşesi olan yaklaşık 72 piksellik bir alanı kaplar (112, 238). Şimdi bu 72 piksellik alanı, her biri 8 x 8 piksel kare olan 9 x 9 renkli blok dizisiyle değiştirelim.

Görüntüyü Pikselleştir sayfası bu bit eşlem içinde yüklenir ve ilk olarak adlı faceBitmapküçük bir 9 piksel kare bit eşlem oluşturur. Bu sadece maymun yüzünü kopyalamak için bir hedeftir. Hedef dikdörtgen yalnızca 9 piksel karedir, ancak kaynak dikdörtgen 72 piksel karedir. Her 8 x 8'lik kaynak piksel bloğu, renklerin ortalamasını alarak yalnızca bir piksele kadar birleştirilmiştir.

Sonraki adım, özgün bit eşlemi adlı pixelizedBitmapaynı boyutta yeni bir bit eşlem içine kopyalamaktır. Daha sonra küçük faceBitmap , her pikselinin faceBitmap boyutunun 8 katına genişletilecek şekilde 72 piksellik bir hedef dikdörtgenle bunun üzerine kopyalanır:

public class PixelizedImagePage : ContentPage
{
    SKBitmap pixelizedBitmap;

    public PixelizedImagePage ()
    {
        Title = "Pixelize Image";

        SKBitmap originalBitmap = BitmapExtensions.LoadBitmapResource(GetType(),
            "SkiaSharpFormsDemos.Media.MountainClimbers.jpg");

        // Create tiny bitmap for pixelized face
        SKBitmap faceBitmap = new SKBitmap(9, 9);

        // Copy subset of original bitmap to that
        using (SKCanvas canvas = new SKCanvas(faceBitmap))
        {
            canvas.Clear();
            canvas.DrawBitmap(originalBitmap,
                              new SKRect(112, 238, 184, 310),   // source
                              new SKRect(0, 0, 9, 9));          // destination

        }

        // Create full-sized bitmap for copy
        pixelizedBitmap = new SKBitmap(originalBitmap.Width, originalBitmap.Height);

        using (SKCanvas canvas = new SKCanvas(pixelizedBitmap))
        {
            canvas.Clear();

            // Draw original in full size
            canvas.DrawBitmap(originalBitmap, new SKPoint());

            // Draw tiny bitmap to cover face
            canvas.DrawBitmap(faceBitmap,
                              new SKRect(112, 238, 184, 310));  // destination
        }

        // Create SKCanvasView to view result
        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();
        canvas.DrawBitmap(pixelizedBitmap, info.Rect, BitmapStretch.Uniform);
    }
}

Oluşturucu, sonucu görüntülemek için bir SKCanvasView oluşturarak sonuçlanır:

Görüntüyü Pikselleştir

Bit eşlemleri döndürme

Bir diğer yaygın görev de bit eşlemleri döndürmektir. Bu özellikle i Telefon veya iPad fotoğraf kitaplığından bit eşlemleri alırken kullanışlıdır. Fotoğraf çekildiğinde cihaz belirli bir yönde tutulmadığı sürece, resmin baş aşağı veya yan olması muhtemeldir.

Bit eşlemi baş aşağı çevirmek için birinciyle aynı boyutta başka bir bit eşlem oluşturulması ve ardından birinci bit eşlemi ikinciye kopyalarken 180 derece döndürülecek şekilde bir dönüşüm ayarlanması gerekir. Bu bölümdeki tüm örneklerde döndürmeniz bitmap gereken nesne verilmiştir SKBitmap :

SKBitmap rotatedBitmap = new SKBitmap(bitmap.Width, bitmap.Height);

using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
    canvas.Clear();
    canvas.RotateDegrees(180, bitmap.Width / 2, bitmap.Height / 2);
    canvas.DrawBitmap(bitmap, new SKPoint());
}

90 derece döndürdüğünüzde, yüksekliği ve genişliği değiştirerek özgün boyuttan farklı bir bit eşlem oluşturmanız gerekir. Örneğin, özgün bit eşlem 1200 piksel genişliğinde ve 800 piksel yüksekliğindeyse, döndürülen bit eşlem 800 piksel genişliğinde ve 1200 piksel genişliğindedir. Bit eşleminin sol üst köşesi etrafında döndürülmesi ve ardından görünüme kaydırılmış olması için çeviriyi ve döndürmeyi ayarlayın. (ve RotateDegrees yöntemlerininTranslate, uygulandıkları yöntemin tersi sırada çağrıldığını unutmayın.) Saat yönünde 90 derece döndürme kodu aşağıdadır:

SKBitmap rotatedBitmap = new SKBitmap(bitmap.Height, bitmap.Width);

using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
    canvas.Clear();
    canvas.Translate(bitmap.Height, 0);
    canvas.RotateDegrees(90);
    canvas.DrawBitmap(bitmap, new SKPoint());
}

Saat yönünün tersine 90 derece döndürmek için de benzer bir işlev aşağıdadır:

SKBitmap rotatedBitmap = new SKBitmap(bitmap.Height, bitmap.Width);

using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
    canvas.Clear();
    canvas.Translate(0, bitmap.Width);
    canvas.RotateDegrees(-90);
    canvas.DrawBitmap(bitmap, new SKPoint());
}

Bu iki yöntem, SkiaSharp Bit Eşlemleri Kırpma makalesinde açıklanan Fotoğraf Bulmacası sayfalarında kullanılır.

Kullanıcının bit eşlemi 90 derecelik artışlarla döndürmesine izin veren bir program, 90 derece döndürmek için yalnızca bir işlev uygulamaya ihtiyaç duyar. Kullanıcı daha sonra bu işlevin tekrar tekrar yürütülmesiyle 90 derecelik herhangi bir artışla döndürebilir.

Bir program bit eşlemi istediğiniz miktarda döndürebilir. Basit bir yaklaşım, 180'i genelleştirilmiş angle bir değişkenle değiştirerek 180 derece döndüren işlevi değiştirmektir:

SKBitmap rotatedBitmap = new SKBitmap(bitmap.Width, bitmap.Height);

using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
    canvas.Clear();
    canvas.RotateDegrees(angle, bitmap.Width / 2, bitmap.Height / 2);
    canvas.DrawBitmap(bitmap, new SKPoint());
}

Ancak, genel durumda, bu mantık döndürülen bit eşlem köşelerini kırpacaktır. Bu köşeleri dahil etmek için trigonometri kullanarak döndürülen bit eşlem boyutunu hesaplamak daha iyi bir yaklaşımdır.

Bu trigonometri Bit Eşlem Rotator sayfasında gösterilir. XAML dosyası SKCanvasView Slider , 0 ile 360 derece arasında bir ve örneği oluşturur ve Label geçerli değeri gösterir:

<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.Bitmaps.BitmapRotatorPage"
             Title="Bitmap Rotator">
    <StackLayout>
        <skia:SKCanvasView x:Name="canvasView"
                           VerticalOptions="FillAndExpand"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <Slider x:Name="slider"
                Maximum="360"
                Margin="10, 0"
                ValueChanged="OnSliderValueChanged" />

        <Label Text="{Binding Source={x:Reference slider},
                              Path=Value,
                              StringFormat='Rotate by {0:F0}&#x00B0;'}"
               HorizontalTextAlignment="Center" />

    </StackLayout>
</ContentPage>

Arka planda kod dosyası bir bit eşlem kaynağı yükler ve adlı originalBitmapstatik salt okunur bir alan olarak kaydeder. İşleyicide PaintSurface görüntülenen bit eşlem, rotatedBitmapbaşlangıçta olarak ayarlanmıştır originalBitmap:

public partial class BitmapRotatorPage : ContentPage
{
    static readonly SKBitmap originalBitmap =
        BitmapExtensions.LoadBitmapResource(typeof(BitmapRotatorPage),
            "SkiaSharpFormsDemos.Media.Banana.jpg");

    SKBitmap rotatedBitmap = originalBitmap;

    public BitmapRotatorPage ()
    {
        InitializeComponent ();
    }

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

        canvas.Clear();
        canvas.DrawBitmap(rotatedBitmap, info.Rect, BitmapStretch.Uniform);
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        double angle = args.NewValue;
        double radians = Math.PI * angle / 180;
        float sine = (float)Math.Abs(Math.Sin(radians));
        float cosine = (float)Math.Abs(Math.Cos(radians));
        int originalWidth = originalBitmap.Width;
        int originalHeight = originalBitmap.Height;
        int rotatedWidth = (int)(cosine * originalWidth + sine * originalHeight);
        int rotatedHeight = (int)(cosine * originalHeight + sine * originalWidth);

        rotatedBitmap = new SKBitmap(rotatedWidth, rotatedHeight);

        using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
        {
            canvas.Clear(SKColors.LightPink);
            canvas.Translate(rotatedWidth / 2, rotatedHeight / 2);
            canvas.RotateDegrees((float)angle);
            canvas.Translate(-originalWidth / 2, -originalHeight / 2);
            canvas.DrawBitmap(originalBitmap, new SKPoint());
        }

        canvasView.InvalidateSurface();
    }
}

ValueChanged işleyicisiSlider, döndürme açısına göre yeni rotatedBitmap bir oluşturan işlemleri gerçekleştirir. Yeni genişlik ve yükseklik, özgün genişliklerin ve yüksekliklerin sinüs ve kosinüslerinin mutlak değerlerini temel alır. Döndürülen bit eşlem üzerinde özgün bit eşlemi çizmek için kullanılan dönüşümler özgün bit eşlem merkezini orijine taşır, ardından belirtilen derece sayısına göre döndürür ve ardından bu merkezi döndürülen bit eşlemin ortasına çevirir. Translate(ve RotateDegrees yöntemleri, uygulandıkları sırayla çağrılır.)

Açık pembe bir arka plan yapmak için yönteminin rotatedBitmap kullanımına Clear dikkat edin. Bu yalnızca ekran boyutunu rotatedBitmap göstermek için yapılır:

Bit Eşlem Rotator

Döndürülen bit eşlem, özgün bit eşlemin tamamını içerecek kadar büyüktür, ancak daha büyük değildir.

Bit eşlemleri çevirme

Bit eşlemlerde yaygın olarak gerçekleştirilen bir diğer işlem de çevirme olarak adlandırılır. Kavramsal olarak bit eşlem, bit eşlem merkezi boyunca dikey eksen veya yatay eksen etrafında üç boyutta döndürülür. Dikey çevirme bir ayna görüntüsü oluşturur.

Örnek uygulamadaki Bitmap Flipper sayfası bu işlemleri gösterir. XAML dosyası, dikey ve yatay olarak çevirmeye yönelik bir SKCanvasView ve iki düğme içerir:

<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.Bitmaps.BitmapFlipperPage"
             Title="Bitmap Flipper">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <skia:SKCanvasView x:Name="canvasView"
                           Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <Button Text="Flip Vertical"
                Grid.Row="1" Grid.Column="0"
                Margin="0, 10"
                Clicked="OnFlipVerticalClicked" />

        <Button Text="Flip Horizontal"
                Grid.Row="1" Grid.Column="1"
                Margin="0, 10"
                Clicked="OnFlipHorizontalClicked" />
    </Grid>
</ContentPage>

Arka planda kod dosyası, düğmeler için işleyicilerde Clicked şu iki işlemi uygular:

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

    public BitmapFlipperPage()
    {
        InitializeComponent();
    }

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

        canvas.Clear();
        canvas.DrawBitmap(bitmap, info.Rect, BitmapStretch.Uniform);
    }

    void OnFlipVerticalClicked(object sender, ValueChangedEventArgs args)
    {
        SKBitmap flippedBitmap = new SKBitmap(bitmap.Width, bitmap.Height);

        using (SKCanvas canvas = new SKCanvas(flippedBitmap))
        {
            canvas.Clear();
            canvas.Scale(-1, 1, bitmap.Width / 2, 0);
            canvas.DrawBitmap(bitmap, new SKPoint());
        }

        bitmap = flippedBitmap;
        canvasView.InvalidateSurface();
    }

    void OnFlipHorizontalClicked(object sender, ValueChangedEventArgs args)
    {
        SKBitmap flippedBitmap = new SKBitmap(bitmap.Width, bitmap.Height);

        using (SKCanvas canvas = new SKCanvas(flippedBitmap))
        {
            canvas.Clear();
            canvas.Scale(1, -1, 0, bitmap.Height / 2);
            canvas.DrawBitmap(bitmap, new SKPoint());
        }

        bitmap = flippedBitmap;
        canvasView.InvalidateSurface();
    }
}

Dikey çevirme, yatay ölçeklendirme faktörü –1 olan bir ölçeklendirme dönüşümüyle gerçekleştirilir. Ölçeklendirme merkezi bit eşleminin dikey merkezidir. Yatay çevirme, –1 dikey ölçeklendirme faktörüne sahip bir ölçeklendirme dönüşümüdür.

Maymun gömleğindeki ters harflerle görebileceğiniz gibi, çevirme döndürme ile aynı değildir. Ancak sağdaki UWP ekran görüntüsünde gösterildiği gibi, hem yatay hem de dikey olarak çevirme işlemi 180 derece döndürmeyle aynıdır:

Bit Eşlem Paleti

Benzer teknikler kullanılarak işlenebilen bir diğer yaygın görev de bit eşlemi dikdörtgen bir alt kümeye kırpmaktır. Bu, bir sonraki SkiaSharp Bit Eşlemlerini Kırpma makalesinde açıklanmıştır.