简体   繁体   中英

Create thumbnails of images and store them in cache

I have a WPF application that has a list box of images. Right now I am using BitmapImage and BitmapCacheOption.OnLoad to load the images.

The problem is that when there are a lot of images, the RAM usage sky rockets due to the size of the images.

How can I create thumbnail images of the originals to display in the list box?

It probably has to be cached since the image files in the directory may be deleted or modified while the application is running.

The problem is that when there are a lot of images, the RAM usage sky rockets due to the size of the images.

C# example from: http://msdn.microsoft.com/en-us/library/ms748873.aspx

// Create source
BitmapImage myBitmapImage = new BitmapImage();

// BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"C:\Water Lilies.jpg");

// To save significant application memory, set the DecodePixelWidth or  
// DecodePixelHeight of the BitmapImage value of the image source to the desired 
// height or width of the rendered image. If you don't do this, the application will 
// cache the image as though it were rendered as its normal size rather then just 
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//
//when you are ready to render the BitmapImage, do:
imageThumb.Source = myBitmapImage;

Note the DecodePixelWidth and DecodePixelHeight properties to cache the image at the desired reduced pixel size. Use both to stretch the image to fit the thumbnail size.

You can create decent thumb bitmaps using InterpolationMode.HighQualityBicubic

   Bitmap bitmap = ...
   Bitmap thumbBitmap = new System.Drawing.Bitmap(thumbWidth, thumbHeight);
   using (Graphics g = Graphics.FromImage(thumbBitmap))
   {
      g.InterpolationMode = InterpolationMode.HighQualityBicubic;
      g.DrawImage(bitmap, 0, 0, thumbWidth, thumbHeight);
   }

If you are creating the thumbs in a background thread just save them into a memory stream which you can then lazily use to create the BitmapImage when requested:

   _ms = new MemoryStream();
   thumbBitmap.Save(_ms, ImageFormat.Png);
   _ms.Position = 0;
   ImageLoaded = true;


    //thumb image property of this class, use in binding  
    public BitmapImage ThumbImage
    {
        get
        {
            if (_thumbImage == null && ImageLoaded)
            {
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = _ms;
                bi.EndInit();
                _thumbImage = bi;
            }
            return _thumbImage;
        }
    }

Here is a method I wrote not too long ago that may help you.

byte[] IImageResizer.CreateThumbnailBytes(byte[] originalImage)
    {
        Image thumbnail = null;

        Image tempImage = Image.FromStream(new MemoryStream(originalImage));

        int desiredWidth = 160;

        int newPixelWidth = tempImage.Width;
        int newPixelHeight = tempImage.Height;

        if (newPixelWidth > desiredWidth)
        {
            float resizePercent = ((float)desiredWidth / (float)tempImage.Width);

            newPixelWidth = (int)(tempImage.Width * resizePercent) + 1;
            newPixelHeight = (int)(tempImage.Height * resizePercent) + 1;
        }

        Bitmap bitmap = new Bitmap(newPixelWidth, newPixelHeight);

        using (Graphics graphics = Graphics.FromImage((Image)bitmap))
        {
            graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            graphics.DrawImage(tempImage, 0, 0, newPixelWidth, newPixelHeight);
        }

        thumbnail = (Image)bitmap;

        MemoryStream ms = new MemoryStream();
        thumbnail.Save(ms, ImageFormat.Jpeg);

        return ms.ToArray();
    }

I pass in the original images binary, and resize the image to be around roughly 160px.

Hope it helps!

检查 MSDN 后,我没有看到任何直接的方法来执行此操作,但也许您可以每隔这么多像素对图像进行采样并将数据写入新图像,然后清理完整尺寸的图像。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM