Если изображение вращается без потерь, почему размер файла изменяется?

37

Я искал способы поворота изображения без потерь и натолкнулся на этот вопрос, который довольно хорошо объясняет это:

Являются ли «Windows Photo Viewer» вращения без потерь?

Итак, я создал 256 × 256 JPEG со случайными пикселями (облачный фильтр Photoshop), а затем повернул его с помощью Windows Picture Viewer. После поворота размер файла фактически увеличился, но только при первом повороте. После каждого последующего поворота размер файла оставался неизменным. Я знаю, что он вращается без потерь, потому что я поворачивал его несколько раз без заметной потери качества, в то время как изображение 257 × 257, повернутое 20 раз, стало очень потерянным.

oscilatingcretin
источник
8
На сколько увеличился размер файла в ваших тестах?
Джеймс Снелл
3
@JamesSnell Я знал, что должен был включить это. Тот, который я только что использовал с помощью фильтра различий в GIMP, изначально составлял 14 583 байта, но после вращения изменился до 23 638 байтов. Это разница в более чем 9000 байтов, что кажется большим количеством дополнительных данных, если мы говорим только о метаданных.
колеблющийся
4
Это похоже на множество дополнительных метаданных. Я бы не стал слишком быстро предполагать, что все эти дополнительные данные будут метаданными. Мне кажется, что разница в размере из-за метаданных должна быть почти постоянной (с точностью до нескольких байтов, чтобы учесть строковое представление некоторых чисел).
scottbb
4
Предоставляя дополнительную информацию, которая имеет отношение к вопросу, пожалуйста, внесите изменения в вопрос, а не в комментарии. Комментарии эфемерны и могут время от времени очищаться.
scottbb
2
Было бы полезно загрузить оригинальную версию вашего тестового изображения.
CodesInChaos

Ответы:

36

Скорее всего, это вызвано энтропийным кодированием , которое является последней стадией сжатия JPEG без потерь после того, как данные изображения были квантованы для уменьшения его размера.

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

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

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

Кроме того, «файлы JPEG», с которыми обычно работают люди, на самом деле содержат сжатые JPEG-данные изображения, заключенные в JFIF или контейнер Exif , который объединяет данные изображения с одним или несколькими блоками метаданных и вносит свой собственный набор сложностей. Даже если программное обеспечение, которое вращает изображение, на самом деле не вносит каких-либо существенных изменений в метаданные JFIF / Exif, простая перегруппировка данных может потенциально повлиять на размер файла на несколько байтов.

В частности, метаданные JFIF / Exif могут содержать одну или несколько миниатюр полноразмерного изображения, и программное обеспечение, которое вращает изображения, действительно должно восстанавливать (или также вращать без потерь!) Миниатюры, чтобы они соответствовали новой ориентации полноразмерного изображения. размер изображения. Одно это может легко объяснить наблюдаемую разницу в размерах.

Илмари Каронен
источник
4
Для разницы в 9 КБ (60%) я бы предпочел миниатюры.
BlueRaja - Дэнни Пфлюгофт
JPEG может быть слишком простым для того, чтобы это стоило делать кодировщикам, но видеокодеры, такие как x264, на самом деле могут учитывать способность кодировщика ввода кодировать то, что они собираются выводить дальше, при принятии решения о соотношении скорости и искажения. (т.е. решить, сколько бит может стоить каждая альтернатива, и взвесить это с ошибкой с потерями). Это называется решетчатым квантованием. См. Примечания по реализации квантования решеток в H.264 от автора x264 (Лорен Мерритт); он начинает с довольно простого объяснения цели.
Питер Кордес
Как бы то ни было, кодер JPEG, возможно, выбрал коэффициенты DCT так, чтобы они хорошо сжимались с помощью энтропийного кодера, поэтому даже оптимальный компрессор не может сделать повернутую версию такой маленькой. (Потому что размещение их в другом порядке, вероятно, сделает их менее хорошо сжатыми.) Это почти наверняка будет небольшим эффектом для JPEG, поскольку каждый блок 8x8 кодируется отдельно (сброс состояния энтропийного кодера, AFAIK). (I-кадры в h.264 используют интрапрогнозирование, прогнозирование по другим блокам в том же кадре, что делает их меньше, чем JPEG с таким же визуальным качеством.)
Питер Кордес,
24

