views:

571

answers:

5

I'm trying to thumb an image as fast as possible regardless of the usage of resources to be used in my ImageList and listview and this is currently how i'm doing it but it seems to be slow:

public Image toThumbs(string file, int width, int height)
        {
            image = null;
            aspectRatio = 1;
            fullSizeImg = null;
            try
            {
                fullSizeImg = Image.FromFile(file);
                float w = fullSizeImg.Width;
                float h = fullSizeImg.Height;
                aspectRatio = w / h;

                int xp = width;
                int yp = height;

                if (fullSizeImg.Width > width && fullSizeImg.Height > height)
                {
                    if ((float)xp / yp > aspectRatio)
                    {
                        xp = (int)(yp * aspectRatio);
                    }
                    else
                    {
                        yp = (int)(xp / aspectRatio);
                    }
                }
                else if (fullSizeImg.Width != 0 && fullSizeImg.Height != 0)
                {
                    xp = fullSizeImg.Width;
                    yp = fullSizeImg.Height;
                }

                image = new Bitmap(width, height);
                graphics = Graphics.FromImage(image);
                graphics.FillRectangle(Brushes.White, ((width - xp) / 2), (height - yp), xp, yp);
                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.DrawImage(fullSizeImg, new Rectangle(((width - xp) / 2), (height - yp), xp, yp));
                graphics.Dispose();
                fullSizeImg.Dispose();
            }
            catch (Exception)
            {
                image = null;
            }
            return image;
        }

I'm not sure if the computation is the one that is slowing down the thumbnailing or maybe the classes itself that are being used are slow, if that is the case then what other alternatives can be use maybe a different computation or i need to import other classes or is there a third party libraries that can be used or i need to do a dll import or something? Please help me.

Edit: Just found a solution here http://www.vbforums.com/showthread.php?t=342386 it extracts a thumbnail from a file without reading the whole file. I was able to reduce the time about 40% when i used this.

+1  A: 

Out of curiosity, have you tried the GetThumbnailImage method on System.Drawing.Bitmap? It might at least be worth comparing to your current implementation.

LorenVS
GetThubnailImage seems to be slower that my code...
murasaki5
A: 

This may seem like to much of an obvious answer but have you tried just using Image.GetThumbnailImage()?

You don't get as much control over the quality of the result but if speed is your main concern?

Nick Allen - Tungle139
but i need to fill the transparency of the image with white so i will still need graphics class.
murasaki5
+3  A: 

Your calculations happen in fractions of a second. The call to DrawImage is most likely the slowest part of this (as that one is doing the scaling).

If you're needing this thumbnail image exactly once then I don't see much room for improvement here. If you're calling that method on the same image more than once, you should cache the thumbnails.

Joey
hmm.. you're right and since i only thumbnail each image once then there seem to be no other way around
murasaki5
If you do this each time your application starts, then you can still cache the thumbnails by storing them in files. Image resampling, especially with large images is really expensive.
Joey
but what if the image was edited? how will i determine that i need to rebuild the thumb since the cache is the older version?
murasaki5
Well, usually this is done by comparing the thumbnail's and the image's last modification date. But yes, caching is always susceptible to the data changing.
Joey
A: 

I use this mechanism which seems to be very fast.

               BitmapFrame bi = BitmapFrame.Create(new Uri(value.ToString()), BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnDemand);

            // If this is a photo there should be a thumbnail image, this is VERY fast
            if (bi.Thumbnail != null)
            {
                return bi.Thumbnail;
            }
            else
            {
                // No thumbnail so make our own (Not so fast)
                BitmapImage bi2 = new BitmapImage();
                bi2.BeginInit();
                bi2.DecodePixelWidth = 100;
                bi2.CacheOption = BitmapCacheOption.OnLoad;
                bi2.UriSource = new Uri(value.ToString());
                bi2.EndInit();
                return bi2;
            }

Hope this helps.

tarantulaman
i think this is a misleading answer since i'm working on a file not a url.
murasaki5
This is using a URI, it can be a path to a file.
tarantulaman
A: 

Your thumbnail extraction that gets you the big speed up relies on the image having a thumbnail already embedded in it.

To speed up the original you might find that changing:-

graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

to

graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;

Might help.

JonB