Трудовые будни или еще раз о формате DNG
Не могу молчать, могу только материться, да и то с трудом.
Преамбула:
Даже если вот рассматривать только документированные форматы данных, там спецификации довольно расплывчатые бывают (вот, к примеру мой вопль о JPEG color profiles). Соответственно, в частности в LibRaw, мы работаем только с реальными примерами из реальной жизни, ибо наворотить создатель файла может всякого, всюду соломки не подстелишь, работаем по заявкам. Так вот.
Акт 1, LibRaw "пару месяцев назад"
Все DNG-теги парсятся в общую кучу, то есть вот если есть несколько тегов, скажем, ColorMatrix1, то сработает последний.
Контрпример (зачеркнуто нецензурное): если создать (из более-менее свежего лайтрума) Lossy DNG с 'fast load data', то там будет два JPEG-RAW (в смысле RAW-данные, пожатые JPEG-ом т.е. с потерями). Вместо таблицы линеаризации Adobe использует OpcodeList2 и линеаризует эти JPEG-и полиномом. И для двух JPEG-ов эти полиномы будут разными (сука, ну почему? данные то исходно одни, просто разного разрешения, почему им нужна разная линеаризация).
ОК. Будем делать по науке, для каждой SubIFD свою табличку DNG-тегов (не всех, но тех что реально используем в приложении, ColorMatrix, AnalogBalance, CameraCalibration, уровень черного-белого) и используем потом ту, которая относится к той SubIFD, которую показываем.
Клюв вытащили. Но увяз, оказывается, хвост:
Акт 2. Вчера.
Есть у меня подборка "хитрых примеров" и я их периодически просматриваю (например, свежей версией FRV при подготовке релиза). Хренак, у одного примера - неверный баланс белого, все в пурпур.
Это, да, непростой пример, это Canon sRAW (т.е. исходно YCC) сохраненный лайтрумом (версии 5.7, похоже что это важно, но проверять не буду) в DNG.
Структура файла такая:
- IFD0 - превьюшка, нежатая, 256px, SubFileType=1 (tiff-превью по сути). Все по рекомендации TIFF-EP, "хранить в начале мелкую превьюшку"
- IFD1 - собственно RAW-изображение, 3960px. Так как в DNG не бывает YCC, оно (естественно) преобразовано в RGB. При этом баланс белого As Shot поставлен примерно 1-1-1, а реальный баланс спрятан в теге AnalogBalance в IFD0 (а не в IFD1), если его не применить - все будет пурпурное.
- IFD2 - превьюшка, JPEG, 1024px
- IFD3 - превьюшка, RAW, fast load data (2048px, JPEG-компрессия)
- IFD4 - превьюшка, RAW, 256px, JPEG-компрессия, вторая таблица линеаризации (см. пример выше)
Так вот, куча тегов, относящихся к IFD1,3,4 - хранится в IFD0. Что было бы почти правильно (см. ниже), если бы в этой IFD не было бы превьюшки.
Стандарт DNG говорит нам следующее:
- DNG is an extension of TIFF 6.0 and is comp atible with the TIFF-EP standard
- DNG recommends, but does not require, that the first IFD contain a low-resolution thumbnail, as described in the TIFF-EP specification.
Смотрим теперь в TIFF/EP:
- The main image shall be in IFD 0.For the main image, NewSubFileType shall be 0 (main image).
- The thumbnail shall be stored in the first IFD, not in IFD 0. That is, IFD 0 shall contain one SubIFDs tag, and the first entry of the SubIFDs tag shall be the thumbnail IFD.
И вот сдается мне, что кто-то в Adobe перепутал IFD0 и FirstIFD (я бы, с такими формулировками, тоже бы перепутал) и сделал все наоборот: в IFD0 положили превьюшку и теги от основного изображения, а в First IFD - основное изображение и немножко тегов, без которых нельзя обойтись: размеры, способ сжатия и подобное.
Ну а жить то с этим как? Нужно ли мне искать недостающие данные только в IFD0, или нужно вообще все теги обсмотреть?
Я проверю, но не сегодня (боюсь раздражиться еще и всю посуду перебить) более новый лайтрум. Судя по количеству жалоб (их нет), все вышеописанное - это фича конкретной довольно старой версии (лайтрума, DNG SDK).
Я это, собственно, вот к чему. Ну ладно, "проприетарные форматы". Ну вот Canon меняет формат Makernotes чуть не с каждой новой камерой (с каждым новым Digic - точно), ну притерпелись, научились. Но вот DNG - документирован в публичных документах, легче от этого стало? Ну только то легче, что можно тыкать вот носом Adobe в нарушение спецификаций, отводить душу. Поддерживать этот зоопарк все едино приходится.
UPD: программируя эту хрень, задумался. А ведь может, в принципе, быть так:
- IFD0 - есть CameraMatrix и Illuminant
- IFDn - только Illuminant
И чего, брать Illuminant для данного Sub-Image, а CameraMatrix - общий? Ну это ведь - ну 100% некорректно, но (похоже) авторы стандарта хотят от нас именно этого?