mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.51k stars 538 forks source link

SkiaSharp vs System.Drawing DrawRectangle and AddArc #526

Closed CyrusJoudieh closed 4 years ago

CyrusJoudieh commented 6 years ago

Description

Path -> DrawArc and SKRect seems not working as they should if compared to System.Drawing

Code

LinqPad File:

SkiaSharp.zip

    int Width = 300;
    int Height = 200;
    int x = 2;
    int y = 3;
    int GapSize = 6;
    int width = Width - x * 2;
    int height = Height - y * 2;
    float MinValue = 0;
    float MaxValue = 100;
    float fromAngle = 135F;
    float toAngle = 405F;

    System.Drawing.Bitmap bmps = new System.Drawing.Bitmap(Width, Height);
    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmps);
    System.Drawing.Rectangle rectImg = new System.Drawing.Rectangle(x, y, width, height);
    g.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.Aqua), 0, 0, bmps.Width, bmps.Height);
    float recommendedValueGreen = 85;
    float thresholdGreen = 30;
    GapSize = 15;

    System.Drawing.Pen Pen_color = new System.Drawing.Pen(System.Drawing.Color.FromArgb(100, System.Drawing.Color.LawnGreen), (float)(width * .06));
    System.Drawing.Rectangle rectg = new System.Drawing.Rectangle(rectImg.X + GapSize, rectImg.Y + GapSize, rectImg.Width - GapSize * 2, rectImg.Height - GapSize * 2);

    float val = MaxValue - MinValue;
    val = (100 * (recommendedValueGreen - MinValue)) / val;
    val = ((toAngle - fromAngle) * val) / 100;
    val += fromAngle;
    float stAngle = val - ((270 * thresholdGreen) / 200);
    if (stAngle <= 135) stAngle = 135;
    float sweepAngle = ((270 * thresholdGreen) / 100);
    if (stAngle + sweepAngle > 405) sweepAngle = 405 - stAngle;

    g.DrawArc(Pen_color, rectg, stAngle, sweepAngle);
    Console.WriteLine("X:" + rectg.X + ", Y:" + rectg.Y + ", W:" + rectg.Width + ", H:" + rectg.Height + ", SA:" + stAngle + ", SW:" + sweepAngle);
    MemoryStream ms = new MemoryStream();
    bmps.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

    Util.Image(ms.GetBuffer()).Dump();

SKIA

    SKImageInfo image = new SKImageInfo(Width, Height);
    SKBitmap bmp = SKBitmap.FromImage(SKImage.Create(image));
    SKSurface surface = SKSurface.Create(image);
    SKCanvas canvas = surface.Canvas;
    canvas.Clear(SKColors.Aqua);

    recommendedValueGreen = 85;
    thresholdGreen = 30;
    GapSize = 15;
    SKRect rect = new SKRect(rectImg.X + GapSize, rectImg.Y + GapSize, rectImg.Width - GapSize * 2, rectImg.Height - GapSize * 2);
    //rect.Size = new SKSize() { Height = rect.Size.Height + rect.Location.Y, Width = rect.Size.Width + rect.Location.X};
    Console.WriteLine("X:" + rect.Location.X + ", Y:" + rect.Location.Y + ", W:" + rect.Width + ", H:" + rect.Height + ", SA:" + stAngle + ", SW:" + sweepAngle);
    val = MaxValue - MinValue;
    val = (100 * (recommendedValueGreen - MinValue)) / val;
    val = ((toAngle - fromAngle) * val) / 100;
    val += fromAngle;
    stAngle = val - ((270 * thresholdGreen) / 200);
    if (stAngle <= 135) stAngle = 135;
    sweepAngle = ((270 * thresholdGreen) / 100);
    if (stAngle + sweepAngle > 405) sweepAngle = 405 - stAngle;

    canvas.DrawArc(rect, stAngle, sweepAngle, new SKPaint()
    {
     Color = SKColors.LawnGreen.SetAlpha(100),
     Style = SKPaintStyle.Stroke,
     StrokeWidth = (float)(width * .06)
    });

    // save the file
    SKImage img = surface.Snapshot();
    SKData data = img.Encode(SKEncodedImageFormat.Png, 100);

    MemoryStream stream = new MemoryStream();

    Util.Image(data.ToArray()).Dump();

Expected Behavior

The sweepAngle of the Path.AddArc is sometime shorter/smaller or larger than the one in System.Drawing for example if set start angle at 90 with 45 sweepangle

The SkRect rectangle is smaller than the Rectangle in System.Drawing have to resize it manually such as rect.Size = new SKSize() { Height = rect.Size.Height + rect.Location.Y, Width = rect.Size.Width + rect.Location.X};

Actual

Not able to draw an Arc identical to the one in System.Drawing

Not able to draw a rectangle of the same size as in System.Drawing without resizing the SKRect with new SKSize

Basic Information

Screenshots

skia skia2 skia3

Reproduction Link

VS bug #736292

mattleibow commented 5 years ago

I had a look at this and I also see the difference. Most notably when the oval is stretched - circles appear to match almost exactly. The more elongated, the more off.

SkiaSharp was never supposed to match, so that is why this is a low priority. Upon closer inspection, I would say that System.Drawing was wrong. I did a test from 0 degrees to 90 degrees and System.Drawing did not have right angles.

image

mattleibow commented 4 years ago

Closing this as SkiaSharp is not meant to exactly match System.Drawing, and it appears that SkiaSharp was more correct.