Я продолжил и повторил эксперимент, чтобы посмотреть, смогу ли я понять, что происходит.

Процедура

Я сгенерировал случайное RGB-изображение размером 256 на 256 пикселей, используя фильтр «Solid Noise» в GIMP («Фильтры»> «Рендеринг> Облака> Solid Noise ...») с настройками по умолчанию (показано ниже):

введите описание изображения здесь

И результат:

введите описание изображения здесь

Затем я сохранил изображение в формате JPEG, используя настройки по умолчанию:

введите описание изображения здесь

Затем я перенес изображение в Windows и открыл его с помощью средства просмотра фотографий Windows, щелкнув правой кнопкой мыши изображение в проводнике и выбрав в меню « Просмотр» . Затем я повернул изображение с помощью кнопок внизу и сохранил изображение, перейдя к следующему изображению с помощью клавиш со стрелками.

Для каждого из приведенных ниже тестов я начал с копии исходного изображения и повернул (щелкнул по кнопке поворота) соответствующее количество раз перед сохранением. Вот остальные размеры ( ls -l -r):

                    size in bytes    last-modified date 
                          VVVVV        VVVVV
-rwxrwx--- 1 root vboxsf   6258 Nov  8 11:24 original.jpg
-rwxrwx--- 1 root vboxsf  23645 Nov  8 11:30 cw.jpg
-rwxrwx--- 1 root vboxsf  23636 Nov  8 11:30 cw-cw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:30 cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf   6258 Nov  8 11:27 cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:31 cw-cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:29 ccw.jpg
-rwxrwx--- 1 root vboxsf  23636 Nov  8 11:29 ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf  23645 Nov  8 11:29 ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf   6258 Nov  8 11:27 ccw-ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf  23649 Nov  8 11:30 ccw-ccw-ccw-ccw-ccw.jpg

Немедленные наблюдения

  • Windows Photo Viewer (WPV) значительно увеличивает размер; величина увеличения в этом тесте примерно в четыре раза!
  • Все новые изображения увеличиваются примерно до одинакового размера, но они не идентичны.
  • WPV не перекодирует и даже не повторно сохраняет изображение, когда оно поворачивается на 360 градусов. (Отметка времени 11:27 - это время, когда файлы были впервые скопированы.)

Использование cmp -lфайлов, которые должны иметь идентичный контент, позволяет нам увидеть, где файлы отличаются.

robert@unity ../jpeg-rotate-test % cmp -l cw.jpg ccw-ccw-ccw.jpg
 2223  63  62
 2224  60  71
 2226  60  64
 2227  60  66
robert@unity ../jpeg-rotate-test % cmp -l cw-cw.jpg ccw-ccw.jpg
 2223  63  62
 2224  60  71
 2226  60  64
 2227  62  64
robert@unity ..jpeg-rotate-test % cmp -l ccw.jpg cw-cw-cw.jpg
 2223  62  63
 2224  71  60
 2226  64  60
 2227  61  64
robert@unity ../jpeg-rotate-test % cmp -l cw.jpg cw-cw-cw-cw-cw.jpg
 2221  60  61
 2223  63  61
 2224  60  66
 2226  60  61
 2227  60  61
robert@unity ../jpeg-rotate-test % cmp -l ccw.jpg ccw-ccw-ccw-ccw-ccw.jpg
 2223  62  63
 2224  71  60
 2226  64  65
 2227  61  64

Эти файлы отличаются только четырьмя байтами (на самом деле это временная метка), что означает, что WPV каждый раз делает одно и то же; теперь нам нужно только выяснить, что это такое.

Подробные наблюдения

Для этого я использовал JPEGsnoop, чтобы увидеть, что именно было на изображениях.

