user975060
user975060

Reputation: 335

High performing Bitmap Drawing solution in c#

I have a use case where I need to render a collage of bitmaps as a preview. The application is implemented as a MVC based REST service, and I have a fairly vanilla implementation:

using (var bitmap = new Bitmap((int)maxWidth, (int)maxHeight))
{
using (var graphic = Graphics.FromImage(bitmap))
{
    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;

    // now again for each mod
    foreach (var mod in mods)
    {
        var frame = frames.First(f => f.Index == mod.FrameIndex);
        var fileInfo = GetFileInfo(mod);
        using (var modImage = Image.FromFile(fileInfo.FullName))
        {
            graphic.DrawImage(modImage, (int)frame.Left, (int)frame.Top);
        }
    }

    bitmap.Save(previewFileName);
}
}

While this code works fine, it performs very poorly (especially with larger images). I am open to using third party libraries as well, I just need a faster performing solution.

Any help would be mostly appreciated.

Update

To clarify the use case, caching doesn't help. These images are uploaded by the customer, then they request a preview of the selected collage. It's the writing of the images to the collage that is slow.

Upvotes: 0

Views: 1725

Answers (3)

wexman
wexman

Reputation: 1305

I just now realized that you're drawing the modImages in their original size (because you're using the override that only takes a left and top coordinate). If that's what you want, you could as well just use the DrawImageUnscaled()-Method of the graphics class, that should be much faster:

    var frame = frames.First(f => f.Index == mod.FrameIndex);
    var fileInfo = GetFileInfo(mod);
    using (var modImage = Image.FromFile(fileInfo.FullName))
    {
        graphic.DrawImageUnscaled(modImage, (int)frame.Left, (int)frame.Top);
    }

Upvotes: 1

David C
David C

Reputation: 3810

If you have a static number of Thumbnails, similar to Netflix, I would create a Cache in memory that keeps the thumbnail bitmaps. This could even be a static object. Once you have generated the thumbnail, you never need to generate it again. It would be a cleaner approach than trying to find a faster hammer to hit it with every time.

Example :

if(MyThumbnailImageDictionary["whateverimageId"] != null)
   return (Bitmap)MyThumbnailImageDictionary["whateverimageId"];

If the thumbnails are dynamic such as from a user uploading random pictures, then this method will not help as the size of the image cache will grow tremendous.

You can use the following code to generate a Thubnail, but I am not sure how much faster it would be :

 Image image = Image.FromFile(fileName);
 Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);

Upvotes: 0

wexman
wexman

Reputation: 1305

How important is the image quality? If you need faster results, you should try InterpolationMode.NearestNeighbour, this should be much faster, but results will be rather low-quality. HeighQualityBicubic (what you're currently using) produces best results, but at lowest performance.

Upvotes: 0

Related Questions