c# - reducir - ¿El cambio de tamaño de las imágenes JPEG afecta su compresión?
programa para reducir tamaño de fotos (8)
Cambiar el tamaño de una imagen afecta la compresión, si por "compresión" se refiere a cuántos detalles se pueden ajustar en cuántos píxeles.
El algoritmo de compresión JPEG favorece imágenes borrosas u homogéneas con degradados y parches planos de colores. Por lo tanto, no existe una correlación directa entre las dimensiones de la imagen y el tamaño del archivo resultante. Lo que más importa es la cantidad de detalles en la imagen (todas las imágenes se guardaron como JPEG con un factor de pérdida del 80%):
El logotipo SO original:
Original http://magnetiq.com/exports/sologo/original.jpg
File size: 4,483 bytes
Conserva las dimensiones y aplica un desenfoque Gaussiano pesado:
Borrosa http://magnetiq.com/exports/sologo/blurred.jpg
File size: 1,578 bytes
Cambiar el tamaño del original a 1/4:
Shrunk http://magnetiq.com/exports/sologo/shrunk.jpg
File size: 2,063 bytes
Tenga en cuenta que la imagen borrosa (2), aunque es 4 veces más grande que la reducida (3), es más pequeña en tamaño de archivo que (1) y (2). La borrosidad agrega agradables gradientes que hacen feliz la compresión JPEG.
La imagen pequeña (3), aunque solo tiene 1/4 de los píxeles que tiene el original (1), no es 1/4 del tamaño del archivo. Esto se debe a que la reducción de la imagen da como resultado detalles más finos y a la compresión JPEG no le gusta eso.
Estoy redimensionando jpegs usando el método Graphics.DrawImage (ver fragmento de código a continuación). ¿Alguien puede confirmar que esto no afectará la compresión de la nueva imagen? He visto este hilo , pero estoy hablando específicamente sobre la compresión de jpegs.
private byte[] getResizedImage(String url, int newWidth)
{
Bitmap bmpOut = null;
System.IO.MemoryStream outStream = new System.IO.MemoryStream();
//input image is disposable
using (Bitmap inputImage = LoadImageFromURL(url))
{
ImageFormat format = inputImage.RawFormat;
decimal ratio; //ratio old width:new width
int newHeight = 0;
//*** If the image is smaller than a thumbnail just return it
if (inputImage.Width < newWidth)
return null;
ratio = (decimal)newWidth / inputImage.Width;
decimal h = inputImage.Height * ratio;
newHeight = (int)h;
bmpOut = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// try testing with following options:
//g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
//g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
//g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
g.DrawImage(inputImage, 0, 0, newWidth, newHeight);
bmpOut.Save(outStream, getImageFormat(url));
}
return outStream.ToArray();
}
Cuando llamas "bmpOut.Save" tienes que pasar algunos EncoderParameters para indicarle al método con qué nivel de calidad te gustaría guardarlo.
http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameters(VS.80).aspx
En su código " HighQualityBicubic
" está la compresión que está utilizando. Cambiar el tamaño a un tamaño más pequeño elimina los detalles, pero eso no tiene nada que ver con la compresión, solo tiene que ver con menos píxeles.
Gracias a MrZebra quien me dio un empujón en la dirección correcta. Este artículo demuestra bastante bien qué hacer.
Igual que lo que ya encontraste, pero aquí está la versión de VB.NET de Circumventing GDI + compresión de imagen predeterminada .
Yo personalmente recomiendo la configuración de calidad JPEG de 90L.
La compresión JPEG es con pérdida : no todos los datos originales se almacenan exactamente. Si comprime una imagen como JPEG y la descomprime, no obtendrá la imagen original exacta. Cada vez que comprime y descomprime, pierde un poco de calidad.
Para algunas transformaciones simples, como girar un JPEG, puede hacerlo sin pérdidas con programas como jpegtran .
Sin embargo, para cambiar el tamaño de las imágenes, no puede hacerlo sin pérdidas. Definitivamente vas a degradar la calidad un poco cuando haces esto, aunque probablemente no por mucho. Si es posible, intente utilizar imágenes sin pérdida originales como fuente de la operación de cambio de tamaño para obtener la calidad más alta posible, y si concatenan varias operaciones de cambio de tamaño, en su lugar, solo realicen un cambio de tamaño único del original.
Los archivos JPEG no tienen guardado ningún valor de "compresión". Cuando cambia el tamaño y los guarda, se comprimen con cualquier valor que le indique a su función de guardar para usar. Como no está pasando un valor, solo usará el valor predeterminado para la biblioteca.
No confunda el formato de almacenamiento (JPEG) con el formato en el que opera utilizando el objeto Graphics
. El formato de almacenamiento está comprimido, el objeto Graphics
funciona con datos descomprimidos.
El método LoadImageFromURL
descomprime la información almacenada en JPEG, realiza su operación de cambio de tamaño en los datos descomprimidos, y cuando la guarda en un archivo JPEG, se vuelve a comprimir.
Como la compresión JPEG no es sin pérdida, la calidad de la imagen se reducirá cada vez que realice este proceso: Descomprimir, mutar, volver a comprimir .
Si no entendí bien tu pregunta: El factor de compresión que usas para guardar la imagen no se establece en tu código, por lo que tendrá un valor predeterminado. Si desea reducir la pérdida de calidad al guardar con un factor de compresión pequeño, debe configurarlo explícitamente.