Поскольку результаты довольно длинные, я привел их в качестве сути . Вот краткое изложение различий:

  • GIMP использует только APP0(JFIF) и COM(комментарий) сегмент для метаданных. WPV оставляет APP0сегмент нетронутым, но, как ни странно, добавляет к комментарию нулевой байт (так что он завершается нулем).

  • WPV добавляет два APP1сегмента, которые являются метаданными Exif и XMP. Эти сегменты составляют 4286 и 12726 байт соответственно. Вместе они составляют почти все увеличение размера файла.

  • GIMP создает прогрессивный JPEG, а WPV - базовый (не прогрессивный) JPEG. По этой причине изображение GIMP имеет несколько сегментов сканирования, а изображение WPV - только один. По моему опыту, прогрессивное изображение иногда немного меньше.

  • GIMP использовал 1 × 1 цветовой подвыборки, в то время как WPV использовал 2 × 2 подвыборки. Это наводит меня на мысль, что WPV не использует «истинное» вращение без потерь, если только оно каким-то образом не способно обнаружить это черно-белое изображение.

Чтобы решить эти проблемы, я провел второй тест.

Процедура

Я выполнил шаги, аналогичные первому тесту. Я создал случайное изображение RGB 256 × 256, используя фильтр шума RGB (Фильтры> Нос> Нос RGB ...) со следующими настройками:

введите описание изображения здесь

Вот результат:

введите описание изображения здесь

Я экспортировал файл в формате JPEG с использованием следующих настроек:

введите описание изображения здесь

Прогрессивный режим отключен, но для субсэмплинга по-прежнему установлено значение 4: 4: 4 (другое название для субсэмплинга 1 × 1). Качество увеличено до 98.

Я скопировал изображение и повернул копию по часовой стрелке; затем скопировали повернутую версию и повернули эту копию против часовой стрелки, чтобы мы могли напрямую сравнить качество между оригинальной и обработанной копией WPV.

Полученные результаты

-rwxrwx--- 1 root vboxsf 159774 Nov  8 16:21 original-random.jpg
-rwxrwx--- 1 root vboxsf 222404 Nov  8 16:24 cw-random.jpg
-rwxrwx--- 1 root vboxsf 222467 Nov  8 16:24 cw-ccw-random.jpg

Хотя это увеличение меньше в относительном выражении (около 40%), абсолютное увеличение еще больше - около 62 кБ. Это говорит о том, что WMV использует менее эффективную кодировку.

Я буду использовать ImageMagick для сравнения двух изображений:

robert@unity ../jpeg-rotate-test % compare -verbose -metric AE original-random.jpg cw-ccw-random.jpg null:
original-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 160KB 0.000u 0:00.009
cw-ccw-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 222KB 0.010u 0:00.010
Image: original-random.jpg
  Channel distortion: AE
    red: 0
    green: 0
    blue: 0
    all: 0
original-random.jpg=> JPEG 256x256 256x256+0+0 8-bit sRGB 0.050u 0:00.020

Есть ноль пикселей разные между оригиналом и копией повернутой. Таким образом, даже если WPV не использует «истинное» вращение без потерь, оно работает достаточно хорошо. Я подозреваю, что знаю, что происходит, и, чтобы объяснить, я немного углублюсь в математику сжатия JPEG.

Алгоритм сжатия JPEG разбивает изображение на блоки 8 × 8 пикселей. Каждый из этих блоков затем подвергается дискретному косинусному преобразованию (DCT) . Результирующие коэффициенты DCT описывают блок как сумму волн различной частоты. Затем алгоритм «выбрасывает» в высокочастотные волны некоторую информацию, соответствующую шуму и очень мелким деталям. Процесс декодирования переворачивает DCT, складывая сохраненные волны вместе, чтобы вернуть блок.

