Какой уровень качества использует image.save () для файлов JPEG?

StackOverflow https://stackoverflow.com/questions/3957477

  •  08-10-2019
  •  | 
  •  

Вопрос

Я только что получил настоящий сюрприз, когда я загрузил файл JPG и обернулся и сохранил его с качеством 100, а размер был почти 4x оригинал. Чтобы дополнительно расследовать я открываю и сохраняю без явного установления качества и размер файла был точно таким же. Я полагал, что это потому, что ничего не изменилось, так что он просто пишет то же самое те же биты обратно в файл. Чтобы проверить это предположение, я нарисовал большую жилую линию по диагонали по изображению и снова сохранил, без настройки качества (на этот раз я ожидал, что файл подпрыгивает, потому что он был бы «грязным»), но он уменьшился ~ 10 кБ!

На данный момент я действительно не понимаю, что происходит, когда я просто называю image.save () w / out Указание качества сжатия. Как размер файла настолько близкий (после того, как изображение модифицировано) к исходному размеру, когда качество не установлено, когда я устанавливаю качество на 100 (в основном без сжатия) размер файла в несколько раз больше, чем оригинал?

Я прочитал документацию на Image.save (), и он отсутствует каких-либо деталей о том, что происходит за кулисами. Я поглотил каждый, о чем я могу думать, но я не могу найти какую-либо дополнительную информацию, которая объяснила бы, что я вижу. Я работаю в течение 31 часа прямо, так что, возможно, я скучаю с чем-то очевидным; 0)

Все это произошло во время реализации некоторых методов библиотеки для сохранения изображений в базу данных. Я перегружал наш метод «AvazyImage», чтобы позволить явно установить качество, и во время моего тестирования я наткнулся на нечетные (для меня) результаты, объясненные выше. Любой свет, который вы можете пролить, будут оценены.

Вот какой-то код, который проиллюстрирует то, что я испытываю:

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;
    });
}
Это было полезно?

Решение

Использование отражателя, оказывается Image.Save() сводится к функции GDI + GDIPSAVIMAGETOFILE., с encoderParams НУЛЕВОЙ. Так что я думаю, что вопрос в том, что дает кодировщик JPEG, когда он получает нуль encoderParams. Отказ Здесь было предложено 75%, но я не могу найти какую-либо твердую ссылку.

РЕДАКТИРОВАТЬ Возможно, вы можете узнать для себя, запустив вашу программу выше для значений качества 1..100 и сравнивая их с JPG, сохраненным с качеством по умолчанию (используя, скажем, fc.exe / b)

Другие советы

IIRC, это 75%, но я не вспоминаю, где я прочитал это.

Я не знаю много о Image.save Method, но я могу сказать вам, что добавление этой жирной линии логично уменьшит размер изображения JPG. Это связано с тем, как A JPG сохраняется (и кодируется).

Толстая черная линия делает для очень простого и меньшего кодирования (если я правильно запомню, это речектируют в основном после дискретной трансформации косинуса), поэтому модифицированное изображение может быть сохранено с использованием меньшего количества данных (байт).

JPG кодирование шагов

Что касается изменений в размере (без добавленной строки), я не уверен, какое изображение вы открывали и возобновили

Для дальнейшего расследования я открываю и сохранюсь без явного установления качества и размер файла был точно таким же

Если вы открыли изображение старого (оригинального нормального размера) и возобновило его, то, возможно, сжатие по умолчанию и исходное сжатие изображения одинаковы. Если вы открыли новое (4x большее изображение) и возобновите его, то, возможно, сжатие по умолчанию для метода сохранения происходит от изображения (как это было при нагрузке).

Опять же, я не знаю метод сохранения, поэтому я просто бросаю идеи (может быть, они дадут вам повод).

Когда вы сохраняете изображение в качестве файла JPEG с уровнем качества <100%, вы представляете артефакты в сохраненное изображение, которые являются побочным эффектом процесса сжатия. Вот почему восстановление изображения на 100% на самом деле увеличивается размер вашего файла за пределами оригинала - по иронии судьбы есть больше информации, присутствующей в растровом изображении.

Это также, поэтому вы всегда должны пытаться сохранить в формате без потерь (например, PNG), если вы намерены выполнять какие-либо изменения к вашему файлу впоследствии, в противном случае вы будете влиять на качество выхода через несколько преобразований с потерями.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top