JPEG
найбільш балакучийФайл JPEG зберігає свої метадані в сегментах APPn, між заголовком файлу й даними зображення. Ось що де лежить і що PicScrub робить із кожною частиною.
Що видаляється
- EXIF GPS-координати, виробник і модель камери, дата й час, параметри експозиції
- XMP історія редагування, використана програма, оцінки
- IPTC / Photoshop підписи, згадки про авторів, ключові слова
- Коментарі та вбудовані мініатюри крихітна копія оригіналу, яка може пережити всі ваші кадрування й правки
Що можна залишити
- Дані зображення завжди недоторкані, ніколи не перекодовуються
- Колірний профіль ICC за бажанням, щоб кольори лишалися точними
- Орієнтація за бажанням, щоб вертикальні знімки не лягали набік
- Згадка про авторські права за бажанням, для фотографів, яким потрібне імʼя без координат
Огляд структури файлу
Якщо ви колись відкривали JPEG у шістнадцятковому редакторі, то помічали, що він складається із сегментів, розділених маркерами. Кожен маркер починається з 0xFF, а далі йде байт, який каже, що це за сегмент. Завдяки такій будові JPEG порівняно легко розбирати: ви просто шукаєте байти FF і дивитеся, що йде після них.
Найцікавіше для приватності те, що всі метадані (EXIF, GPS, дата й час) живуть саме в цих сегментах, окремо від самих даних зображення. Тому ми й можемо видалити метадані, не чіпаючи пікселів і нічого не стискаючи повторно.
Структура файлу JPEG
Приклад заголовка JPEG
| Offset | Hex | ASCII | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | FFD8FFE000104A464946000101000048 | ......JFIF.....H | |||||||||||||||
| 0010 | 00480000FFE112344578696600000000 | .H.....4Exif.. | |||||||||||||||
Будова маркера
FF xx:маркер (xx визначає тип)LL LL:довжина (2 байти, big-endian, враховує саму себе)Data...:дані сегмента (довжина мінус 2 байти)
Повний довідник маркерів JPEG
| Маркер | Назва | Опис |
|---|---|---|
| FF D8 | SOI | Початок зображення |
| FF D9 | EOI | Кінець зображення |
| FF C0 | SOF0 | Початок кадру (baseline DCT) |
| FF C2 | SOF2 | Початок кадру (progressive DCT) |
| FF C4 | DHT | Опис таблиці Гаффмана |
| FF DB | DQT | Опис таблиці квантування |
| FF DD | DRI | Опис інтервалу перезапуску |
| FF DA | SOS | Початок сканування (далі йдуть дані зображення) |
| FF FE | COM | Коментар (метадані) |
| FF E0 | APP0 | Маркер JFIF |
| FF E1 | APP1 | Маркер EXIF / XMP |
| FF E2 | APP2 | Профіль ICC / MPF |
| FF ED | APP13 | IPTC / Photoshop |
| FF EE | APP14 | Перетворення кольору Adobe |
Золотим позначено метадані (видаляються), звичайним: структуру, яка залишається
JFIF проти EXIF
Ось що збиває з пантелику багатьох: файли JPEG часто містятьдва різні стандарти метаданих одночасно. Спочатку зʼявився JFIF, який відповідає за базові речі на кшталт роздільності. Потім камери почали додавати дані EXIF з усіма подробицями про зйомку. Більшість сучасних JPEG мають і те, і те, тому на початку файлу ви бачите одразу маркери APP0 та APP1.
APP0:JFIF
JPEG File Interchange Format. Базова інформація про зображення.
- • Номер версії
- • Щільність пікселів (DPI)
- • Співвідношення сторін
- • Необовʼязкова мініатюра
APP1:EXIF
Exchangeable Image File Format. Метадані камери.
- • Виробник і модель камери
- • GPS-координати
- • Дата й час
- • Параметри експозиції
Маркери APP у деталях
Специфікація JPEG зарезервувала 16 «прикладних» маркерів (від APP0 до APP15), щоб виробники використовували їх як заманеться. З роками різні організації позаймали різні маркери під свої формати метаданих. Вийшов невеликий безлад, але принаймні добре задокументований.
Складність у тому, що той самий маркер може означати різні речі залежно від вмісту. APP1, наприклад, може містити або EXIF, або XMP, тож доводиться дивитися на рядок-ідентифікатор усередині, щоб зрозуміти, з чим ви маєте справу.
APP0 (0xFFE0):JFIF
Ідентифікатор: JFIF\0. Містить версію, одиниці щільності, щільність по X та Y і необовʼязкову вбудовану мініатюру. Зазвичай його можна безпечно зберегти.
APP1 (0xFFE1):EXIF
Ідентифікатор: Exif\0\0. Містить повноцінну структуру TIFF із записами IFD про камеру, дані GPS, дату й час, мініатюри та нотатки виробника. Головна загроза приватності.
APP1 (0xFFE1):XMP
Ідентифікатор: http://ns.adobe.com/xap/1.0/\0. Стандарт метаданих на основі XML від Adobe. Може містити історію редагування, дані про програму та розширені дані EXIF.
Простори імен XMP
xmp: http://ns.adobe.com/xap/1.0/xmpMM: http://ns.adobe.com/xap/1.0/mm/dc: http://purl.org/dc/elements/1.1/photoshop: http://ns.adobe.com/photoshop/1.0/tiff: http://ns.adobe.com/tiff/1.0/exif: http://ns.adobe.com/exif/1.0/APP1 (0xFFE1):розширений XMP
Ідентифікатор: http://ns.adobe.com/xmp/extension/\0. Для даних XMP, більших за 65 КБ, які розбиваються на кілька сегментів APP1.
APP2 (0xFFE2):MPF
Ідентифікатор: MPF\0. Multi-Picture Format для стереоскопічних зображень і панорам.
APP2 (0xFFE2):профіль ICC
Ідентифікатор: ICC_PROFILE\0. Дані для керування кольором. Можуть бути розбиті на кілька маркерів APP2. Зазвичай їх безпечно зберігати.
APP13 (0xFFED):IPTC/Photoshop
Ідентифікатор: Photoshop 3.0\0. Містить дані IPTC-IIM: підписи, ключові слова, авторські права, відомості про автора. Може містити інформацію про особу автора.
APP14 (0xFFEE):Adobe
Ідентифікатор: Adobe\0. Містить прапорці перетворення кольору (RGB/CMYK). Важливі для правильного відтворення кольорів.
Структура EXIF
Ось де починається найцікавіше (і трохи дивне). Дані EXIF насправді є крихітним файлом TIFF, вбудованим у ваш JPEG. Так, справді. У нього власний заголовок, власний порядок байтів, а теги він зберігає у структурі IFD (Image File Directory) з TIFF.
Перше, що ви побачите після ідентифікатора «Exif», це заголовок TIFF, який каже, у якому порядку записані дані: little-endian (Intel, «II») чи big-endian (Motorola, «MM»). Помилитеся тут, і всі числа перетворяться на сміття, тож будь-який парсер перевіряє це найпершим.
Заголовок TIFF (8 байтів)
| Offset | Hex | ASCII | |||||||
|---|---|---|---|---|---|---|---|---|---|
| 0000 | 49492A0008000000 | II*..... | |||||||
II = Intel (little-endian), MM = Motorola (big-endian)
Будова запису IFD (12 байтів)
Ключові записи IFD
0x010F:Make0x0110:Model0x0132:DateTime0x8769:ExifIFDPointer0x8825:GPSInfoIFDPointer0x927C:MakerNoteЯк PicScrub обробляє JPEG
Підхід доволі простий: ми читаємо файл маркер за маркером, залишаємо ті, що потрібні для показу зображення, і пропускаємо ті, що містять метадані. Оскільки стиснених даних зображення ми не торкаємося взагалі, втрат якості немає жодних.
Ключ до всього: побудова JPEG на маркерах, яка дуже це спрощує. Нам не потрібно розбиратися ні в коефіцієнтах DCT, ні в таблицях Гаффмана. Досить визначити, які сегменти є метаданими, а які ні.
Перевіряємо заголовок
Переконуємося, що на початку файлу є маркер SOI (FF D8)
Розбираємо маркери
Читаємо кожен маркер послідовно, визначаючи тип і довжину
Знаходимо метадані
Перевіряємо ідентифікатори в сегментах APP (EXIF, XMP, IPTC тощо)
Копіюємо вибірково
Переносимо у вихідний файл усе, крім метаданих, а сегменти з метаданими пропускаємо
Що зберігається
- • маркери SOI/EOI (обовʼязкові)
- • DQT (таблиці квантування)
- • SOF (заголовок кадру)
- • DHT (таблиці Гаффмана)
- • SOS і дані сканування (саме зображення)
- • за бажанням: колірний профіль ICC (налаштовується)
Що видаляється
- • APP1 EXIF (камера, GPS, дата й час)
- • APP1 XMP (метадані редагування)
- • APP13 IPTC (підписи, автор)
- • маркери COM (коментарі)
- • мініатюри з EXIF
Довідник тегів EXIF
Не всі теги EXIF однаково небезпечні для приватності. Одні, як-от параметри експозиції, цілком безневинні. Інші, як-от серійні номери та імена власників, можуть однозначно вказати на вас чи вашу техніку. Ось ті, які ми вважаємо найризикованішими:
| Tag ID | Назва | Ризик для приватності |
|---|---|---|
| 0x9003 | DateTimeOriginal | Високий |
| 0x9004 | DateTimeDigitized | Високий |
| 0x9010 | OffsetTime | Середній |
| 0x9286 | UserComment | Високий |
| 0x927C | MakerNote | Високий |
| 0xA420 | ImageUniqueID | Високий |
| 0xA430 | CameraOwnerName | Високий |
| 0xA431 | BodySerialNumber | Високий |
| 0xA434 | LensModel | Середній |
| 0xA435 | LensSerialNumber | Високий |
| 0xFDE8 | OwnerName | Високий |
| 0xFDE9 | SerialNumber | Високий |
Показати всі теги з параметрами зйомки (не ідентифікують вас)
0x829A ExposureTime0x829D FNumber0x8822 ExposureProgram0x8827 ISOSpeedRatings0x9201 ShutterSpeedValue0x9202 ApertureValue0x9203 BrightnessValue0x9204 ExposureBiasValue0x9207 MeteringMode0x9208 LightSource0x9209 Flash0x920A FocalLength0xA001 ColorSpace0xA002 PixelXDimension0xA003 PixelYDimension0xA402 ExposureMode0xA403 WhiteBalance0xA405 FocalLengthIn35mmFilm0xA406 SceneCaptureTypeДовідник тегів GPS
Дані GPS живуть в окремому під-IFD, на який вказує тег 0x8825 у головному IFD. Якщо цей вказівник є, у вашому зображенні є дані про місцеперебування. Сучасні смартфони особливо старанно їх вбудовують, часто з такою точністю, що можна визначити, де саме ви стояли.
| Tag ID | Назва | Опис |
|---|---|---|
| 0x0000 | GPSVersionID | Версія тегів GPS |
| 0x0001 | GPSLatitudeRef | N або S |
| 0x0002 | GPSLatitude | Градуси, мінути, секунди |
| 0x0003 | GPSLongitudeRef | E або W |
| 0x0004 | GPSLongitude | Градуси, мінути, секунди |
| 0x0005 | GPSAltitudeRef | Вище або нижче рівня моря |
| 0x0006 | GPSAltitude | Метри |
| 0x0007 | GPSTimeStamp | Час UTC |
| 0x001D | GPSDateStamp | Дата UTC |
| 0x0012 | GPSMapDatum | Геодезична система координат |
| 0x001B | GPSProcessingMethod | GPS/CELLID/WLAN/MANUAL |
| 0x001C | GPSAreaInformation | Назва місця |
Довідник тегів IPTC
IPTC придумали для інформагенцій, щоб вбудовувати в знімки підписи, згадки про авторів і відомості про авторські права. Він зберігається всередині APP13 з ідентифікатором «Photoshop 3.0» (так, Adobe перейняла цей стандарт). Якщо ви колись додавали копірайт чи ключові слова в Lightroom або Photoshop, вони опинилися саме тут.
0x0250 By-line (автор)0x0255 By-line Title (посада автора)0x025A City (місто)0x025C Sub-location (місцевість)0x025F Province/State (область)0x0265 Country Name (країна)0x0274 Copyright Notice (авторські права)0x0276 Contact (контакти)0x0237 Date Created (дата створення)0x023C Time Created (час створення)0x0278 Caption/Abstract (підпис)0x0219 Keywords (ключові слова)