Question

Je viens de recevoir une vraie surprise quand je charge un fichier jpg et fait demi-tour et a sauvé avec une qualité de 100 et la taille était presque 4 fois l'original. Pour étudier plus je ouvert et sauvé sans mettre explicitement la qualité et la taille du fichier était exactement le même. Je pensais que c'était parce que rien n'a changé de sorte qu'il est en train d'écrire les bits exactement le même dos à un fichier. Pour tester cette hypothèse, je dessinais une grande ligne de graisse en diagonale à travers l'image et réenregistré sans réglage de qualité (cette fois je m'y attendais le fichier sauter parce qu'il serait « sale »), mais il a diminué ~ 10Kb!

À ce stade, je ne comprends vraiment pas ce qui se passe quand je l'appelle simplement Image.Save () w / out spécifiant une qualité de compression. Comment est la taille du fichier si proche (une fois l'image modifiée) à la taille d'origine en l'absence de qualité est défini encore quand je mets de qualité à 100 (essentiellement pas de compression) la taille du fichier est plusieurs fois plus grand que l'original?

J'ai lu la documentation sur Image.Save () et il manque aucun détail sur ce qui se passe dans les coulisses. J'ai googlé tous les sens que je peux penser, mais je ne peux trouver aucune information supplémentaire qui expliquerait ce que je vois. Je travaille pendant 31 heures d'affilée alors peut-être que je manque quelque chose d'évident, 0)

Tout cela est venu au sujet pendant que je mettre en œuvre des méthodes bibliothèque pour enregistrer des images à une base de données. Je l'ai surchargée notre méthode « SaveImage » pour permettre la définition explicite d'une qualité et pendant mes tests, je suis tombé sur l'étrange (pour moi) les résultats exposés ci-dessus. Toute la lumière que vous pouvez apporter sera apprécié.

Voici un code qui illustrera ce que je fais l'expérience:

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;
    });
}
Était-ce utile?

La solution

En utilisant le réflecteur, il se trouve Image.Save() se résume à la fonction GDI + GdipSaveImageToFile , avec NULL encoderParams. Je pense donc que la question est ce que l'encodeur JPEG fait quand il obtient une encoderParams nulle. 75% a été suggérée ici, mais je ne peux trouver aucune référence solide.

EDIT Vous pourriez probablement par vous-même en exécutant votre programme ci-dessus pour les valeurs de qualité de 1..100 et en les comparant avec le jpg enregistré avec la qualité par défaut (en utilisant, par exemple, fc.exe / B)

Autres conseils

IIRC, il est de 75%, mais je ne le rappel où je lis cela.

Je ne sais pas beaucoup sur la méthode Image.Save, mais je peux vous dire que l'ajout de cette ligne de graisse serait logicly réduire la taille de l'image jpg. Cela est dû à la façon dont un jpg est enregistré (et codé).

La ligne noire épaisse fait un très simple et plus petit encodage (Si je me souviens bien cela est relevent le plus souvent après la transformée en cosinus discrète), de sorte que l'image modifiée peut être stockée en utilisant moins de données (octets).

jpg encodage étapes

En ce qui concerne les changements de taille (sans la ligne ajoutée), je ne suis pas sûr que l'image que vous et réenregistré réouvert

  

Pour étudier plus je ouvrir et enregistré sans mettre explicitement la qualité et la taille du fichier était exactement le même

Si vous avez ouvert l'ancienne (taille normale d'origine) image et réenregistré, alors peut-être la compression par défaut et la compression d'image d'origine sont les mêmes. Si vous avez ouvert la nouvelle (4X plus grande) image et réenregistré, alors peut-être la compression par défaut pour la méthode de sauvegarde est dérivé de l'image (comme il a été une fois chargé).

Encore une fois, je ne sais pas la méthode de sauvegarde, donc je vais juste jeter des idées (peut-être qu'ils vont vous donner une avance).

Lorsque vous enregistrez une image sous forme de fichier JPEG avec un niveau de qualité de <100%, vous introduisez des objets dans les sauvés-off image, qui sont un effet secondaire du processus de compression. C'est pourquoi re-enregistrement de l'image à 100% ne cesse d'augmenter la taille de votre fichier au-delà de l'original -. Ironie du sort, il y a plus d'informations présentes dans le bitmap

Ceci est également la raison pour laquelle vous devez toujours essayer d'enregistrer dans un format non-lossy (comme PNG) si vous avez l'intention de faire des modifications à votre fichier par la suite, sinon vous serez affecter la qualité de la sortie par plusieurs lossy transformations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top