5

i am new to C#. Thus, i am not so sure what the problem is with my program. The program works with small image but it shows "Out of memory exeception" when it works with a large image which is about A4 size. However, the program would be useless if it cannot work with large image. How can I solve the problem? With thanks.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { //Bitmap objects //input image Bitmap bmOrg = (Bitmap)Bitmap.FromFile(@"C:\B.png"); Bitmap bmTransparentLayover = new Bitmap(bmOrg.Width, bmOrg.Height); //Create Graphic Objects. Graphics gOriginal = Graphics.FromImage(bmOrg); Graphics gTransparentLayover = Graphics.FromImage(bmTransparentLayover); //Set Transparent Graphics back ground to an "odd" color // that hopefully won't be used to //Be changed to transparent later. gTransparentLayover.FillRectangle ( Brushes.Pink, new Rectangle (0, 0, bmTransparentLayover.Width, bmTransparentLayover.Height ) ); //Draw "transparent" graphics that will look through // the overlay onto the original. //Using LimeGreen in hopes that it's not used. Point[] points = new Point[5]; points[0] = new Point(130, 140); points[1] = new Point(130, 370); points[2] = new Point(420, 370); points[3] = new Point(420, 140); points[4] = new Point(130, 140); System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath(); gp.AddPolygon(points); gTransparentLayover.FillPath(Brushes.LimeGreen, gp); //Now make the LimeGreen Transparent to see through overlay. bmTransparentLayover.MakeTransparent(Color.LimeGreen); //draw the overlay on top of the original. gOriginal.DrawImage(bmTransparentLayover, new Rectangle(0, 0, bmTransparentLayover.Width, bmTransparentLayover.Height)); //Create new image to make the overlays background tranparent Bitmap bm3 = new Bitmap(bmOrg); bm3.MakeTransparent(Color.Pink); //Save file. //to save the output image bm3.Save(@"save.png",System.Drawing.Imaging.ImageFormat.Png); Image img = new Bitmap(480, 480); //the background image img = Image.FromFile(@"a.png"); Graphics g = Graphics.FromImage(img); //to save the combined image g.DrawImage(Image.FromFile(@"save.png"), new Point(-50, -70)); img.Save(@"final.png", ImageFormat.Png); } } } 
7
  • Unrelated to answering your question, you must be aware that you must close and dispose your graphics objects. Pad code fragments with using statements. That would do the work. Commented Jul 19, 2012 at 8:21
  • 5
    A4 size doesn't say anything. I can create an A4 size image with just 4 pixels in it :) Commented Jul 19, 2012 at 8:21
  • Not sure what the problem is, but try to add using statements around every object that implements IDisposable (Bitmap, Graphics). How much memory is the process using when you look at the task manager? Commented Jul 19, 2012 at 8:22
  • 1
    What is the overall pixel dimensions of the large image that fails? Commented Jul 19, 2012 at 8:24
  • As a 32 bit bitmap it has the size of 9992 * 8750 * (32/8) which is about 349 MB Commented Jul 19, 2012 at 8:45

3 Answers 3

9

it is a 9992x8750 image

Yes, you're in the danger zone for a 32-bit process. That image requires a big chunk of contiguous address space, 334 megabytes. You'll easily get that when you load the image early, right after your program starts. You can get about 650 megabytes at that point, give or take.

But that goes down-hill from there as your program allocates and releases memory and loads a couple of assemblies. The address space gets fragmented, the holes between the allocations are getting smaller. Just loading a DLL with an awkward base address can suddenly cut the largest hole by more than a factor of two. The problem is not the total amount of virtual memory available, it can be a gigabyte or more, it is the size of the largest available chunk. After a while, having a 90 megabyte allocation fail is not entirely unusual. Just that one allocation can fail, you could still allocate a bunch of, say, 50 megabyte chunks.

There is no cure for address space fragmentation and you can't fix the way that the Bitmap class stores the pixel data. But one, specify a 64-bit version of Windows as a requirement for your program. It provides gobs of virtual memory, fragmentation is a non-issue. If you want to chase it down then you can get insight in the VM layout with the SysInternals' VMMap utility. Beware of the information overload you may experience.

Sign up to request clarification or add additional context in comments.

Comments

0

I suspect that your main problem is that you've got a number of bitmap and graphics instances in use at the same time.

It's probably worth trying to reorganise your code so that as few of these are present at any one time as possible, using .Dispose() to remove items you're finished with.

Comments

0

Try to work on Windows 64-bit, That's the solution of most of memory problems.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.