Создавайте эскизы изображений и сохраняйте их в кеше - PullRequest
5 голосов
/ 31 декабря 2010

У меня есть приложение WPF со списком изображений. Прямо сейчас я использую BitmapImage и BitmapCacheOption.OnLoad для загрузки изображений. Проблема заключается в том, что при большом количестве изображений использование оперативной памяти ускоряется из-за размера изображений. Как создать миниатюры изображений оригиналов для отображения в списке? Вероятно, его необходимо кэшировать, поскольку файлы изображений в каталоге могут быть удалены или изменены во время работы приложения.

Ответы [ 4 ]

4 голосов
/ 18 апреля 2012

Проблема заключается в том, что при большом количестве изображений использование ОЗУ ускоряется из-за размера изображений.

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 для кэширования изображения с требуемым уменьшенным размером пикселя.Используйте оба, чтобы растянуть изображение до размера миниатюры.

2 голосов
/ 31 декабря 2010

Вы можете создавать приличные растровые изображения большого пальца, используя 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 голосов
/ 31 декабря 2010

Вот метод, который я написал не так давно, который может вам помочь.

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();
    }

Я передаю исходные изображения в двоичном виде и изменяю размер изображения примерно до 160 пикселей.

Надеюсь, это поможет!

0 голосов
/ 31 декабря 2010

После проверки MSDN я не вижу простого способа сделать это, но, возможно, вы могли бы просто сэмплировать изображение каждые несколько пикселей и записать данные в новое изображение, а затем очистить полноразмерное изображение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...