none
System.Drawing.Graphics.DrawPath throws OutOfMemoryException when drawing a very small cubic bezier with a pen width greater than 1.5 RRS feed

  • Question

  • System.Drawing.Graphics.DrawPath throws OutOfMemoryException when drawing a very small cubic bezier with a pen width greater than 1.5. This is a very very very painful bug, because this means we basically we cannot use arbitrary graphics paths/pen widths. We're not even sure how to work around this issue yet, we either need to stick with a pen width of 1, not drawing cubic beziers, or pre-checking the size of the bezier, but it's not very clear around which size the problem occurs. We're displaying CAD drawings, and when displaying a full drawing, certain features can be very tiny, and become decent sized only when zoomed in.

    This is actually a duplicate of issue 182774 (https://connect.microsoft.com/VisualStudio/feedback/details/182774), which was closed because nobody could reproduce it. But below is a small program to reproduce the issue.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Text;
    using System.Windows.Forms;
    
    namespace CurveTest {
        public partial class Form1 : Form {
            public Form1() {
                InitializeComponent();
            }
    
            protected override void OnPaint(PaintEventArgs e) {
                // Bug in GDI+ for drawing small cubic bezier curves with a pen greater than 1.5.
                using (
                    GraphicsPath graphicsPath =
                        new GraphicsPath(
                            new PointF[]
                            {new PointF(100, 100), new PointF(100.001f, 100), new PointF(100.001f, 100.001f), new PointF(100, 100.001f)},
                            new byte[]
                            {(byte)PathPointType.Start, (byte)PathPointType.Bezier3, (byte)PathPointType.Bezier3, (byte)PathPointType.Bezier3}
                    )
                ) {
                    using (Pen pen = new Pen(Color.Red, 1.51f)) {
                        e.Graphics.DrawPath(pen, graphicsPath);
                    }
                }
            }
        }
    }

    I tried to submit this to connect.microsoft.com, but for no apparent reason I cannot submit any feedback, the application just waits for minutes and returns to the submit form everytime I submit without any message as to what went wrong.

    - Wout

    Thursday, September 19, 2013 12:54 PM

Answers

All replies

  • I too cannot reproduce it. Do you have any reproducible steps? Also, which OS, .NET Framework you are using?


    Please mark this post as answer if it solved your problem. Happy Programming!

    Thursday, September 19, 2013 3:35 PM
  • .NET 4.0, Win 7 x64, VS 2010. Just make a simple win forms application (not sure if the size needs to be large enough (> 100) to trigger the drawing). The OnPaint method above is the only thing that is added to the application. Our customers have the exact same problem, and it does reproduce every time I run.

    - Wout

    Thursday, September 19, 2013 5:44 PM
  • I can reproduce the error on a Win8 x86 machine (.NET 4.5).

    You can try to report it on Connect again or maybe contact MS support. Though it's probably going to be difficult to obtain a fix for this, GDI+ is pretty much "legacy".

    I did a quick test and flattening the path seems to avoid the exception. Not sure how that will affect your rendering.

    Thursday, September 19, 2013 7:01 PM
    Moderator
  • Yeah well, there isn't anything that's not legacy nowadays. WPF is too slow (and also legacy). I guess I'm not gonna bother with MS connect, as it doesn't seem to function either. I'm just posting it for other people to recognize the issue.

    - Wout

    Thursday, September 19, 2013 7:16 PM
  • "Yeah well, there isn't anything that's not legacy nowadays."

    Well, there is Direct2D.

    Thursday, September 19, 2013 7:45 PM
    Moderator
  • I know about Direct2D and whatever. I just wanted to report the bug, and someone might be interested in fixing it. It might be a bug in the .NET layer (I suspect it is).

    - Wout

    Thursday, September 19, 2013 9:04 PM
  • "It might be a bug in the .NET layer (I suspect it is)."

    Nope, I tested your example in C++ and GDI+ itself is returning that error, OutOfMemory. Of course, it isn't a real out of memory error, the error itself is bogus...

    • Proposed as answer by Damon Bu - MSFT Wednesday, September 25, 2013 9:37 AM
    Friday, September 20, 2013 4:25 AM
    Moderator
  • Just theorizing: if the error message is bogus, while nothing fatal is happening, could I in theory wrap this method myself in my own .NET wrapper and just ignore the OutOfMemory error? Thank you for testing this against GDI+ itself by the way, that is useful information.
    • Edited by wout11010110 Wednesday, September 25, 2013 11:42 AM
    Wednesday, September 25, 2013 11:38 AM
  • "could I in theory wrap this method myself in my own .NET wrapper and just ignore the OutOfMemory error?"

    I suppose you could do so but unfortunately GDI+ tends to throw this exception for various reasons. For example you also get this exception if you're trying to load an invalid image. And I remember seeing other reports of System.Drawing throwing this exception out of the blue.

    On a side note: your code works if you add a ScaleTransform(2, 2). Maybe you could render the graphics on bitmap with scale=2 and then scale down the bitmap for display. Though I wouldn't be surprised if you'll get again the exception for other path coordinates.

    Thursday, September 26, 2013 5:52 AM
    Moderator
  • Hi Mike,

    Thank you for your suggestions, I will contemplate the options for a while. Ignoring the error might not be too bad, I could internally handle it in another way, but not using exceptions, because that would be obviously fatal for performance.


    By the way: is it even remotely thinkable that the GDI+ guys are fixing this? Not that it's of any immediate use, but I can imagine they would like to have it fixed themselves.
    • Edited by wout11010110 Thursday, September 26, 2013 1:36 PM
    Thursday, September 26, 2013 1:34 PM
  • "By the way: is it even remotely thinkable that the GDI+ guys are fixing this?"

    It seems unlikely. I've seen a few System.Drawing bugs reported on connect. They end up either as Won't Fix or as External. External means that they recognize that the bug is actually in GDI+ and GDI+ is owned by the Windows team, not by VS/.NET teams.

    Here's one example that's somewhat similar to yours - a coordinate problem but with large coordinates rather than small differences between coordinates:

    https://connect.microsoft.com/VisualStudio/feedback/details/755394/graphics-drawellipse-method-pen-rectanglef-documentation-fails-to-mention-maximum-ellipse-dimensions

    Thursday, September 26, 2013 5:27 PM
    Moderator