Pregunta

acabo de recibir una verdadera sorpresa cuando he cargado un archivo JPG y di la vuelta y lo ha guardado con una calidad de 100 y el tamaño era casi 4x el original. Para investigar más abierto I y guardado sin establecer explícitamente la calidad y el tamaño del archivo era exactamente la misma. Pensé que esto era porque nada ha cambiado por lo que acaba de escribir los mismos bits exacta de nuevo a un archivo. Para probar esta hipótesis Dibujé una línea de grasa grande en diagonal a través de la imagen y se guarda de nuevo sin el establecimiento de la calidad (esta vez espera que el archivo a saltar porque sería "sucia"), pero disminuyó ~ 10Kb!

En este punto, realmente no entiendo lo que está sucediendo cuando me llamo simplemente Image.Save () w / out especificar una calidad de compresión. Como el tamaño del archivo tan cerca (después de que la imagen se modifica) al tamaño original cuando hay calidad se establece sin embargo, cuando me puse de 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 sobre Image.Save () y que carece de cualquier detalle sobre lo que está sucediendo detrás de las escenas. He buscado en Google en todas direcciones que se me ocurre, pero no puedo encontrar ninguna información adicional que pudiera explicar lo que estoy viendo. He estado trabajando durante 31 horas seguidas así que tal vez me estoy perdiendo algo obvio; 0)

Todo esto ha ocurrido mientras yo implementar algunos métodos de biblioteca para guardar imágenes en una base de datos. He sobrecargado nuestro método "SaveImage" para permitir el establecimiento de una calidad de forma explícita y durante mis pruebas me encontré con el impar (para mí) resultados explicados anteriormente. Cualquier luz que puede arrojar será apreciada.

Aquí hay un código que va a 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;
    });
}
¿Fue útil?

Solución

El uso del reflector, resulta que Image.Save() se reduce a la función GDI + GdipSaveImageToFile , con el NULL encoderParams. Así que creo que la cuestión es lo que hace el codificador JPEG cuando se pone un encoderParams nula. 75% se ha sugerido aquí, pero no puedo encontrar ninguna referencia sólido.

Editar Probablemente se podría averiguar por sí mismo mediante la ejecución de su programa por encima de los valores de calidad de 1..100 y su comparación con el jpg guarda con la calidad predeterminada (usando, por ejemplo, fc.exe / B)

Otros consejos

IIRC, es del 75%, pero yo no recuerdo donde leí esto.

No sé mucho sobre el método Image.Save, pero se puede decir que la adición de esa línea de grasa sería Logicly reducir el tamaño de la imagen jpg. Esto se debe a la forma en que se guarda un archivo JPG (y codificado).

La línea negro grueso hace que para una codificación muy simple y más pequeño (Si recuerdo bien esto es relevante sobre todo después de la transformada discreta del coseno), por lo que la imagen modificada se puede almacenar utilizando menos datos (bytes).

jpg codificación pasos

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

Para investigar más a lo abierto y guardado sin establecer explícitamente la calidad y el tamaño del archivo era exactamente el mismo

Si ha abierto la imagen de la anterior (tamaño normal original) y vuelve a guardar, entonces tal vez el defecto de compresión y la compresión de imagen original son los mismos. Si ha abierto la nueva imagen (4X más grande) y vuelve a guardar, entonces tal vez la compresión por defecto para el método save se deriva de la imagen (como lo fue cuando carga).

Una vez más, no sé el método para guardar, así que sólo estoy lanzando las ideas (tal vez van a darle una ventaja).

Al guardar una imagen como un archivo JPEG con un nivel de calidad de <100%, se están introduciendo objetos en el salvado-off de imágenes, que son un efecto secundario del proceso de compresión. Esta es la razón por la re-guardar la imagen al 100% está aumentando 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 la razón por la que siempre debe intentar guardar en un formato sin pérdidas (como PNG) si tiene la intención de hacer cualquier modificación a su archivo después, de lo contrario estará afectando la calidad de la salida a través de múltiples pérdidas transformaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top