Crop a svg image and convert it to png

Viewed 243

I have a big svg image.
I would like to crop it to a rectangle, using coordinates, and convert it to png image.

I have to say that I'm not used to drawing with c#.
Surface, Canvas and other notions are new to me.

I have figured out how to load the svg, using SkiaShark and SkiaShark.Svg:

var svg = new SkiaSharp.Extended.Svg.SKSvg();
svg.Load(tmpPath);

And found a gist that saves a png. But this is "Chinese" for me.

var imageInfo = new SKImageInfo(100, 100);
using (var surface = SKSurface.Create(imageInfo))
using (var canvas = surface.Canvas)
{
    // calculate the scaling need to fit to screen
    var scaleX = 100 / svg.Picture.CullRect.Width;
    var scaleY = 100 / svg.Picture.CullRect.Height;
    var matrix = SKMatrix.CreateScale((float)scaleX, (float)scaleY);

    // draw the svg
    canvas.Clear(SKColors.Transparent);
    canvas.DrawPicture(svg.Picture, ref matrix);
    canvas.Flush();

    using (var data = surface.Snapshot())
    using (var pngImage = data.Encode(SKEncodedImageFormat.Png, 100))
    {
        tmpPath = Path.ChangeExtension(tmpPath, "PNG");
        using var imageStream = new FileStream(tmpPath, FileMode.Create);
        pngImage.SaveTo(imageStream);
    }
}

If someone could show me the directions, it would be much appreciated.

EDIT


I've come to this implentation myself, though it is not working... The result bitmap is transparent and empty.

private string ConvertSVGToPNGRectangleWithSkiaSharpExtended(string path, double left, double top, double right, double bottom)
{
    var svg = new SkiaSharp.Extended.Svg.SKSvg();
    var picture = svg.Load(path);

    // Get the initial map size
    var source = new SKRect(picture.CullRect.Left, picture.CullRect.Top, picture.CullRect.Width, picture.CullRect.Height);

    // Cropping Rect
    var cropRect = new SKRect((int)left, (int)top, (int)right, (int)bottom);

    var croppedBitmap = new SKBitmap((int)cropRect.Width, (int)cropRect.Height);

    using var canvas = new SKCanvas(croppedBitmap);
    canvas.Clear(SKColors.Transparent);
    canvas.DrawBitmap(croppedBitmap, source, cropRect);

    var data = croppedBitmap.Encode(SKEncodedImageFormat.Png, 100);

    path = Path.ChangeExtension(path, "PNG");
    using var imageStream = new FileStream(path, FileMode.Create);
    data.SaveTo(imageStream);

    return path;
}

EDIT 2: I'm sorry , if it is not clear. You can refer to this question for doing so on Android.

1 Answers

Disclaimer: I'm not an expert with SkiaSharp, but I do know about drawing and canvases and I looked up the documentation at https://docs.microsoft.com/en-us/dotnet/api/skiasharp.skcanvas.drawpicture

I think the problem is this line:

canvas.DrawBitmap(croppedBitmap, source, cropRect);

I think you need:

canvas.DrawPicture(picture, -cropRect.Left, -cropRect.Top);
canvas.Flush();

I might have the coordinates wrong, but the problem behind your failure is that you are never drawing picture to the canvas.

To help with your confusion about what a canvas is: SKCanvas(croppedBitmap) is making it so that every time you draw to canvas, what you are actually drawing on is the bitmap. So in order to draw your picture onto the bitmap, you have to draw picture onto canvas. Using negative coordinates make it so the top and left of the svg picture are above and to the left of the top-left corner of the bitmap, which is the equivalent of having the bitmap start somewhere in the middle of the svg picture.

Hope this helps!

Related