DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Mon, 13 Aug 2007 11:11:41 -0700,    posted on: microsoft.public.dotnet.framework.drawing        back       

Thread Index
  1    vector
          2    Bob Powell [MVP]
                 3    Doug Forster nobody@nowhere,com
          4    vector


ArgumentException and OutOfMemoryException in Bitmap constructor   
I'm trying to write a program that spins through a List collection of
Image objects and manipulates them.  Unfortunately I keep encountering
exceptions where I don't understand why they're happening.  I've
stripped down my app into a sample program that has the same flaws in
it.

The first exception happens in a loop where I create and add Bitmap
objects to a List.  The message is "Parameter is not valid," and it
can be avoided by adding "PixelFormat.Format1bppIndexed" to the Bitmap
constructor.

The second exception is an out of memory error, where I'm trying in a
loop to create a deep copy of each Image object in the List,
manipulate it (but not in the sample code below), and replace the old
Image in the List with the new Image.

I really don't understand what's going wrong here.  Can someone please
explain this to me?

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;

namespace ConsoleApplication2
{
  class Program
  {
    [STAThread]
    static void Main(string[] args)
    {
      try {
        bool causeArgumentException = false;
        bool causeOutOfMemoryException = true;
        RunTest(causeArgumentException, causeOutOfMemoryException);
      }
      catch (ArgumentException ex) {
        //A first chance exception of type 'System.ArgumentException'
occurred in System.Drawing.dll
        //	at System.Drawing.Bitmap..ctor(Int32 width, Int32 height,
PixelFormat format)
        //	at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
        //	at ConsoleApplication2.Program.RunTest(Boolean
causeOutOfMemoryException) in c:\source\ImagePro2008\ImagePro
\Class1.cs:line 49
        //	at ConsoleApplication2.Program.Main(String[] args) in c:
\source\ImagePro2008\ImagePro\Class1.cs:line 17
        Debug.WriteLine(ex.StackTrace);

        // Parameter is not valid.
        Debug.WriteLine(ex.Message);
      }
      catch (OutOfMemoryException ex) {
        // A first chance exception of type
'System.OutOfMemoryException' occurred in System.Drawing.dll
        //	at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
        //	at System.Drawing.Graphics.DrawImage(Image image, Int32 x,
Int32 y, Int32 width, Int32 height)
        //	at System.Drawing.Bitmap..ctor(Image original, Int32 width,
Int32 height)
        //	at System.Drawing.Bitmap..ctor(Image original)
        //	at ConsoleApplication2.Program.RunTest(Boolean
causeOutOfMemoryException)
        //	at ConsoleApplication2.Program.Main(String[] args)
        Debug.WriteLine(ex.StackTrace);

        // Out of memory.
        Debug.WriteLine(ex.Message);
      }

      return;
    }

    private static void RunTest(bool causeArgumentException, bool
causeOutOfMemoryException)
    {
      // the number of test pages to put into the list
      int numTestPages = 150;

      List<Image> list = new List<Image>();

      // get n unique single-page image objects loaded into our
collection
      for (int i = 1; i <= numTestPages; i++) {
        Debug.WriteLine("Adding page " + i.ToString());

        if (causeArgumentException) {
          // this exception takes a few loops before it will happen
          list.Add(new Bitmap(1728, 2244));
        }
        else {
          // this doesn't cause an exception
          list.Add(new Bitmap(1728, 2244,
PixelFormat.Format1bppIndexed));
        }
      }

      // iterate over every page in the list and replace it with a
copy,
      // disposing of the old pages as we go
      for (int i = 0; i < list.Count; i++) {
        // the memory used by the program does not increase
substantially as the program runs
        Debug.WriteLine(string.Format("Page {0}, Memory used: {1}", i
+ 1, System.GC.GetTotalMemory(true)));

        // get a pointer to the old page
        Image oldpage = list[i];

        if (causeOutOfMemoryException) {
          // this is the line that eventually causes the crash
          Bitmap newpage = new Bitmap(oldpage);

          // remove the old page from the collection
          list.RemoveAt(i);

          // insert the new page in the old page's place
          list.Insert(i, newpage);

          // dispose the old page
          oldpage.Dispose();
        }
      }
    }
  }
}
Date:Mon, 13 Aug 2007 11:11:41 -0700   Author:  