Можно вращать «волны» DCT, фактически не отменяя и не возвращая преобразование (в основном вы превращаете все горизонтальные волны в вертикальные волны и наоборот). Я думаю, что в WPV происходит то, что изображение фактически декодируется, поворачивается, а затем перекодируется. Во время процесса перекодирования, поскольку размер нашего изображения кратен 8 в обоих измерениях, каждый из новых блоков соответствует одному из исходных блоков. Важно отметить, что поскольку каждый блок не имеет высокочастотных компонентов, алгоритм не отбрасывает никакой информации и находит именно те компоненты DCT, которые имел бы «истинный» поворот без потерь.

Наконец, я еще раз посмотрю на компоненты файлов JPEG. Результаты снова связаны между собой . Сравнивая два:

  • Образ WPV содержит дополнительные 4286 + 2 байта метаданных Exif, 1 дополнительный байт в комментарии и 12 726 + 2 байта метаданных XMP. Это всего 17 017 байтов дополнительных метаданных. Для чего используются все эти данные? Я заглянул в файл с моим верным шестнадцатеричным редактором и копией соответствующих стандартов:

    • Метаданные Exif структурированы как изображения в формате TIFF, которые содержат несколько тегов (здесь намного сложнее, но я пропущу это сразу). Большинство байтов в сегменте Exif содержатся в двух идентичных тегах с номером тега EA1C(59 932 десятичных). Этот номер тега нигде не задокументирован. Оба тега содержат 2060 байтов типа «неопределенный», которые являются нулевыми байтами, кроме первых шести ( 1C EA 00 00 00 08). Я понятия не имею, что это за теги, почему их два, и почему они должны быть размером 2 КБ каждый.

    • Метаданные XMP на самом деле представляют собой весь встроенный XML-документ с пространством имен и длинными UUID, который просто содержит строку версии WPV (которая уже была в метаданных Exif). Тем не менее, это только около 400 байтов. Остальная часть сегмента - 122 повторения 100 пробелов, сопровождаемых новой строкой . Это более 12 000 байтов полностью потраченного впустую пространства.

  • Как и в предыдущем тесте, и GIMP, и WPV используют одни и те же таблицы квантования DCT. Это означает, что они должны вычислять точно такие же коэффициенты DCT, поэтому изображения точно такие же. Я не уверен, что WPV просто использует те же таблицы квантования или копирует таблицы из входных данных.

  • В отличие от предыдущего теста, на этот раз WPV использует субсэмплирование 1 × 1, поэтому он может фактически обнаружить, что это цветное изображение (или, по крайней мере, что более высокие выборки необходимы для перекодирования изображения без потерь).

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

    Глядя на статистику JPEGsnoop, мы видим, что некоторые из этих кодов используются редко. Например, в ID: 1, Class: ACтаблице из 119 определенных 16-битных кодов фактически используются только 23. В целом, фактический сегмент сканирования в версии WPV на 28,5% больше.

Резюме

  • WPV, возможно, не делает «настоящих» вращений без потерь, но вращения кажутся практически без потерь.

  • Дополнительный размер частично обусловлен фиксированным количеством добавленных метаданных, а частично - менее эффективным энтропийным кодированием.

Информация о версии:

  • ОС (Linux) ( uname -a):

    Linux unity 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux
    
  • ОС (Windows):

    введите описание изображения здесь

  • GIMP (Linux): 2.8.14 (из пакета gimp, версии 2.8.14-1+deb8u1)

    введите описание изображения здесь

  • Окно просмотра фотографий (в соответствии с метаданными изображения):

    Microsoft Windows Photo Viewer 10.0.10586.0
    
2012rcampion
источник
20

РЕДАКТИРОВАТЬ : Этот ответ был опубликован до того, как я узнал, что размер файлов увеличился примерно на 9 КиБ (9055 байт для изображения 256 × 256, 9612 КиБ для изображения 512 × 512).

По всей вероятности, когда вы впервые повернули изображение, Windows Picture Viewer сделал одну (или обе) из следующих вещей:

  1. Добавлен тег EXIF, которого не было в исходном изображении JPEG (возможно, тег Orientation);
  2. Изменена / добавлена ​​информация к уже существующему тегу (возможно, теги Software Processing или Image Software).

