2015-06-16 2 views
2

Мне удалось изменить изображение DateTaken. Но после сохранения изображения размер его изменился. Я проверил с Matlab, и оба байта изображений идентичны.Почему Bitmap.Save меняет размер изображения?

Чтобы проверить, меняется ли изменение свойства, я решил просто открыть файл и сохранить его без изменения каких-либо свойств. Код ниже:

using (var image = new Bitmap(@"C:\Temp\1.jpg")) 
{ 
    image.Save(@"C:\Temp\2.jpg"); 
} 

Но размер по-прежнему меняется. Размер исходного jpeg-изображения 1.jpg: 1.88 MB (1,975,162 bytes). После сохранения его до 2.jpg размер изображения изменяется на 1.86 MB (1,960,824 bytes).

В чем может быть проблема? Хотя Matlab обеспечил мне, что байты изображений не были изменены, я хочу услышать от вас, что Bitmap.Save не должен изменять байты изображения.

+0

Возможно, вы захотите использовать библиотеку EXIF ​​для изменения метаданных, а не для обработки всего изображения. –

ответ

0

JPEG способен переменного сжатия, которая торгует компрессию с против верность оригиналу. Факторы, которые могут влиять на размер, включают:

  1. Конкретный формат JPEG: последовательный или прогрессивный. Последовательный кодирует все данные для компонента в одном сканировании. Progressive кодирует компонент при нескольких сканированиях. Прогрессивный может часто производить большее сжатие. Тем не менее, существует множество настроек, которые применяются к прогрессивному.

  2. Отбор проб. Jpeg позволяет отбирать компоненты Cb и Cb с меньшей скоростью, чем компонент Y. Если вы берете один образец Cb и Cr на каждые два Ys (по вертикали и по горизонтали), вы получаете 1 образец Cb и CR для каждых 4 Y образцов. Это уменьшает объем данных для сжатия от половины от 12 до 6.

  3. Таблицы квантования. Выбор таблицы квантования является основной формой настройки сжатия JPEG. Многие энкодеры скрывают это за настройкой качества.

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

Если вы не скомпонуете с использованием тех же настроек в оригинале, вы получите другой выходной размер.Даже если вы используете одинаковые настройки, вы обычно получаете разные значения из-за округления: JPEG использует вычисления с плавающей запятой, которые округляются до целых чисел.

1

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

Подумайте, возьмете ли вы файл и сжимаете его в формате ZIP, и вы берете тот же файл и сжимаете его в формате RAR. Эти два файла будут иметь разные размеры, но когда они распаковываются, файлы идентичны внутри.

Вы можете прочитать о том, как установить уровень сжатия для изображений here

я копирую код из ссылки для облегчения ссылки:

private void VaryQualityLevel() 
{ 
    // Get a bitmap. 
    Bitmap bmp1 = new Bitmap(@"c:\TestPhoto.jpg"); 
    ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg); 

    // Create an Encoder object based on the GUID 
    // for the Quality parameter category. 
    System.Drawing.Imaging.Encoder myEncoder = 
     System.Drawing.Imaging.Encoder.Quality; 

    // Create an EncoderParameters object. 
    // An EncoderParameters object has an array of EncoderParameter 
    // objects. In this case, there is only one 
    // EncoderParameter object in the array. 
    EncoderParameters myEncoderParameters = new EncoderParameters(1); 

    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L); 
    myEncoderParameters.Param[0] = myEncoderParameter; 
    bmp1.Save(@"c:\TestPhotoQualityFifty.jpg", jpgEncoder, myEncoderParameters); 

    myEncoderParameter = new EncoderParameter(myEncoder, 100L); 
    myEncoderParameters.Param[0] = myEncoderParameter; 
    bmp1.Save(@"c:\TestPhotoQualityHundred.jpg", jpgEncoder, myEncoderParameters); 

    // Save the bitmap as a JPG file with zero quality level compression. 
    myEncoderParameter = new EncoderParameter(myEncoder, 0L); 
    myEncoderParameters.Param[0] = myEncoderParameter; 
    bmp1.Save(@"c:\TestPhotoQualityZero.jpg", jpgEncoder, myEncoderParameters); 

} 
+0

Есть ли возможность открывать, изменять свойство и сохранять с тем же качеством? – theateist

+0

Вы должны быть в состоянии прочитать параметры кодировщика растрового изображения. Затем просто используйте приведенный выше пример, чтобы задать параметры для параметров, которые вы читаете, из оригинала. – Icemanind

+0

Проблема в том, что я не могу использовать 'bmp1.GetEncoderParameterList (jpgEncoder.Clsid);'. Это исключает. Насколько я понимаю, эта ошибка еще не исправлена ​​в Win7. Любые другие предложения? – theateist

Смежные вопросы