Re: ArgumentException and OutOfMemoryException in Bitmap constructor   
1728*2244*4=15,510,528 bytes per image. This is the case for a 32 bits per 
pixel image and is reasonably accurate because 1728 is divisible by four so 
the padding is the same. How many times does the loop run? 15.5 megs per 
image will pretty soon fill up the memory.

The 1bpp format however uses 1728/8*2244 which yields 484704 bytes for the 
image buffer and a few bytes for the palette. You can get roughly 16 times 
more 1bpp images in the same memory.

-- 
-- 
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.


"vector"  wrote in message 
news:1187028701.594048.207260@g4g2000hsf.googlegroups.com...

> I'm trying to write a program that spins through a List collection of
> Image objects and manipulates them.  Unfortunately I keep encountering
> exceptions where I don't understand why they're happening.  I've
> stripped down my app into a sample program that has the same flaws in
> it.
>
> The first exception happens in a loop where I create and add Bitmap
> objects to a List.  The message is "Parameter is not valid," and it
> can be avoided by adding "PixelFormat.Format1bppIndexed" to the Bitmap
> constructor.
>
> The second exception is an out of memory error, where I'm trying in a
> loop to create a deep copy of each Image object in the List,
> manipulate it (but not in the sample code below), and replace the old
> Image in the List with the new Image.
>
> I really don't understand what's going wrong here.  Can someone please
> explain this to me?
>
> using System;
> using System.Drawing;
> using System.Drawing.Imaging;
> using System.IO;
> using System.Diagnostics;
> using System.Collections.Generic;
>
> namespace ConsoleApplication2
> {
>  class Program
>  {
>    [STAThread]
>    static void Main(string[] args)
>    {
>      try {
>        bool causeArgumentException = false;
>        bool causeOutOfMemoryException = true;
>        RunTest(causeArgumentException, causeOutOfMemoryException);
>      }
>      catch (ArgumentException ex) {
>        //A first chance exception of type 'System.ArgumentException'
> occurred in System.Drawing.dll
>        // at System.Drawing.Bitmap..ctor(Int32 width, Int32 height,
> PixelFormat format)
>        // at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
>        // at ConsoleApplication2.Program.RunTest(Boolean
> causeOutOfMemoryException) in c:\source\ImagePro2008\ImagePro
> \Class1.cs:line 49
>        // at ConsoleApplication2.Program.Main(String[] args) in c:
> \source\ImagePro2008\ImagePro\Class1.cs:line 17
>        Debug.WriteLine(ex.StackTrace);
>
>        // Parameter is not valid.
>        Debug.WriteLine(ex.Message);
>      }
>      catch (OutOfMemoryException ex) {
>        // A first chance exception of type
> 'System.OutOfMemoryException' occurred in System.Drawing.dll
>        // at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
>        // at System.Drawing.Graphics.DrawImage(Image image, Int32 x,
> Int32 y, Int32 width, Int32 height)
>        // at System.Drawing.Bitmap..ctor(Image original, Int32 width,
> Int32 height)
>        // at System.Drawing.Bitmap..ctor(Image original)
>        // at ConsoleApplication2.Program.RunTest(Boolean
> causeOutOfMemoryException)
>        // at ConsoleApplication2.Program.Main(String[] args)
>        Debug.WriteLine(ex.StackTrace);
>
>        // Out of memory.
>        Debug.WriteLine(ex.Message);
>      }
>
>      return;
>    }
>
>    private static void RunTest(bool causeArgumentException, bool
> causeOutOfMemoryException)
>    {
>      // the number of test pages to put into the list
>      int numTestPages = 150;
>
>      List<Image> list = new List<Image>();
>
>      // get n unique single-page image objects loaded into our
> collection
>      for (int i = 1; i <= numTestPages; i++) {
>        Debug.WriteLine("Adding page " + i.ToString());
>
>        if (causeArgumentException) {
>          // this exception takes a few loops before it will happen
>          list.Add(new Bitmap(1728, 2244));
>        }
>        else {
>          // this doesn't cause an exception
>          list.Add(new Bitmap(1728, 2244,
> PixelFormat.Format1bppIndexed));
>        }
>      }
>
>      // iterate over every page in the list and replace it with a
> copy,
>      // disposing of the old pages as we go
>      for (int i = 0; i < list.Count; i++) {
>        // the memory used by the program does not increase
> substantially as the program runs
>        Debug.WriteLine(string.Format("Page {0}, Memory used: {1}", i
> + 1, System.GC.GetTotalMemory(true)));
>
>        // get a pointer to the old page
>        Image oldpage = list[i];
>
>        if (causeOutOfMemoryException) {
>          // this is the line that eventually causes the crash
>          Bitmap newpage = new Bitmap(oldpage);
>
>          // remove the old page from the collection
>          list.RemoveAt(i);
>
>          // insert the new page in the old page's place
>          list.Insert(i, newpage);
>
>          // dispose the old page
>          oldpage.Dispose();
>        }
>      }
>    }
>  }
> }
> 
Date:Mon, 13 Aug 2007 21:26:13 +0200   Author:  

