Я пішов вперед і повторив експеримент, щоб побачити, чи зможу я зрозуміти, що відбувається.
Порядок
Я генерував випадкове RGB зображення 256 на 256 пікселів, використовуючи фільтр "Суцільний шум" у GIMP (Фільтри> Візуалізація> Хмари> Суцільний шум ...), використовуючи параметри за замовчуванням (показано нижче):
І результат:
Потім я зберегла зображення як 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 не використовує "справжнього" обертання без втрат, якщо тільки якимось чином не вдається виявити це чорно-біле зображення.
Щоб вирішити ці проблеми, я пройшов другий тест.
Порядок
Я дотримувався аналогічних кроків до першого тесту. Я створив випадкове зображення 256 × 256 RGB за допомогою фільтра шуму 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 077 байт додаткових метаданих. Для чого використовуються ці дані? Я зазирнув у файл зі своїм надійним шестигранним редактором та копією відповідних стандартів:
Метадані 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