[Mono-list] OutOfMemoryException after scale transform a Region
Sebastien Pouliot
sebastien.pouliot at gmail.com
Mon Sep 22 13:42:50 EDT 2008
Hello Pablo,
On Mon, 2008-09-22 at 08:46 -0700, Pablo Lecea wrote:
> Hello there,
> I have an application which takes two Regions and gets the intersection
> between both in order to get the closest point... Before the intersect
> operation is figured out I'm scaling the regions to avoid roundings. But
> after the regions are scaled (100) any operation against the regions can be
> done without get a OutOfMemoryException.
The region stuff can be *very* complex and libgdiplus took a few
shortcuts to get things working.
A long time ago (well about 2.5 year ago) only region with rectangle
shapes were supported inside libgdiplus. This was a big limitation but
was much simpler to implement (first shortcut).
To get around this libgdiplus implements binary operations on
non-rectangular regions using a (1bbp) bitmap. This (second shortcut)
works very well unless you (a) need more than pixel accuracy or (b) have
very large regions.
Your example that have a region of 2936 x 3647 pixels (see WARNING)
which exceed the amount of memory that libgdiplus is willing to allocate
to compute the region - problem (b). This would (probably) work without
scaling but then you loose your "hacked" accuracy - problem (a).
> This is happening just on Mac OS, I
> tested on Windows XP via mono and it works fine.
This is because Mono use MS GDI+ on Windows. Your code would not be
working on Linux, Solaris or anywhere else (but Windows).
> The exception message is :
> ** (/Users/pablolecea/closest/closest/bin/Debug/closest.exe:604): WARNING
> **: Path conversion requested 42830368 bytes (2936 x 3647). Maximum size is
> 8388608 bytes.
>
> Unhandled Exception: System.OutOfMemoryException: Not enough memory to
> complete operation [GDI+ status: OutOfMemory]
> at System.Drawing.GDIPlus.CheckStatus (Status status) [0x000be] in
> /private/tmp/monobuild/build/BUILD/mono-1.9.1/mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs:222
> at System.Drawing.Region.Intersect (System.Drawing.Region region)
> [0x00024] in
> /private/tmp/monobuild/build/BUILD/mono-1.9.1/mcs/class/System.Drawing/System.Drawing/Region.cs:148
> at (wrapper remoting-invoke-with-check) System.Drawing.Region:Intersect
> (System.Drawing.Region)
> at closest.MainClass.GetClosestPoint () [0x00030] in
> /Users/pablolecea/closest/closest/Main.cs:171
> at closest.MainClass.Main (System.String[] args) [0x00000] in
> /Users/pablolecea/closest/closest/Main.cs:154
>
> Here the code:
>
> static void Main(string[] args)
> {
> GetClosestPoint();
> }
>
>
> private static void GetClosestPoint()
> {
> //get the regions
> Region firstRegion = CreateFirstRegion();
> Region secondRegion = CreateSecondRegion();
>
> //This scaling is done to avoid rounding in bounds values
> Matrix matrix = new Matrix();
> matrix.Scale(100, 100);
> firstRegion.Transform(matrix);
> secondRegion.Transform(matrix);
>
> //intersect the regions
> firstRegion.Intersect(secondRegion); //an OutOfMemoryException
> is thrown on mac OS
>
> System.Windows.Forms.Control control = new
> System.Windows.Forms.Control();
> System.Drawing.Graphics graph = control.CreateGraphics();
> graph.PageUnit = GraphicsUnit.Pixel;
> System.Drawing.RectangleF bounds = firstRegion.GetBounds(graph);
>
> }
>
> private static Region CreateFirstRegion()
> {
> GraphicsPath gp = new GraphicsPath();
>
> gp.StartFigure();
> gp.AddLine(new PointF(193.24475f, 189.1613f), new
> PointF(221.7687f, 225.011f));
> gp.AddLine(new PointF(221.7687f, 225.011f), new
> PointF(222.5512f, 224.38869f));
> gp.AddLine(new PointF(222.5512f, 224.38869f), new
> PointF(194.0272f, 188.53869f));
> gp.CloseFigure();
>
> Region result = new Region(gp);
> return result;
> }
>
> private static Region CreateSecondRegion()
> {
> GraphicsPath gp = new GraphicsPath();
> string text = "Cl";
> int platformStyle = (int)System.Drawing.FontStyle.Regular;
> float fontSize = 12;
> string fontName = "Times New Roman";
>
> System.Drawing.Font platformFont = new
> System.Drawing.Font(fontName, fontSize, System.Drawing.FontStyle.Regular,
> GraphicsUnit.Pixel);
> gp.AddString(text, platformFont.FontFamily, platformStyle,
> platformFont.Size, new System.Drawing.Rectangle(),
> StringFormat.GenericTypographic);
>
> Matrix translationMatrix = new Matrix();
> translationMatrix.Translate(187.222f, 182.8066f);
> gp.Transform(translationMatrix);
>
> Region result = new Region(gp);
> return result;
> }
>
> Can you help me to figure out what is happening.
> Thanks,
> Pablo
> --
> View this message in context: http://www.nabble.com/OutOfMemoryException-after-scale-transform-a-Region-tp19610028p19610028.html
> Sent from the Mono - General mailing list archive at Nabble.com.
>
> _______________________________________________
> Mono-list maillist - Mono-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
More information about the Mono-list
mailing list