Search code examples
svgskiasharp

some noises were added when convert from svg to png with SkiaSharp.Svg


I tried to convert following svg image to png by SkiaSharp.Extended.Svg-1.60.0(netcoreapp2.0). but there some noises in the created png file.

please tell me how to get rid of them.

<svg height="100" width="100">
    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>

and the code is here

// using SkiaSharp;
// using SkiaSharp.Extended;
// using SkiaSharp.Extended.Svg;
string fromfile = "circle.svg";
string tofile = "circle.png";
SKEncodedImageFormat toencoding = SKEncodedImageFormat.Png;
var svg = new SkiaSharp.Extended.Svg.SKSvg();
using (var pic = svg.Load(fromfile))
{
    Console.WriteLine($"{pic.CullRect.Width},{pic.CullRect.Height}");
    using (var bmp = new SKBitmap((int)svg.Picture.CullRect.Width, (int)svg.Picture.CullRect.Height))
    {
        using (var canvas = new SKCanvas(bmp))
        using (var paint = new SKPaint())
        {
            canvas.DrawPicture(svg.Picture);
            canvas.Flush();
            canvas.Save();
            using (var img = SKImage.FromBitmap(bmp))
            using (var data = img.Encode(toencoding, 100))
            {
                using (var stm = data.AsStream())
                using (var ostm = File.Create(tofile))
                {
                    stm.CopyTo(ostm);
                }
            }
        }
    }
}

Solution

  • That is cause by you not first clearing the canvas. Just add this after the canvas is created:

    canvas.Clear(SKColors.Transparent);
    

    Unlike some other libraries that auto-clear the pixels, skia and SkiaSharp do not. This is for two main reasons:

    • The clear operation is expensive
      Assume a large bitmap (10K x 10K), to clear this to transparent will take some time. And then you decide that you actually want a red background, so you clear with red. This means that the first clear was a total waste of CPU.
    • There may be existing pixel data
      In your case, you are creating a new, blank bitmap. But, there are instances when you create a new bitmap over existing memory. If we were to clear first, your image will disappear. Now, we could be clever and determine that empty bitmaps should clear, and existing pixels should not. But why do this if it is expensive and may not be required? See the point above for reasons...