Это увеличило размер файла из-за дополнительного тега EXIF ​​(и / или дополнительных данных к существующим тегам).

Последующие ротации не увеличивали размер файла, потому что все теги и / или данные тегов, которые WPV добавил бы / изменил, уже были там. Изменено только значение тега ориентации (и, возможно, значения тега даты / времени).


РЕДАКТИРОВАТЬ : Почти наверняка, что это объяснение не может содержать около 9 КиБ дополнительных данных в файле. Кроме того, в отсутствие каких-либо других причин увеличения размера это объяснение предполагает, что увеличение размера будет более или менее постоянным (по модулю некоторых различий в длине между строковыми представлениями числовых данных, возможно, в несколько байтов). Это, очевидно, не то, что здесь происходит, по крайней мере, не полное объяснение.

scottbb
источник
1
И тег EXIF ​​будет занимать 9 КБ? Что ж, по крайней мере, это легко проверить - попросите OP удалить EXIF ​​или другие теги из повернутого изображения и посмотрите, как изменяется размер файла.
Карл Виттофт
2
@CarlWitthoft 9kB это новая информация. Редактирование, чтобы упомянуть об этом.
scottbb
3

Без обратного инжиниринга jpeg en / decoder невозможно сказать наверняка. На самом деле существует ряд стандартов jpeg, и вопреки распространенному мнению, не все они могут быть изменены без перекодирования.

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

Увеличение размера файла может также включать некоторые дополнительные метаданные, хотя 9k кажется большим, это возможно. Увеличение также может быть объяснено добавлением миниатюры, которая может отсутствовать в выходных данных GIMP. Мы можем получить больше информации из файлов напрямую (до WPV и после).

В любом случае, пытаться без потерь работать с jpeg - это действительно дурацкое поручение, так как это полезно только для изображений определенного размера, не все декодеры и кодеры идентичны, и это требует, чтобы эти редакторы работали напрямую с содержимым jpeg, на которое нельзя полагаться. дело ... То, что это происходит сейчас, не означает, что так будет и в будущем.

Лучше всего работать с форматом без потерь и полностью избежать боли.

Джеймс Снелл
источник
2
Я совсем не уверен, что вращение данных в формате JPEG должно вызывать перекодировку.
Карл Виттофт
Зависит от того, программист ты или нет ... Я думаю, что нет. Вы должны были бы специально искать эту оптимизацию, чтобы внести это минимальное изменение, иначе операция сохранения начнется с несжатого растрового изображения.
Джеймс Снелл
3
Из связанного вопроса ясно, что Windows Photo Viewer вращает JPEG без потерь.
vclaw
2
@James Я не программист низкого уровня, хотя я играю на ТВ :-). ОП предоставил ссылку на точное описание того, когда будет повторное кодирование, а когда нет. Из этого обсуждения я понял, что он вращался только на $ \ frac {\ pi} {2} $. Я согласен с тем, что поворот на произвольный угол вызывает перекодирование и в этом отношении может привести к потере информации, если изображение X-Y-Y не внедрено в область, по крайней мере такую ​​же большую, как гипотенуза.
Карл Виттофт
1
Мы уверены, что знаем, что WPV вращается обратимо для изображений с размерами, кратными 8/16. См. Комментарий @ Tristan к ответу Мэтта Грума на вопрос, связанный с ОП. Тристан работал в команде WPV в Microsoft, и в основном это подтверждает.
scottbb
1

Вращение JPEG без потерь возможно только без введения граничных артефактов, если размеры изображения кратны размеру блока (обычно [/ всегда?] 8). См. Справочную страницу jpegtran (извините, у меня нет хорошей канонической ссылки для нее; не стесняйтесь редактировать, если вы ее найдете), чтобы узнать подробности:

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

