简体   繁体   English

创建图像的缩略图并将它们存储在缓存中

[英]Create thumbnails of images and store them in cache

I have a WPF application that has a list box of images.我有一个 WPF 应用程序,它有一个图像列表框。 Right now I am using BitmapImage and BitmapCacheOption.OnLoad to load the images.现在我正在使用BitmapImageBitmapCacheOption.OnLoad来加载图像。

The problem is that when there are a lot of images, the RAM usage sky rockets due to the size of the images.问题是当有很多图像时,由于图像的大小,RAM 使用率会飙升。

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.问题是当有很多图像时,由于图像的大小,RAM 使用率会飙升。

C# example from: http://msdn.microsoft.com/en-us/library/ms748873.aspx C# 示例来自: 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.请注意 DecodePixelWidth 和 DecodePixelHeight 属性,以便以所需的缩小像素大小缓存图像。 Use both to stretch the image to fit the thumbnail size.使用两者来拉伸图像以适合缩略图大小。

You can create decent thumb bitmaps using InterpolationMode.HighQualityBicubic您可以使用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:如果您在后台线程中创建缩略图,只需将它们保存到内存流中,然后您就可以在请求时懒惰地使用它来创建BitmapImage

   _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.我传入原始图像二进制文件,并将图像大小调整为大约 160 像素。

Hope it helps!希望有帮助!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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