【问题标题】:How to draw with Skia on Cairo context in Gtk3如何在 Gtk3 中在开罗上下文中使用 Skia 绘制
【发布时间】:2016-02-29 14:14:34
【问题描述】:

我希望得到彩色矩形,但得到的是垃圾矩形。到目前为止,我有以下代码:

using System;
using GLib;
using SkiaSharp;
using Gtk;

namespace SkiaSharpExample {
    class CCDrawingArea : DrawingArea {
        protected override bool OnDrawn (Cairo.Context cr) {
            using (var skSurface = SKSurface.Create (100, 100, SKColorType.N_32, SKAlphaType.Premul)) {
                var canvas = skSurface.Canvas;
                var paint = new SKPaint {
                    StrokeWidth = 4, 
                    Color = new SKColor (255, 255, 255, 255)
                };

                var rect = new SKRect (10, 10, 50, 50);
                canvas.DrawRect (rect, paint);

                var image = skSurface.Snapshot ();

                Cairo.Surface surface = new Cairo.ImageSurface (
                    image.Encode ().Data,
                    Cairo.Format.Argb32,
                    image.Width, image.Height,
                    4 * image.Width * image.Height);

                surface.MarkDirty ();
                cr.SetSourceSurface (surface, 0, 0);
                cr.Paint ();
            }
            return true;
        }
    }

    class MainClass {
        public static void Main (string[] args){
            ExceptionManager.UnhandledException += delegate(UnhandledExceptionArgs expArgs) {
                Console.WriteLine (expArgs.ExceptionObject.ToString ());
                expArgs.ExitApplication = true;
            };

            Gtk.Application.Init ();

            var window = new Window ("Hello World");
            window.SetDefaultSize (1024, 800);
            window.SetPosition (WindowPosition.Center);
            window.DeleteEvent += delegate { 
                Gtk.Application.Quit (); 
            };

            var darea = new CCDrawingArea ();
            window.Add (darea);

            window.ShowAll ();

            Gtk.Application.Run ();
        }
    }
}

【问题讨论】:

    标签: c# cairo gtk# skia


    【解决方案1】:

    我对 Skia 毫无头绪,也找不到任何有关其图像格式的文档,但这里的最后一个参数应该是步幅。 自然步幅为4*image.Width。这也是Skia使用的吗? (步幅是一个像素的开头和该像素下面的像素之间的字节数)

               Cairo.Surface surface = new Cairo.ImageSurface (
                    image.Encode ().Data,
                    Cairo.Format.Argb32,
                    image.Width, image.Height,
                    4 * image.Width * image.Height);
    

    【讨论】:

    • 是的,这是问题的一部分,我应该使用 4 * image.Width
    【解决方案2】:

    我找到了在创建 SKSurface 和 SKCanvas 之前我应该​​使用 SKBitmap 的解决方案。要获取像素数据,我应该使用 SKBitmap.GetPixels 方法。以下是工作示例的源代码:

        using System;
        using GLib;
        using SkiaSharp;
        using Gtk;
    
        namespace SkiaSharpExample
        {
            class CCDrawingArea : DrawingArea
            {
                protected override bool OnDrawn(Cairo.Context cr)
                {
                    const int width = 100;
                    const int height = 100;
    
                    using (var bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul))
                    {
                        IntPtr len;
                        using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SKColorType.N_32, SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes))
                        {
                            var canvas = skSurface.Canvas;
                            canvas.Clear(SKColors.White);
    
                            using (var paint = new SKPaint())
                            {
                                paint.StrokeWidth = 4;
                                paint.Color = new SKColor(0x2c, 0x3e, 0x50);
    
                                var rect = new SKRect(10, 10, 50, 50);
                                canvas.DrawRect(rect, paint);
                            }
    
                            Cairo.Surface surface = new Cairo.ImageSurface(
                                bitmap.GetPixels(out len),
                                Cairo.Format.Argb32,
                                bitmap.Width, bitmap.Height,
                                bitmap.Width * 4);
    
    
                            surface.MarkDirty();
                            cr.SetSourceSurface(surface, 0, 0);
                            cr.Paint();
                        }
                    }
    
                    return true;
                }
            }
    
            class MainClass
            {
                public static void Main(string[] args)
                {
                    ExceptionManager.UnhandledException += delegate(UnhandledExceptionArgs expArgs)
                    {
                        Console.WriteLine(expArgs.ExceptionObject.ToString());
                        expArgs.ExitApplication = true;
                    };
    
                    Gtk.Application.Init();
    
                    var window = new Window("Hello Skia World");
                    window.SetDefaultSize(1024, 800);
                    window.SetPosition(WindowPosition.Center);
                    window.DeleteEvent += delegate
                    {
                        Gtk.Application.Quit();
                    };
    
                    var darea = new CCDrawingArea();
                    window.Add(darea);
    
                    window.ShowAll();
    
                    Gtk.Application.Run();
                }
    
                void OnException(object o, UnhandledExceptionArgs args)
                {
    
                }
            }
        }
    

    【讨论】:

    • 此代码仅适用于 Cairo.Format.Argb32SKColorType.N_32 定义相同 A-R-G-B 顺序的 Windows。在 Linux 和 Mac 上,SKColorType.N_32 改为 A-B-G-R
    猜你喜欢
    • 1970-01-01
    • 2017-02-03
    • 2020-09-19
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多