创建图像缩略图并将其存储在缓存中。

5
我有一个WPF应用程序,其中包含一组图像列表。目前我正在使用BitmapImageBitmapCacheOption.OnLoad来加载这些图像。

问题在于,当图像数量很多时,由于图像的大小,RAM使用量会急剧增加。

我该如何创建原始图像的缩略图以显示在列表框中?

它可能需要被缓存,因为在应用程序运行时,目录中的图像文件可能会被删除或修改。

4个回答

4
当有很多图片时,由于图片的大小,内存使用量飚升是个问题。
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;

请注意 DecodePixelWidth 和 DecodePixelHeight 属性,以在所需的缩小像素大小下缓存图像。使用两者将图像拉伸以适应缩略图大小。

太好了!这使得我的应用程序加载图像更快,我不需要处理每个图像的完整尺寸,然后再将其缩小。 - ygoe

2

您可以使用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);
   }

如果你是在后台线程中创建缩略图,只需将其保存到内存流中,然后在需要时惰性地使用它来创建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;
        }
    }

2
这是我不久前写的一个方法,可能会对你有所帮助。
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();
    }

我传入原始图像二进制,并将图像调整大小为大约160px左右。

希望这能有所帮助!


0

在查看了MSDN之后,我没有找到任何直接的方法来实现这个,但也许你可以每隔一定像素采样图像,并将数据写入新图像,然后清理原始的全尺寸图像。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接