2010-12-31 17 views
5

Tengo una aplicación WPF que tiene un cuadro de lista de imágenes. En este momento estoy usando BitmapImage y BitmapCacheOption.OnLoad para cargar las imágenes. El problema es que cuando hay muchas imágenes, el uso de RAM se dispara debido al tamaño de las imágenes. ¿Cómo puedo crear imágenes en miniatura de los originales para mostrar en el cuadro de lista? Probablemente deba almacenarse en caché, ya que los archivos de imagen en el directorio pueden eliminarse o modificarse mientras la aplicación se está ejecutando.Crear miniaturas de imágenes y almacenarlas en caché

Respuesta

2

Se pueden crear mapas de bits pulgar decente utilizando 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); 
    } 

Si va a crear los pulgares en un subproceso de fondo simplemente guardarlos en una secuencia de memoria que luego se puede utilizar con pereza para crear el BitmapImage cuando se le solicite:

_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; 
     } 
    } 
0

Después de consultar MSDN, no veo ninguna manera directa de hacerlo, pero tal vez podría simplemente muestrear la imagen cada tantos píxeles y escribir los datos en una nueva imagen, y luego limpiar la de tamaño completo.

2

Aquí hay un método que escribí no hace mucho tiempo que puede ser de ayuda.

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

Paso en las imágenes originales en binario, y cambio el tamaño de la imagen para que sea aproximadamente 160px.

Espero que ayude!

4

El problema es que cuando hay muchas imágenes, el uso de RAM se dispara debido al tamaño de las imágenes.

C# ejemplo a partir de: 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; 

Nota las propiedades DecodePixelWidth y DecodePixelHeight a caché de la imagen en el tamaño de píxel reducido deseado. Use ambos para estirar la imagen para que se ajuste al tamaño de la miniatura.

+0

¡Estupendo! Esto hace que cargar las imágenes sea mucho más rápido en mi aplicación y no es necesario que maneje cada imagen en tamaño completo y luego vuelva a escalarla. – ygoe

Cuestiones relacionadas