Какой уровень качества использует image.save () для файлов JPEG?
-
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 сохраняется (и кодируется).
Толстая черная линия делает для очень простого и меньшего кодирования (если я правильно запомню, это речектируют в основном после дискретной трансформации косинуса), поэтому модифицированное изображение может быть сохранено с использованием меньшего количества данных (байт).
Что касается изменений в размере (без добавленной строки), я не уверен, какое изображение вы открывали и возобновили
Для дальнейшего расследования я открываю и сохранюсь без явного установления качества и размер файла был точно таким же
Если вы открыли изображение старого (оригинального нормального размера) и возобновило его, то, возможно, сжатие по умолчанию и исходное сжатие изображения одинаковы. Если вы открыли новое (4x большее изображение) и возобновите его, то, возможно, сжатие по умолчанию для метода сохранения происходит от изображения (как это было при нагрузке).
Опять же, я не знаю метод сохранения, поэтому я просто бросаю идеи (может быть, они дадут вам повод).
Когда вы сохраняете изображение в качестве файла JPEG с уровнем качества <100%, вы представляете артефакты в сохраненное изображение, которые являются побочным эффектом процесса сжатия. Вот почему восстановление изображения на 100% на самом деле увеличивается размер вашего файла за пределами оригинала - по иронии судьбы есть больше информации, присутствующей в растровом изображении.
Это также, поэтому вы всегда должны пытаться сохранить в формате без потерь (например, PNG), если вы намерены выполнять какие-либо изменения к вашему файлу впоследствии, в противном случае вы будете влиять на качество выхода через несколько преобразований с потерями.