PictureBox control memory and speed BIG problem

G

Guest

I’m writing a Windows application.
In the form I have a Panel and inside the panel I have a PictureBox control.
I’m loading the PictureBox control with BMP image that has the following
criteria:
14174 x 7874 Pixels (111.61MPixels), 1 BitsPerPixel, 3200x3200 DPI, No
Compression.
The memory consumption for loading this image should be 13.31 MB (13,952,776
Bytes) (this is what IrfanView takes, http://www.irfanview.com/).

I’m loading the BMP file like that:
pictureBox1.Image = Image.FromFile("MyFileName.bmp", true);
// - or -
//pictureBox1.Image = Image.FromFile("MyFileName.bmp");
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Width = pictureBox1.Image.Width;
pictureBox1.Height = pictureBox1.Image.Height;

And this way, I get image scrolling for free (see
http://www.codeproject.com/cs/miscctrl/PictureBox.asp).

After I load the image, the memory usage of my application is about 50 MB
according to the Windows ‘Task Manager’.

The trouble is that every time I try to move any scroll bar, or showing the
image after hiding it (or part of it) with another window, it redraws itself
very very slowly and the memory usage jump up to 430 MB for a few seconds.

I’m running this application on a Pentium 4 processor 2.4GHz and 1.5 GB RAM.


Can anybody tell me why this is happening and how can I make it run much
much faster with no memory eating?
 
K

Kevin Yu [MSFT]

Hi Sharon,

When you load the image into memory, GDI+ is allocating the memory it needs
to store the image. Then, when you start to draw to the image, it creates
a new image buffer of the same size (hence the doubling of the memory).

There isn't much you could do here, unless you can break the image down
into smaller images and process those.

You can also try to post in microsoft.public.win32.programmer.gdi newsgroup.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
G

Guest

Hi Kevin,

I can leave with twice the memory for every redraw, but it’s eating 10 times
the amount of memory for every redraw (from less then 50 MB to 430 MB).

I suspect that for every redraw it convert the image from 1 bit per pixel to
1 byte per pixel, therefore multiplying the memory consumption at least by 8.
It this is what happening, it’s very bad. It means that the PicturePox
control can work only with very small images.

But what about larger images? Isn’t there a .NET control that I can use for
them?
 
W

Willy Denoyette [MVP]

Sharon said:
Hi Kevin,

I can leave with twice the memory for every redraw, but it’s eating 10
times
the amount of memory for every redraw (from less then 50 MB to 430 MB).

I suspect that for every redraw it convert the image from 1 bit per pixel
to
1 byte per pixel, therefore multiplying the memory consumption at least by
8.
It this is what happening, it’s very bad. It means that the PicturePox
control can work only with very small images.

But what about larger images? Isn’t there a .NET control that I can use
for
them?


A redraw of a loaded image does not change the memory consumption.
As I told you before, when you call Image.FromFile(), GDI+ loads the
Filedata into memory and builds an internal Image object from it (done by
GDI+ function - GdipImageForceValidation()), that means that you need aprox.
twice the memory (depending the pix. format and type of the file).

If you don't want this to happen, you can load the image from a stream like
this:

fs = new FileStream(value, FileMode.Open, FileAccess.ReadWrite);
Image = Image.FromStream(fs, false, false); // set third arg. to false to
prevent GdipImageForceValidation to be called.

This has the advantage that the internal buffer is not created and the
memory taken depends on the size of the portion actually drawn, but the
disadvantage is that it's terrible slow when redrawing (scrolling etc...),
because the drawing engine has to read the pixeldata from the underlying
stream and convert it to a bitmap each time the "view" changes.

Anyway, it looks like you are trying to use the PictureBox control for other
purposes than it was designed for, that is being a static container for
simple reasonable sized images (smaller than the form or containing
control). What you are trying is to do is use this control to display much
larger images and hope that you can scroll real fast when the control area
is smaller than the image size.
I don't think you will find a .NET control that fits this purpose, I doubt
that such control can even be built using GDI+.

Willy.
 
G

Guest

Hello again Willy,

Thanks for your help.

I changed my code to load the image from stream as you posted and indeed it
is working smoothly with image I mentioned.
But now, it takes much more then the twice the memory, it consumes 437 MB
(20 MB before loading the image, and 457 MB after loading the image).
As I mentioned before, the image is BMP 14174 x 7874 pixels (111.61
MPixels), 1 bits per pixel, 3200x3200 DPI, No Compression and the memory
consumption for loading this image should be 13.31 MB.

So I tested to se its limit I tried to load the same image but sized 15748 x
28348 pixels (should take 53.23 MB (55,810,960 Bytes)), but I get
successfully exception (strange one): System.ComponentModel.Win32Exception
{The operation completed successfully}
Thrown by the
System.Windows.Forms.DibGraphicsBufferManager.CreateCompatibleDIB(IntPtr hdc,
IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits)

Do you know that one?

I guess that the control convert the image from 1 bit per pixel to 1 byte
per pixel, it’s the only explanation I can imagine for that amount of memory
consumption. Still it doesn’t explain the so large memory it takes.

Can you elaborate on that?

If I can not use the PictureBox control for this kind of images, how can I
do that in any other way?
 
K

Kevin Yu [MSFT]

Hi Sharon,

In this case, you might need some third party components which have better
performance on large pictures. Or you have to write your own control to
display and scroll.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top