views:

86

answers:

3

I was trying to generate thumbnails using Bitmap.GetThumbnailImage() function for 20+ images in a folder. I could see huge memory spike by the application when it does the following procedure (about 600,000K in Task Manager mem usage).

foreach (var image in ListOfImages)
{
    var thumbnailFolder = @"\thumb";
    var thumbnailFile = thumbnailFolder + "\\" + image.Name;

    if (!Directory.Exists(thumbnailFolder))
    {
        Directory.CreateDirectory(thumbnailFolder);
    }
    if (!File.Exists(thumbnailFile))
    {
        using (FileStream fs = new FileStream(image.FullName, FileMode.Open, FileAccess.Read))
        {
            Image origImage = Image.FromStream(fs);
            var thumbnail = origImage.GetThumbnailImage(90, 120, null, IntPtr.Zero);
            thumbnail.Save(thumbnailFile);
            thumbnail.Dispose();
            origImage.Dispose();
        }
    }
}

Is there any way to reduce this much memory usage for thumbnail generation?

+1  A: 

Do not use Image.FromStream, use Image.FromFile instead for memory reasons. Frankly, I think you'd be better to adapt this example for quality reasons:

http://www.webcosmoforums.com/asp/321-create-high-quality-thumbnail-resize-image-dynamically-asp-net-c-code.html

Nissan Fan
A: 

Give it a try using WPF.

In my experience WPF's image operations quite well optimized (actually it is the WIC library that's being used), and designed with threading in mind, and it does not depend the GDI bitmap handles like GDI+ does. I read once that GDI+ is not supported in server code because it is not entirely leakfree. For your scenario, WPF does not need a 3D video card.

WPF's BitmapDecoder even has built-in thumbnail functionality, which will take advantage of thumbnails in the image itself if available. See http://msdn.microsoft.com/en-us/library/ms750864(VS.85).aspx for basic image tasks in WPF. To access WPF, you need to reference the WindowsBase assembly (.net 3.0 or better).

jdv
In my experience this performs as bad as functions in System.Drawing namespace.
Raj
When you say "as bad", do you you've observed that it also leaks memory for this example?
jdv
No it does not memory leak. But memory usage is as higher as System.Drawing.
Raj
It could be that the memory used temporarily is not reclaimed by the garbage collector, because there is ample memory. Large memory blocks are assumed to stay alive longer. You could force a `System.GC.Collect()` after each image to try this out.
jdv
A: 

I once wrote a blog post on this: Image.GetThumbnailImage and beyond. Maybe you'll find it useful.

danbystrom