Size of images in image list

L

lord.zoltar

Hello,
I have an ImageList that will store a large number of images, but if
it starts using too much memory, I'd like to be able to purge it (or
part of it). The problem is, I'm not sure how to determine how much
memory is being used by this object. I've read that Marshal.SizeOf()
can determine the size of the object, but I get an exception:
"Type 'System.Windows.Forms.ImageList+ImageCollection' cannot be
marshaled as an unmanaged structure; no meaningful size or offset can
be computed."
Similar exception when I tried to iterate through the list and call
SizeOf on each Image in the list.

I could add up the sizes of the images as their loaded, but I'm not
sure how to determine the size, in bytes, of an Image object. Is there
a way I could access an Image as an array of bytes and then just look
at it's length?
 
M

Morten Wennevik [C# MVP]

Hello,
I have an ImageList that will store a large number of images, but if
it starts using too much memory, I'd like to be able to purge it (or
part of it). The problem is, I'm not sure how to determine how much
memory is being used by this object. I've read that Marshal.SizeOf()
can determine the size of the object, but I get an exception:
"Type 'System.Windows.Forms.ImageList+ImageCollection' cannot be
marshaled as an unmanaged structure; no meaningful size or offset can
be computed."
Similar exception when I tried to iterate through the list and call
SizeOf on each Image in the list.

I don't think you can easily determine the exact memory size of an image
object as the image will consist of the actual pixel data as well as other
data like possible embedded thumbnail images, exif tags etc. A rough
estimate could be width*height*4 bytes.
I could add up the sizes of the images as their loaded, but I'm not
sure how to determine the size, in bytes, of an Image object. Is there
a way I could access an Image as an array of bytes and then just look
at it's length?

That wouldn't work either as a compressed jpeg image would take up much more
memory than the actual file size would indicate. You could potentially
extract the image width and size from the file data directly and calculate an
estimate from that, but that may easily prove difficult, especially if you
are using different image formats. The jpeg file format isn't particularly
straightforward either. You might be better off loading and disposing one
image at a time and add their estimated memory sizes.

If you tell us what you are planning to use the ImageList for we might be
able to provide alternate solutions.
 
L

lord.zoltar

I don't think you can easily determine the exact memory size of an image
object as the image will consist of the actual pixel data as well as other
data like possible embedded thumbnail images, exif tags etc.  A rough
estimate could be width*height*4 bytes.  


That wouldn't work either as a compressed jpeg image would take up much more
memory than the actual file size would indicate.  You could potentially
extract the image width and size from the file data directly and calculate an
estimate from that, but that may easily prove difficult, especially if you
are using different image formats.  The jpeg file format isn't particularly
straightforward either.  You might be better off loading and disposing one
image at a time and add their estimated memory sizes.

If you tell us what you are planning to use the ImageList for we might be
able to provide alternate solutions.

The image list stores images for image galleries, some of which may be
very large (many images). I wanted to be able to cap the growth of the
ImageList so that if a user navigates from one large gallery to
another, the ImageList won't keep both sets of images in memory, but
if they navigate between small galleries, I DO want to keep all the
images in memory so that the small galleries load faster.
The image data being stored in the ImageList is the thumbnail images
of the full-sized images, so I imagine that EXIF data would have been
removed by that point. I don't know how to estimate the size of those
images (besides w*h*4, but i don't know how accurate that is in this
situation - probably over-estimating?).
 
M

Morten Wennevik [C# MVP]

The image list stores images for image galleries, some of which may be
very large (many images). I wanted to be able to cap the growth of the
ImageList so that if a user navigates from one large gallery to
another, the ImageList won't keep both sets of images in memory, but
if they navigate between small galleries, I DO want to keep all the
images in memory so that the small galleries load faster.
The image data being stored in the ImageList is the thumbnail images
of the full-sized images, so I imagine that EXIF data would have been
removed by that point. I don't know how to estimate the size of those
images (besides w*h*4, but i don't know how accurate that is in this
situation - probably over-estimating?).

I'm afraid the ImageList keeps the reference to the fully exanded image
object as it doesn't create the thumbnail until it needs it. I suppose you
could force it to create thumbnail images immediatly by getting an image
object from every index in the ImageList and then dispose the original
images.

private void AddImageToImageList(string file)
{
using (Image img = Image.FromFile(file))
{
list.Images.Add(img);
Image i = list.Images[list.Images.Count - 1];
}
}

In that case the size of the imagelist would be closer to

list.ImageSize.Width * list.ImageSize.Height * 4 * list.Images.Count

1Kb per image on a 16x16 ImageList pluss a few bytes for the ImageList
object itself as well as the size of the Image references. In real life
there seems to be some overhead and a list with 100 images appeared to use
15-20Kb per image, 1000 images seemed to use somewhere between 3 and 5Kb per
image and a 10000 image list just above 1Kb per image. However, this
solution is slow. Loading and creating thumbnails for 10000 images takes a
couple of minutes on a fast machine.
 
L

lord.zoltar

The image list stores images for image galleries, some of which may be
very large (many images). I wanted to be able to cap the growth of the
ImageList so that if a user navigates from one large gallery to
another, the ImageList won't keep both sets of images in memory, but
if they navigate between small galleries, I DO want to keep all the
images in memory so that the small galleries load faster.
The image data being stored in the ImageList is the thumbnail images
of the full-sized images, so I imagine that EXIF data would have been
removed by that point. I don't know how to estimate the size of those
images (besides w*h*4, but i don't know how accurate that is in this
situation - probably over-estimating?).

I'm afraid the ImageList keeps the reference to the fully exanded image
object as it doesn't create the thumbnail until it needs it.  I supposeyou
could force it to create thumbnail images immediatly by getting an image
object from every index in the ImageList and then dispose the original
images.  

private void AddImageToImageList(string file)
{
    using (Image img = Image.FromFile(file))
    {
        list.Images.Add(img);
        Image i = list.Images[list.Images.Count - 1];
    }

}

In that case the size of the imagelist would be closer to

list.ImageSize.Width * list.ImageSize.Height * 4 * list.Images.Count

1Kb per image on a 16x16 ImageList pluss a few bytes for the ImageList
object itself as well as the size of the Image references.  In real life
there seems to be some overhead and a list with 100 images appeared to use
15-20Kb per image, 1000 images seemed to use somewhere between 3 and 5Kb per
image and a 10000 image list just above 1Kb per image.  However, this
solution is slow.  Loading and creating thumbnails for 10000 images takes a
couple of minutes on a fast machine.

The way I get images into the image list is to load the images files
one at a time, get a thumbnail from that image and save it as a new
Image in the ImageList and then dispose of the Image loaded from file.
You're right - it does take a little longer this way but I'm OK with
that, I just want to have a bit of control over how much space the
ImageList will consume. It seems that the estimation might give me a
good enough approximation, although the thumbnails I display will be
at most 128x128. I guess I'll just have to try it now and see what
happens!
 

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