Поведение jpegtran по умолчанию при преобразовании изображения нечетного размера
предназначено для сохранения точной обратимости и математической
согласованности набора преобразования. Как уже говорилось, транспонирование
может перевернуть всю область изображения. Горизонтальное зеркальное отображение не затрагивает любой частичный столбец iMCU по правому краю, но может перевернуть все строки изображения. Точно так же вертикальное зеркальное отображение оставляет любую частичную строку iMCU на нижнем краю нетронутой, но может перевернуть все столбцы. Другие преобразования могут быть созданы как последовательности операций транспонирования и переворачивания; для согласованности их действия над краевыми пикселями определяются как конечные результаты соответствующей последовательности транспонирования и переворачивания.

Для практического использования вы можете предпочесть отбрасывать любые непереводимые
краевые пиксели, а не иметь странно выглядящую полосу вдоль
правого и / или нижнего краев преобразованного изображения. Для этого добавьте ключ -trim:

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

Р..
источник
1
не имеет значения для изображения 256x256.
тыс
Я неправильно прочитал и подумал, что проблема была для версии 257x257.
Р ..
0

У меня нет определенного ответа, но есть несколько возможных теорий, почему это произошло. Некоторые типы файлов работают таким образом, что два разных кода для изображения этого типа файла не обязательно создают разные изображения. Например, тип файла PNG работает таким образом, потому что он допускает прозрачный фон, но изображение с прозрачным фоном и одно и то же, за исключением того, что один и тот же фон белого цвета, выглядит точно так же. Файл изображения считается сжатым, если он занимает менее 3 байтов памяти на пиксель. Я считаю, что кроме тех, которые имеют прозрачный фон, никакие два файла PNG не генерируют точно такое же изображение. Когда вы сохраняете изображение в формате PNG, оно преобразует его в код, который генерирует исходное изображение, за исключением очень необычных изображений, таких как одно, где каждый пиксель является случайным цветом всех 2 ^ 24 цветов, код будет занимать меньше памяти, чем 3 байта на пиксель, поэтому сохранение, поскольку PNG называется сжатием без потерь. С другой стороны, для экономии памяти с помощью кода файла изображения JPEG можно генерировать только определенные изображения. Вероятно, существует несколько типов файлов JPEG, и я не знаю, обладает ли какой-либо из них свойством, что два разных изображения этого типа файлов могут генерировать одно и то же изображение. Я предполагаю, что несколько раз вы просто поворачивали изображение, а затем сохраняли его в формате JPEG и объяснили, что произошло, исходя из предположения, что это то, что вы сделали, и я не знаю, правда ли это. Вращение, которое вы сделали, без потерь, если есть способ вернуть тот же код файла изображения, который вы использовали до того, как повернули и сохранили его. Возможно, вы не правы, что вы действительно сделали вращение без потерь. Если бы это действительно было без потерь,

Тимоти
источник
-3

Причины этого несколько

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

Но почему вы вращаете JPEG в 20 раз?

Cc Dd
источник
2
Если вы прочитаете ссылку в исходном вопросе, по крайней мере, для Windows Picture Viewer , если размеры JPEG кратны 8, то повороты JPEGS в WPV - это преобразования без потерь. Простой способ проверить это - повернуть 4 раза (получая ту же ориентацию, что и оригинал) и выполнить простое попиксельное вычитание изображения.
scottbb
@scottbb Это не обязательно просто проблема с программой просмотра изображений Windows. Все, что вращает формат с потерями, должно пересчитать сжатие. вращение изображения с кратностью 8 означает, что все умещается в 8-битные слова и может не сжиматься таким образом, чтобы добавлять артефакты. Это основано на том, как алгоритм работает и реализован в используемой программе.
Копия Dd
-3

Из-за того, как работает сжатие изображений . Любой формат, такой как PNG или JPG в целом, не сохраняет размер файла после поворота.

Для компрессора повернутое изображение - это просто другое изображение, так как эвристика сжатия работает , нет гарантии, что оно будет сжимать повернутое изображение так же .

