2011-05-04 16 views
16

¿Cuál es la forma más rápida y confiable de generar miniaturas en .NET? Necesito obtener cualquier imagen, comprimirla en JPEG y cambiar su tamaño.¿Genera miniaturas de imágenes en ASP.NET?

He visto varios ejemplos con GDI +, algunos componentes no libres y recuerdo que WPF tiene algunas cosas buenas acerca de la creación de imágenes. GDI + es bastante viejo y las cosas de WPF quizás no tengan ningún beneficio en el entorno de un servidor.

Esto tiene que funcionar en una aplicación ASP.NET MVC que se ejecute con plena confianza y, si es posible, sincrónicamente.

¿Qué recomendarías?

ACTUALIZACIÓN:

Basado en Mantorok's answer he trabajado a cabo este ejemplo, pero aún así es GDI +, y se bloquea si lo intento con una imagen grande:

public void GenerateThumbnail(String filename, Int32? desiredWidth, 
    Int32? desiredHeight, Int64 quality, Stream s) 
{ 
    using (Image image = Image.FromFile(filename)) 
    { 
     Int32 width=0, height=0; 

     if ((!desiredHeight.HasValue && !desiredWidth.HasValue) || 
      (desiredHeight.HasValue && desiredWidth.HasValue)) 
      throw new ArgumentException(
       "You have to specify a desired width OR a desired height"); 

     if (desiredHeight.HasValue) 
     { 
      width = (desiredHeight.Value * image.Width)/image.Height; 
      height = desiredHeight.Value; 
     } 
     else 
     { 
      height = (desiredWidth.Value * image.Height)/image.Width; 
      width = desiredWidth.Value; 
     } 

     using (var newImage = new Bitmap(width, height)) 
     using (var graphics = Graphics.FromImage(newImage)) 
     using (EncoderParameter qualityParam = 
      new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 
       quality)) 
     using (EncoderParameters encoderParams = new EncoderParameters(1)) 
     { 
      graphics.DrawImage(image, 0, 0, width, height); 
      ImageCodecInfo jpegCodec = ImageCodecInfo.GetImageEncoders(). 
       Single(e => e.MimeType.Equals("image/jpeg", 
        StringComparison.Ordinal)); 
      encoderParams.Param[0] = qualityParam; 
      newImage.Save(s, jpegCodec, encoderParams); 
     } 
    } 
} 
+0

Lo que se está lanzando la excepción? – Mantorok

+0

OutOfMemoryException en Image.FromFile (nombre de archivo) – vtortola

+0

Blimey! ¿¡Qué tan grande es el archivo!? – Mantorok

Respuesta

5

Para obtener un código intensivo del lado del servidor, le sugiero que utilice otras técnicas además de GDI + que no se haya diseñado para manejar imágenes s pedazo por pedazo (en forma de transmisión).

Puede usar Windows Imaging Component o WPF para esta tarea. Hay un muy buen ejemplo de cómo hacer esto de una forma rápida y - más importante - de forma escalable aquí:

The fastest way to resize images from ASP.NET. And it’s (more) supported-ish.

+0

¡Eso es genial, gracias! – vtortola

+0

La biblioteca http://imageresizing.net ahora ofrece cambio de tamaño basado en WIC. Es más rápido que el código de muestra de Bertrand al que está enlazando y administra la memoria correctamente. Es muy simple y fácil de usar. –

2

no puedo decir si esta es la manera más eficiente, pero aquí es un fragmento de código que escribí para producir 3 imágenes más pequeñas de una imagen grande:

private void GenerateImages(byte[] data, string extension, string filename) 
    { 
    // Assuming data is the original filename. 
    var ms = new MemoryStream(data); 
    var image = Image.FromStream(ms); 
    image.Save(filename); 
    ResizeImage(image, 800, 600, "large.jpg"); 
    ResizeImage(image, 480, 320, "medium.jpg"); 
    ResizeImage(image, 192, 144, "small.jpg"); 
    } 

    private void ResizeImage(Image image, int width, int height, string filename) 
    { 
    using (var newImage = new Bitmap(width, height)) 
    { 
     var graphics = Graphics.FromImage(newImage); 
     graphics.DrawImage(image, 0, 0, width, height); 
     newImage.Save(filename, ImageFormat.Jpeg); 
    } 
    } 
