¿Qué nivel de calidad usa Image.Save () para archivos jpeg?

Me llevé una sorpresa cuando cargué un archivo jpg y lo guardé con una calidad de 100 y el tamaño fue casi 4 veces el original. Para seguir investigando, abrí y guardé sin establecer explícitamente la calidad y el tamaño del archivo era exactamente el mismo. Pensé que esto era porque nada había cambiado, así que solo estaba escribiendo los mismos bits en un archivo. Para probar esta suposición, dibujé una línea grande y gruesa en diagonal sobre la imagen y guardé nuevamente sin establecer la calidad (esta vez esperaba que el archivo saltara porque sería “sucio”) pero disminuyó ~ 10Kb.

En este punto, realmente no entiendo lo que sucede cuando simplemente llamo Image.Save () sin especificar una calidad de compresión. ¿Cómo está tan cerca el tamaño del archivo (después de que se modificó la imagen) al tamaño original cuando aún no se establece la calidad cuando configuro la calidad a 100 (básicamente sin compresión) el tamaño del archivo es varias veces mayor que el original?

He leído la documentación de Image.Save () y me faltan detalles sobre lo que sucede detrás de las escenas. He buscado en Google de todas las formas en que puedo pensar, pero no puedo encontrar ninguna información adicional que explique lo que estoy viendo. He estado trabajando durante 31 horas seguidas, así que tal vez me esté perdiendo algo obvio; 0)

Todo esto se ha producido mientras implementé algunos métodos de biblioteca para guardar imágenes en una base de datos. Sobrecargué nuestro método “SaveImage” para permitir establecer explícitamente una calidad y durante mi prueba me encontré con los resultados impares (para mí) explicados anteriormente. Cualquier luz que puedas arrojar será apreciada.

Aquí hay un código que ilustrará lo que estoy experimentando:

string filename = @"C:\temp\image testing\hh.jpg"; string destPath = @"C:\temp\image testing\"; using(Image image = Image.FromFile(filename)) { ImageCodecInfo codecInfo = ImageUtils.GetEncoderInfo(ImageFormat.Jpeg); // Set the quality EncoderParameters parameters = new EncoderParameters(1); // Quality: 10 parameters.Param[0] = new EncoderParameter( System.Drawing.Imaging.Encoder.Quality, 10L); image.Save(destPath + "10.jpg", codecInfo, parameters); // Quality: 75 parameters.Param[0] = new EncoderParameter( System.Drawing.Imaging.Encoder.Quality, 75L); image.Save(destPath + "75.jpg", codecInfo, parameters); // Quality: 100 parameters.Param[0] = new EncoderParameter( System.Drawing.Imaging.Encoder.Quality, 100L); image.Save(destPath + "100.jpg", codecInfo, parameters); // default image.Save(destPath + "default.jpg", ImageFormat.Jpeg); // Big line across image using (Graphics g = Graphics.FromImage(image)) { using(Pen pen = new Pen(Color.Red, 50F)) { g.DrawLine(pen, 0, 0, image.Width, image.Height); } } image.Save(destPath + "big red line.jpg", ImageFormat.Jpeg); } public static ImageCodecInfo GetEncoderInfo(ImageFormat format) { return ImageCodecInfo.GetImageEncoders().ToList().Find(delegate(ImageCodecInfo codec) { return codec.FormatID == format.Guid; }); } 

Con el reflector, Image.Save() reduce a la función Gdi + GdipSaveImageToFile , con encoderParams NULL. Así que creo que la pregunta es qué hace el codificador JPEG cuando obtiene un encoderParams . Se ha sugerido el 75% aquí, pero no puedo encontrar ninguna referencia sólida.

EDITAR Puede encontrarlo ejecutando el progtwig anterior para valores de calidad de 1..100 y comparándolos con el jpg guardado con la calidad predeterminada (utilizando, por ejemplo, fc.exe / B)

IIRC, es 75%, pero no recuerdo dónde lo leí.

No sé mucho sobre el método Image.Save, pero puedo decir que agregar esa línea grasa reduciría lógicamente el tamaño de la imagen jpg. Esto se debe a la forma en que se guarda (y codifica) un jpg.

La línea negra gruesa crea una encoding muy simple y más pequeña (si mal no recuerdo esto es importante principalmente después de la transformación del coseno discreto), por lo que la imagen modificada se puede almacenar utilizando menos datos (bytes).

jpg pasos de encoding

En cuanto a los cambios en el tamaño (sin la línea añadida), no estoy seguro de qué imagen ha vuelto a abrir y volver a guardar

Para seguir investigando, abrí y guardé sin establecer explícitamente la calidad y el tamaño del archivo era exactamente el mismo

Si abrió la imagen anterior (tamaño normal original) y la volvió a guardar, entonces tal vez la compresión predeterminada y la compresión de la imagen original sean las mismas. Si abrió la nueva imagen (4 veces más grande) y la volvió a guardar, entonces tal vez la compresión predeterminada para el método de guardar se derive de la imagen (como cuando se cargó).

De nuevo, no sé el método de guardar, así que solo estoy lanzando ideas (tal vez te den una pista).

Cuando guarda una imagen como un archivo JPEG con un nivel de calidad de <100%, está introduciendo artefactos en la imagen guardada, que son un efecto secundario del proceso de compresión. Esta es la razón por la que volver a guardar la imagen al 100% aumenta el tamaño del archivo más allá del original; irónicamente, hay más información presente en el mapa de bits.

Esta es también la razón por la cual siempre debe intentar guardar en un formato sin pérdida (como PNG) si tiene la intención de realizar modificaciones en su archivo posteriormente, de lo contrario afectará la calidad del resultado a través de múltiples transformaciones con pérdida.