Конечно, если сжатие выполняется без потерь, если вы поворачиваете изображение 4 раза в 4-й раз, изображение снова становится таким же (поворачивается до тех пор, пока оно не станет наклоненным как оригинал): в этом случае оно должно снова стать таким же сжатым размером, если нет, то это из-за одной из следующих причин :

  • Добавлены метаданные : программа по какой-то причине добавила часть текста
  • Компрессор изменен: программа может выбрать повторное сохранение изображения как оригинала, если нет никаких изменений, но если вы примените какое-либо изменение (даже 4 поворота на 90 градусов), она может решить повторно сжать изображение снова, используя свой собственный компрессор (программа больше не знает, что это все тот же образ).
  • В целом, один и тот же компрессор (libPNG или libJPG) дает очень разные результаты в разных реализациях, в разных версиях одной и той же библиотеки и с разными параметрами сжатия (операционная система и компилятор иногда имеют значение здесь).

Сжатие изображений работает путем сжатия изображений в фрагменты 4x4 или других размеров. В общем, компрессор видит повернутое изображение как другое изображение, однако, поскольку сжатый пиксельный фрагмент представляет собой просто линейную декомпозицию, если фрагменты на изображении одинаковы, можно просто транспонировать / отразить матрицы линейной декомпозиции, эффективно сохраняя их качественный:

Обратите внимание, что это должно быть реализовано отдельно для каждого объекта , и это также объясняет начальное увеличение размера => при первом повороте, оно просто пытается сжать изображение фрагментами, которые могут вращаться:

  • Если это не удается сделать, качество изображения ухудшается
  • Если он успешен, он увеличивает размер только один раз, тогда каждое вращение сохраняет то же качество.

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

Скоттбб ответит неправильно, и вы можете сделать простой тест:

  • Открыть оригинальное изображение: Скриншот это
  • Поворот изображения 4 раза с WPV: снимок экрана
  • Сравните 2 скриншота

Вы увидите измененное изображение (оно сжимается при первом повороте). Однако это изменение ограничено по времени, теперь вы можете повернуть его снова без потери качества (если размер изображения кратен 8)

Чтобы напрямую ответить на OP:

Я знаю, что он вращается без потерь

Он не вращается без потерь, он теряет качество хотя бы один раз (при первом вращении: поскольку он должен сначала сжать его таким образом, чтобы его можно было вращать), затем он сохраняет свое качество.

Разработчик игр
источник
1
Речь идет о вращении без потерь, поэтому повторного сжатия избегают.
Agent_L
5
ОП спросил не об общем случае, а именно об одном конкретном программном обеспечении и об одном конкретном случае, который это делает. Ваш ответ не является неправильным, он просто отвечает на вопрос, отличный от того, который задал ОП.
Agent_L
1
Первые 3 предложения по-прежнему относятся к другому вопросу: «как работает сжатие изображений» - в повороте без потерь сжатия нет. «Для компрессора повернутое изображение» - опять компрессор не вызывается. «если сжатие без потерь» - сжатие с потерями. Вращение без потерь. Вот как далеко я готов принять этот аргумент. Я понимаю вашу точку зрения, я согласен с этим, но здесь это совершенно неуместно. Кстати, я тоже программист, и я сделал свою долю чтения и записи сырых файлов.
Agent_L
1
Я создал изображение в Paint, повернул его 4 раза, и он идентичен, но размер, тем не менее, подскочил с 1,6 до 8,1 КБ. Бинарный diff показывает, что данные изображения были нетронуты, это просто огромный кусок метаданных в <?xpacketтегах.
Agent_L
1
Если размеры JPEG равномерно делятся на 8 (или 16 с подвыборкой), его можно поворачивать без потерь на 90 градусов . Ключ в том, чтобы не декодировать его полностью в RGB, а работать напрямую с коэффициентами DCT. Это специализированная функция, которая не часто включается в общий редактор изображений. Смотрите, например, en.wikipedia.org/wiki/Libjpeg#jpegtran . Если вы выполнили свой эксперимент с Windows Photo Viewer, как указано в вопросе, вы увидите, что он действительно без потерь.
Марк Рэнсом