3

utilizo ImageMagick para el procesamiento de fotografías

ACTUALIZADO

Modelo:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.IO; 
using ImageMagickObject; 

namespace photostorage.Models 
{ 
    public class PhotoProcessing 
    { 
     public MagickImage ResizeImg(string filepath, string filename) 
     { 
      Object[] rotate = new Object[] { filepath + "/" + filename, 
       "-auto-orient", filepath + "/" + filename }; 
      Object[] big = new Object[] { filepath + "/" + filename, 
       "-resize", "800", filepath + "/" + "big_" + filename }; 
      Object[] middle = new Object[] { filepath + "/big_" + filename, 
       "-resize", "400", filepath + "/" + "mid_" + filename }; 
      Object[] small = new Object[] { filepath + "/mid_" + filename, 
       "-resize", "200", filepath + "/" + "small_" + filename }; 
      Object[] crop = new Object[] { filepath + "/small_" + filename, 
       "-resize", "50", filepath + "/" + "crop_" + filename }; 
      ImageMagickObject.MagickImage img = 
       new ImageMagickObject.MagickImage(); 
      img.Convert(rotate); 
      img.Convert(big); 
      img.Convert(middle); 
      img.Convert(small); 
      img.Convert(crop); 
      return img; 
     } 
    } 
} 

controlador:

PhotoProcessing resizeImg = new PhotoProcessing(); 
[HttpPost] 
public string Index(params,params,params...) 
{ 
    var GetResize = resizeImg.ResizeImg(
     destinationFolder + "/" + curFolder, fullFileName); 
} 
+0

¿Cómo se usa? Encontré un contenedor .net, pero no está documentado y las clases que mencionas no existen en él. – vtortola

+0

no uso ImageMagick.NET - uso el dll ImageMagickObject (porque, como usted escribió, el .Net vertion está completamente indocumentado). Espere un minuto, pondré la solución completa aquí –

+0

compruebe la actualización –

0

estoy usando la herramienta Imagen subida por Aurigma. es un control bastante bueno. pero se paga se puede comprobar aurigma

3

Véase mi respuesta aquí Create thumbnail image

Hay una función en la imagen que devuelve una imagen en miniatura de esta manera:

Image image = Image.FromFile(fileName); 
Image thumb = image.GetThumbnailImage(120, 120,()=>false, IntPtr.Zero); 
thumb.Save(Path.ChangeExtension(fileName, "thumb")); 
6

Esto me ha hecho muy bien durante años:

public static void CreateThumbnail(string filename, int desiredWidth, int desiredHeight, string outFilename) 
{ 
    using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename)) 
    { 
     float widthRatio = (float)img.Width/(float)desiredWidth; 
     float heightRatio = (float)img.Height/(float)desiredHeight; 
     // Resize to the greatest ratio 
     float ratio = heightRatio > widthRatio ? heightRatio : widthRatio; 
     int newWidth = Convert.ToInt32(Math.Floor((float)img.Width/ratio)); 
     int newHeight = Convert.ToInt32(Math.Floor((float)img.Height/ratio)); 
     using (System.Drawing.Image thumb = img.GetThumbnailImage(newWidth, newHeight, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailImageAbortCallback), IntPtr.Zero)) 
     { 
      thumb.Save(outFilename, System.Drawing.Imaging.ImageFormat.Jpeg); 
     } 
    } 
} 

public static bool ThumbnailImageAbortCallback() 
{ 
    return true; 
} 
+0

simple y elegante; Estoy robando esto con certeza :) – kite

+0

Probar eso con una imagen grande, sin embargo. 1920 * 60000, por ejemplo. No es lo suficientemente robusto – TEK

Cuestiones relacionadas