Re: ArgumentException and OutOfMemoryException in Bitmap constructor   
On Aug 13, 3:26 pm, "Bob Powell [MVP]" 
wrote:

> 1728*2244*4=15,510,528 bytes per image. This is the case for a 32 bits per
> pixel image and is reasonably accurate because 1728 is divisible by four so
> the padding is the same. How many times does the loop run? 15.5 megs per
> image will pretty soon fill up the memory.


Both loops run 150 times, the value of numTestPages.


> The 1bpp format however uses 1728/8*2244 which yields 484704 bytes for the
> image buffer and a few bytes for the palette. You can get roughly 16 times
> more 1bpp images in the same memory.


I think you've misunderstood the problem.  The first loop -- the one
that populates the List with Bitmap objects -- throws an
ArgumentException, not an OutOfMemoryException, when I don't specify
the PixelFormat.  Why would an ArgumentException be thrown if the
problem is that the images are too large?

The second loop -- the one that replaces the Image objects in the List
with new Bitmaps -- is the one that throws an OutOfMemoryException,
only I don't understand why.  The original Image objects should be
Disposed and garbage collected as the loop runs, taking up no more
memory than they did originally.  That is, if I populated the list in
the first loop, that should be enough proof that the second loop has
all the space it needs.  Using a List of 150 1bpp images, here's a
snippet of the debug output from that failure, which seems to say I
still have plenty of memory to use.  Maybe System.GC.GetTotalMemory
doesn't report what I think it does?

....
Page 119, Memory used: 374068
Page 120, Memory used: 374068
Page 121, Memory used: 374068
A first chance exception of type 'System.OutOfMemoryException'
occurred in System.Drawing.dll
   at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
   at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y,
Int32 width, Int32 height)
   at System.Drawing.Bitmap..ctor(Image original, Int32 width, Int32
height)
   at System.Drawing.Bitmap..ctor(Image original)
   at ConsoleApplication2.Program.RunTest(Boolean
causeArgumentException, Boolean causeOutOfMemoryException) in c:\source
\ImagePro2008\ImagePro\Class1.cs:line 80
   at ConsoleApplication2.Program.Main(String[] args) in c:\source
\ImagePro2008\ImagePro\Class1.cs:line 18
Out of memory.
Date:Mon, 13 Aug 2007 13:23:08 -0700   Author:  

Re: ArgumentException and OutOfMemoryException in Bitmap constructor   

> Why would an ArgumentException be thrown if the
> problem is that the images are too large?


I don't know the answer to that, but I'm quite sure that is your problem. A 
32 bit managed program is limited to ~2GB virtual memory and will typically 
start being prone to running out of memory when it reaches ~1.5GB especially 
when you are asking for large contiguous blocks. You only need to use simple 
arithmetic to determine that what you are attempting is impossible in a 32 
bit environment.

Cheers
Doug Forster
Date:Tue, 14 Aug 2007 08:59:13 +1200   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us