WinForms / C #: implementing a long scrollable list of images explodes memory

I am trying to upload jpg images as a long list of image blocks into a table layout panel. The list of images should be scrollable smoothly, i.e. No flickering or visible blurring or smoothing. There are about 300 images, each about 150kb in size (600px x 850px).

The problem is that when loading images into the panel, the memory (RAM) is much more exploded than it should be (considered the size of the image files). If the list is loaded, about 500 MB are locked in memory, but images should be about 300 x 150 kb = 45 MB.

It doesn’t matter if I upload the image to the box directly or as a MemoryStream: The result of loading the memory is the same.

So, something explodes my memory load, in a volume exceeding 10 times more than the image files are needed.

Question: how can I get a memory load of about 100 MB without changing the image quality or image size. Anyone have a good idea?

Thank you in advance

Rockie

+4
source share
1 answer

The size of your jpg images in memory is the memory used by uncompressed images.

MemorySize = w * h * (number of images) * (3 or 4 bytes) -> w, h is in pixels 

3 bytes or 24 bits for images without transparency and 4 bytes for images with transparency. This is 8 bits per channel (red, green, blue, transparent) per pixel.

So in your case this is:

 MemorySize = 600 * 850 * 300 * 3 = 459000000 bytes ~ 440 MB 

The only solution that allows memory up to 100 MB was to download only the first 70 images and load the desired images after the user scrolls further, while at the same time deleting the images from above.

Tell me if there are n images in each line, and k lines are visible. Better to say, first download the first n * (k+2) images. Then, when the user scrolls below the line, delete the images in an invisible line and load the following line / line images. To do this, add some EventHandler to scroll through the event.

Update
A google search for bitmap compressed memory, I found this:
http://www.codeproject.com/KB/graphics/CompressibleImage.aspx

Check this, it can save time when downloading images from the disk, then you only unpack them at runtime, thereby saving disk access time.

I just tried this class in a sample project and updated the answer with the results.

Update 2

I tested the CompressibleImage class and its performance.
But since it re-compresses your image, which is already compressed by JPEG, this can lead to some loss of quality.
To do this, I added an extra class to the class that stores bytes of raw files directly in the compressed class stream variable. Therefore, add the following constructor and it should work without quality loss due to repeated compression:

 public CompressibleImage(string fileName, bool alreadyCompressed){ if (alreadyCompressed) this.stream = new MemoryStream(File.ReadAllBytes(fileName)); else this.decompressed = Image.FromFile(fileName); } 

Then you can use the class as follows:

 // to load image in compressed format, where filename points to a JPG // and the second argument as true tells that the image is already compressed CompressibleImage ci = new CompressibleImage(filename, true); // to display in a PictureBox pictureBox1.Image = ci.GetDecompressedImage(); // to free image memory once out of view pictureBox1.Image = null; ci.ClearDecompressedImage(); // force Garbage Collector, do this after removing a whole row of images, // as by default GC is not called immediately but only when needed, so // this forces GC and reclaims memory from just freed images immediately GC.Collect(); 

Try and see if there is a loss of quality or stutter when scrolling

+7
source

All Articles