¿Cómo puedo cambiar el tamaño de una imagen sin que la calidad de la imagen se vea afectada?
¿Cómo puedo cambiar el tamaño de una imagen sin que la calidad de la imagen se vea afectada?
Respuestas:
Como dice rcar , no puede sin perder algo de calidad, lo mejor que puede hacer en c # es:
Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
}
A menos que esté haciendo gráficos vectoriales, no hay forma de cambiar el tamaño de una imagen sin perder potencialmente algo de calidad de imagen.
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
Creo que lo que está buscando hacer es "Cambiar el tamaño / Volver a muestrear" sus imágenes. Aquí hay un buen sitio que brinda instrucciones y proporciona una clase de utilidad (que también uso):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
A menos que cambie el tamaño, no puede hacer esto con gráficos rasterizados.
Lo que puede hacer con un buen filtrado y suavizado es cambiar el tamaño sin perder una calidad notable .
También puede alterar los metadatos DPI de la imagen (suponiendo que tenga algunos), lo que mantendrá exactamente el mismo recuento de píxeles, pero alterará la forma en que los editores de imágenes lo consideran en las mediciones del 'mundo real'.
Y solo para cubrir todas las bases, si realmente se refería solo al tamaño del archivo de la imagen y no a las dimensiones reales de la imagen, le sugiero que mire una codificación sin pérdidas de los datos de la imagen. Mi sugerencia para esto sería volver a guardar la imagen como un archivo .png (tiendo a usar paint como un transcodificador gratuito para imágenes en Windows. Cargar imagen en paint, guardar como en el nuevo formato)
No puede cambiar el tamaño de una imagen sin perder algo de calidad, simplemente porque está reduciendo el número de píxeles.
No reduzca el tamaño del lado del cliente, porque los navegadores no hacen un buen trabajo al cambiar el tamaño de las imágenes.
Lo que puede hacer es cambiar programáticamente el tamaño antes de renderizarlo o cuando un usuario lo carga.
Aquí hay un artículo que explica una forma de hacer esto en c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx
Vea si le gusta la calidad de cambio de tamaño de la imagen de este módulo ASP.NET de código abierto. Hay una demostración en vivo, por lo que puede jugar con ella usted mismo. Produce resultados que son (para mí) imposibles de distinguir de la salida de Photoshop. También tiene tamaños de archivo similares: MS hizo un buen trabajo en su codificador JPEG.
Hay algo ahí fuera, cambio de tamaño consciente del contexto, no sé si podrá usarlo, pero vale la pena mirarlo, eso es seguro
Un buen video de demostración (la ampliación aparece hacia el medio) http://www.youtube.com/watch?v=vIFCV2spKtg
Aquí podría haber algún código. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/
¿Fue exagerado? Tal vez haya algunos filtros fáciles que pueda aplicar a una imagen ampliada para difuminar un poco los píxeles, podría investigar eso.
¿Está cambiando el tamaño más grande o más pequeño? ¿Por un porcentaje pequeño o por un factor mayor como 2x, 3x? ¿Qué quiere decir con calidad para su aplicación? ¿Y qué tipo de imágenes: fotografías, dibujos de líneas bien definidas o qué? ¿Escribir su propio código de pulido de píxeles de bajo nivel o intentar hacerlo tanto como sea posible con las bibliotecas existentes (.net o lo que sea)?
Existe una gran cantidad de conocimientos sobre este tema. El concepto clave es la interpolación.
Recomendaciones de navegación:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* para C #: https: //secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945
* esto es específico de Java pero puede ser educativo - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Aquí puede encontrar también agregar códigos de marca de agua en esta clase:
public class ImageProcessor
{
public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message)
{
try
{
Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth));
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height));
var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205));
double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height);
Rectangle containerBox = new Rectangle();
containerBox.X = (int)(diagonal / 10);
float messageLength = (float)(diagonal / message.Length * 1);
containerBox.Y = -(int)(messageLength / 1.6);
Font stringFont = new Font("verdana", messageLength);
StringFormat sf = new StringFormat();
float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI);
gr.RotateTransform(slope);
gr.DrawString(message, stringFont, myBrush, containerBox, sf);
return newImage;
}
}
catch (Exception exc)
{
throw exc;
}
}
public int Calculations(decimal w1, decimal h1, int newWidth)
{
decimal height = 0;
decimal ratio = 0;
if (newWidth < w1)
{
ratio = w1 / newWidth;
height = h1 / ratio;
return height.To<int>();
}
if (w1 < newWidth)
{
ratio = newWidth / w1;
height = h1 * ratio;
return height.To<int>();
}
return height.To<int>();
}
}
Aquí hay un hilo del foro que proporciona una muestra de código de cambio de tamaño de imagen C #. Puede usar uno de los enlazadores de bibliotecas GD para volver a muestrear en C #.