⚠️ Warning: This website is still being developed. Code examples, videos, and links may be broken while I continue to work on it. -- Scott, May 10, 2020
Resources for visualizing data using C# and the .NET platform

Drawing with SkiaSharp

SkiaSharp is a .NET wrapper for Google's Skia Graphics Library that can be used to draw 2D graphics across mobile, server, and desktop platforms. SkiaSharp can be used with OpenGL for hardware-accelerated rendering. SkiaSharp was initially developed by Mono but is now maintained by Microsoft and is provided under the MIT License.

Drawing Library 10 lines 1k lines 10k lines 100k lines
System.Drawing 0.614 ms 28.350 ms 278.477 ms 2.834 sec
SkiaSharp 12.777 ms 97.011 ms 352.343 ms 3.493 sec
SkiaSharp + OpenGL 2.973 ms 6.588 ms 40.765 ms 422.217 ms

Code

In this example we are going to use SkiaSharp without the SkiaSharp user control (SKControl). The advantage of the present method is that it can be used in console applications. Use of the user control is demonstrated in the 🚩[???]() article.

  • Edit your build settings to target 32-bit or 64-bit (not any CPU)
  • Install the SkiaSharp NuGet package

The overall goal here is to create a SKSurface in memory, then draw on it using methods of its Canvas.

Create a SKSurface in memory

var imageInfo = new SKImageInfo(
    width: pictureBox1.Width,
    height: pictureBox1.Height,
    colorType: SKColorType.Rgba8888,
    alphaType: SKAlphaType.Premul);
var surface = SKSurface.Create(imageInfo);
var canvas = surface.Canvas;

Draw on the Surface's Canvas

canvas.Clear(SKColor.Parse("#003366"));

int lineCount = 1000;
for (int i = 0; i < lineCount; i++)
{
    float lineWidth = rand.Next(1, 10);
    var lineColor = new SKColor(
            red: (byte)rand.Next(255),
            green: (byte)rand.Next(255),
            blue: (byte)rand.Next(255),
            alpha: (byte)rand.Next(255));

    var linePaint = new SKPaint
    {
        Color = lineColor,
        StrokeWidth = lineWidth,
        IsAntialias = true,
        Style = SKPaintStyle.Stroke
    };

    int x1 = rand.Next(imageInfo.Width);
    int y1 = rand.Next(imageInfo.Height);
    int x2 = rand.Next(imageInfo.Width);
    int y2 = rand.Next(imageInfo.Height);
    canvas.DrawLine(x1, y1, x2, y2, linePaint);
}

💡 See the full SkiaSharp API to learn more about the available drawing methods

Render onto a Bitmap

Now that we're done with the drawing, let's convert this image to a Bitmap so we can display it in a Picturebox. As we've discussed previously, as Picturebox is preferred because it is double-buffered and less prone to flickering during animations where the underlying image it displays is frequently updated.

using (SKImage image = surface.Snapshot())
using (SKData data = image.Encode())
using (System.IO.MemoryStream mStream = new System.IO.MemoryStream(data.ToArray()))
{
    pictureBox1.Image?.Dispose();
    pictureBox1.Image = new Bitmap(mStream, false);
}

Source Code

Source code for this project is on GitHub: /examples/drawing/alternate/SkiaSharpBenchmark