c# - reducir - Cambiar el tamaño de una imagen sin perder ninguna calidad
como reducir tamaño fotos sin perder calidad (11)
¿Estás cambiando de tamaño más grande o más pequeño? ¿Por un pequeño% o por un factor más grande como 2x, 3x? ¿Qué quiere decir con calidad para su aplicación? ¿Y qué tipo de imágenes: fotografías, dibujos de líneas duras o qué? ¿Escribir su propio código de pulido de píxeles de bajo nivel o tratar de hacerlo tanto como sea posible con las bibliotecas existentes (.net o lo que sea)?
Hay un gran cuerpo de conocimiento 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 para Java pero podría ser educativo - http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Necesito cambiar el tamaño de una imagen, pero la calidad de la imagen no puede verse afectada por esto.
A menos que cambie el tamaño, no puede hacer esto con gráficos de trama.
Lo que puede hacer con un buen filtrado y suavizado es cambiar el tamaño sin perder ninguna calidad notable .
También puede alterar los metadatos DPI de la imagen (suponiendo que tenga algunos) que mantendrán exactamente el mismo número de píxeles, pero alterarán la forma en que los editores de imágenes piensan en las mediciones del "mundo real".
Y para cubrir todas las bases, si realmente quiso decir solo el tamaño del archivo de la imagen y no las dimensiones reales de la imagen, le sugiero que busque una codificación sin pérdida de los datos de la imagen. Mi sugerencia para esto sería volver a guardar la imagen como un archivo .png (tiendo a usar pintura como un transcodificador gratuito para las imágenes en Windows. Cargue la imagen en pintura, guárdela como en el nuevo formato)
A menos que esté haciendo gráficos vectoriales, no hay forma de cambiar el tamaño de una imagen sin perder potencialmente parte de la calidad de la imagen.
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 archivadores de la biblioteca GD para hacer un remuestreo en C #.
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>();
}
}
Como dice rcar , no se puede sin perder calidad, lo mejor que se 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));
}
Creo que lo que estás buscando hacer es "Redimensionar / Volver a muestrear" tus imágenes. Aquí hay un buen sitio que da instrucciones y proporciona una clase de utilidad (que también uso):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
Hay algo por ahí, cambio de tamaño sensible al contexto, no sé si podrás usarlo, pero vale la pena mirarlo, eso es seguro
Una buena demostración de video (la ampliación aparece hacia la mitad) 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/
¿Eso fue excesivo? Tal vez haya algunos filtros fáciles de aplicar a una imagen ampliada para difuminar un poco los píxeles, podrías ver eso.
No puede cambiar el tamaño de una imagen sin perder calidad, simplemente porque está reduciendo el número de píxeles.
No reduzca el tamaño del lado del cliente, ya que los navegadores no hacen un buen trabajo para cambiar el tamaño de las imágenes.
Lo que puede hacer es cambiar programáticamente el tamaño antes de procesarlo, o cuando un usuario lo sube.
Aquí hay un artículo que explica una forma de hacerlo 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 fuente abierta. Hay una demostración en vivo, por lo que puede jugar con usted mismo. Produce resultados que (para mí) son 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.
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;
}