¿Generando miniaturas de imágenes en ASP.NET?
asp net crop and resize image (7)
¿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.
He visto varios ejemplos con GDI +, algunos componentes no libres y recuerdo que WPF tiene algunas cosas buenas acerca de las imágenes. GDI + es bastante antiguo y el WPF quizás no tenga beneficios en un entorno de servidor.
Esto tiene que funcionar en una aplicación MVC de ASP.NET que se ejecuta con plena confianza y, si es posible, de forma síncrona.
¿Qué recomendarías?
ACTUALIZAR:
Basándome en la respuesta de Mantorok, he resuelto este ejemplo, pero sigue siendo 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);
}
}
}
Esto me ha ido 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;
}
Estoy usando la herramienta Aurigma Image Uploader. Es un buen control. Pero si se paga se puede consultar aurigma.
No puedo decir si esta es la manera más eficiente, pero aquí hay 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);
}
}
Para el código intensivo del lado del servidor, le sugiero que utilice otras técnicas que no sean GDI + que no hayan sido diseñadas para manejar las imágenes por partes (de forma continua).
Puede usar Windows Imaging Component o WPF para esta tarea. Hay un muy buen ejemplo de cómo hacer esto de manera rápida y, lo que es más importante, escalable aquí:
La forma más rápida de cambiar el tamaño de las imágenes desde ASP.NET. Y es (más) apoyado-ish.
Uso ImageMagick para el procesamiento de fotos
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);
}
Ver mi respuesta aquí Crear imagen en miniatura
Hay una función en la imagen que devuelve una miniatura como esta:
Image image = Image.FromFile(fileName);
Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);
thumb.Save(Path.ChangeExtension(fileName, "thumb"));
http://www.codeproject.com/KB/graphics/image_croppingVBNet.aspx
esto es para el centro de imagen de recorte espero que te ayude más ..