[Mono-list] OutOfMemoryException after scale transform a Region

Sebastien Pouliot sebastien.pouliot at gmail.com
Mon Sep 22 16:12:42 EDT 2008


Hello Pablo,

On Mon, 2008-09-22 at 12:50 -0700, Pablo Lecea wrote:
> Hello Sebastien,
>  
> First to all, thanks for your answer. 
> Our application works with this kind of regions all the time, for that
> reason we need to figth with both issues, more than pixel accuracy and very
> large regions. Do you have any idea to proceed? I mean, do you know some
> other way to work around this problem?

With both requirements I suggest you look at other alternatives (than
libgdiplus) and I guess the next question will be "with what?" so...

It's been quite a while (the same 2.5 years ;-) since I looked at what
was available, so the situation could have improved, but there was
nothing that I could reuse (license-compatible) inside libgdiplus.

That being said the one that impressed me the most, back then, was
GPC[1] (enough that I remember its name ;-). It's not free software but
can be used in non-commercial projects and has .NET bindings (but I
never looked at them).

Otherwise there is a lot of code (either to work on specific problems,
or "attempts" at larger goals) that did not do everything libgdiplus
needed, but could be enough for you. Google will be your
(over-enthusiastic) friend to look at them.

Sebastien

p.s. If/when you find something interesting (applicable to libgdiplus
or not) please let us know!

[1] http://www.cs.man.ac.uk/~toby/alan/software/

> Pablo
> 
> 
> Sebastien Pouliot-2 wrote:
> > 
> > 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
> > 
> > _______________________________________________
> > 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