[вернуться к оглавлению]

LibRaw: общие комментарии к API

Содержание

  1. Соглашения о кодах ошибок и действиях при ошибках
  2. Нештатные ситуации, не являющиеся ошибкой
  3. Thread safety
  4. Использование C++
  5. Параметры структуры LibRaw::imgdata.params, влияющие на поведение open_file/unpack/unpack_thumb
  6. Использование памяти
    1. Использование стека
    2. Управление динамической памятью
    3. Использование динамической памяти
      1. Память для раскодированного изображения
      2. Память для раскодированного thumbnail
      3. Память для раскодированного ICC-profile
      4. Память для распаковки RAW
      5. Память для постобработки
      6. Память для записи файла
      7. Память для распаковки в буфер в памяти
  7. Несовместимости с dcraw
    1. Обработка Thumbnails от камер Kodak

Соглашения о кодах ошибок и действиях при ошибках

Приняты следующие соглашения о возвращаемых ошибках

  1. Все функции, которые могут вернуть код ошибки имеют целый тип возвращаемых данных.
  2. При отсутствии ошибки возвращается 0 (LIBRAW_SUCCESS).
  3. Если случилась ошибка в системном вызове, то возвращается значение errno (это положительное число), которое может быть проанализировано с помощью strerror() или подобных средств.
  4. Все собственные коды ошибок LibRaw - отрицательные, при этом ошибки делятся на два типа:
    Нефатальные ошибки
    Нефатальные ошибки не запрещают исполнение других функций в последовательности обработки (например, unpack_thumb() вполне может вернуть код, означающий "preview отсутствует" и это не мешает затем вызвать unpack()).
    Фатальные ошибки
    В случае возникновения фатальной ошибки (нехватка памяти, ошибка во входных данных, невозможность распаковки данных) текущая стадия обработки завершается, все аллоцированные ресурсы освобождаются.
    В случае попытки продолжения обработки - все последущие вызовы API вернут ошибку LIBRAW_OUT_OF_ORDER_CALL.
    Вместе с тем, экземпляр LibRaw, в котором возникла фатальная ошибка, может обрабатывать следущие RAW-файлы обычным образом (вызов open_file(), затем unpack() и так далее).
  5. Проверка фатальности ошибки осуществляется макросом LIBAW_FATAL_ERROR(код ошибки)
  6. Коды ошибок перечислены и расшифрованы здесь.

Нештатные ситуации, не являющиеся ошибкой

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

Thread safety

Thread safety обеспечивается, если объект LibRaw создается и иcпользуется внутри одного thread. При этом количество threads (каждая со своим объектом LibRaw) ничем не ограничено (кроме потребностей в памяти).

В случае создания объекта LibRaw в одном потоке исполнения, а использования в другом - необходима внешняя синхронизация.

В Unix (Linux/FreeBSD/MacOS) собираются две версии библиотеки: thread-safe версия libraw_r.a и более быстрая не thread-safe libraw.a.

Thread-safe версия использует для хранения локальных данных поля в классе LibRaw, что позволяет иметь несколько экземпляров класса LibRaw, работающих одновременно.

Не thread-safe версия хранит промежуточные данные в глобальных переменных, что несколько быстрее. Не thread-safe версия может использоваться и в multithreaded-приложениях, но только если экземпляр класса LibRaw гарантированно один.

Под Windows собирается только thread-safe версия.

Использование C++

При обработке исключительных ситуаций внутри LibRaw используется механизм C++ exceptions. Все исключения перехватываются внутри функций библиотеки и проникать наружу не должны.

Для аллокации/освобождения памяти используются функции malloc(calloc)/free, а не new/delete.

Какие-либо специфические библиотеки (STL, Boost, smart pointers) - не используются.

При использовании С API ссылки на C++-вызовы new/delete остаются, поэтому линковаться надо с libstdc++(Unix)/....(Windows).

Параметры структуры LibRaw::imgdata.params, влияющие на поведение open_file/unpack/unpack_thumb

Большинство полей данных структуры LibRaw::imgdata.params влияют только на постобработку данных, но есть ряд исключений, унаследованных текущей версией LibRaw от исходных текстов dcraw (постепенно эти зависимости будут удаляться).

imgdata.params.use_camera_matrix и imgdata.params.use_camera_wb
Влияют на загрузку RAW-данных для камер у которых есть colormatrix.
Внимание! Если параметр imgdata.params.use_camera_matrix не установлен пользователем, то он копируется из imgdata.params.use_camera_wb на этапе открытия файла.
imgdata.params.user_flip
Если этот параметр больше или равен нулю, то на этапе open_file() производится присваивание imgdata.sizes.flip = imgdata.params.user_flip.
imgdata.params.shot_select
Позволяет выбрать номер извлекаемого изображения для тех форматов данных, где возможно хранение нескольких RAW-изображений в одном файле данных.
imgdata.params.half_size
Влияет на загрузку RAW-данных для задников Phase One и Sinar.
imgdata.params.use_camera_wb
Влияет на загрузку матрицы баланса белого для задников Leaf.
imgdata.params.document_mode
В текущей версии LibRaw не влияет на чтение данных. В dcraw - влияет на данные thumbnails для некоторых камер Kodak и на RAW-данные изображения для камер с матрицей Foveon.

Использование памяти

Использование стека

Экземпляр класса LibRaw имеет собственный размер около 100 килобайт, при использовании конструкций вида LibRaw imageProcessor; эта память аллоцируется на стеке.

Методы класса LibRaw (и вызовы С API) при работе могут аллоцировать до 130-140 килобайт данных на стеке под автоматические переменные.

Таким образом, для работы одного экземпляра LibRaw может требоваться около 250 килобайт стека. В большинстве современных архитектур это не является проблемой, но при использовании LibRaw в multi-threaded-окружении необходимо не забывать аллоцировать достаточно памяти для стека thread.

При динамической аллокации (LibRaw *iProcessor = new LibRaw;) требования к памяти на стеке снижаются (на 100 килобайт - размер экземпляра класса). При использовании C API экземпляр LibRaw аллоцируется динамически.

Управление динамической памятью

LibRaw ведет учет всех блоков аллоцированной динамической памяти, при возникновении исключительной ситуации (фатальной ошибки) все они освобождаются. Код учета довольно примитивный и не расчитан на аллокацию большого числа блоков (в обычной ситуации при обработке файла аллокация происходи 2-6 раз), при расширении LibRaw собственными методами это надлежит учитывать.

Использование динамической памяти

LibRaw использует динамическую память:

Память для раскодированного изображения

С целью упрощения дальнейшей обработки, память под извлекаемые RAW-данные аллоцируется с 4-кратным (для байеровских камер) запасом: для каждого пикселя отводится 4 16-битных компонента (три из которых будут нулевыми после распаковки RAW). Это позволяет проводить дебайеризацию и прочие действия по постобработке прямо в том же буфере, куда были извлечены данные, но повышает требования к памяти вчетверо.
Таким образом, размер памяти под буфер изображения в 6-10 раз превышает размер исходного RAW-файла.
Вполне вероятно, что в следующих версиях LibRaw аллокация этого буфера будет более экономной, при условии неиспользования вызовов постобработки, унаследованных от dcraw..

Буфер для раскодированного изображения аллоцируется при вызове unpack() и освобождается при recycle().

Память для раскодированного thumbnail

Память для thumbnail аллоцируется при вызове unpack_thumb() и освобождается при recycle(). Аллоцируется буфер размером ровно под thumbnail т.е. до нескольких мегабайт.

Память для раскодированного ICC-profile

Память для ICC-профиля аллоцируется при вызове unpack_profile() и освобождается при recycle(). Аллоцируется буфер размером ровно под размер ICC-профиля т.е. до нескольких сотен килобайт.

Память для распаковки RAW

Память для временных буферов, нужных при распаковке RAW-данных может быт аллоцирована во время работы unpack() и освобождается до завершения этой функции. Размеры аллоцированных буферов невелики, в пределах нескольких десятков килобайт.

Память для постобработки

При постобработке изображений (унаследованной от dcraw) выделяется память под гистограмму (128 килобайт). Эта память выделяется при вызове dcraw_document_mode_processing() и dcraw_process(), а освобождается при вызове recycle().

Помимо этого, при работе dcraw_process() и использовании ряда имеющихся возможностей:

будет аллоцирован временный буфер, размер которого равен размеру результирующего изображения (из расчета 6-8 байт на пиксел для разных стадий обработки). При завершении промежуточной подстадии обработки, буфер с предыдущей копией изображения будет освобожден.
Если постобработка не используется, то временные буферы не аллоцируются.

Память для записи файла

Вызов dcraw_ppm_tiff_writer() аллоцирует память под одну строку выходного изображения. Аллоцированная память освобождается перед выходом из вызова.

Память для распаковки в буфер в памяти

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

Несовместимости с dcraw

Обработка Thumbnails от камер Kodak

В ряде камер Kodak preview (thumbnail) хранится в виде нескорректированного изображения. При извлечении его с помощью dcraw -e используются те же настройки баланса белого, коррекции цветов и так далее, что и для извлечения основных RAW-данных (включая удаление дефектов и вычитание dark frame, что ошибочно т.к. размер изображения другой).
В вызове LibRaw::unpack_thumb() всегда используется баланс белого, взятый из камеры (as shot), какие-либо настроки из imgdata.params не используются.

Для Всех остальных камер thumbnails извлекаются as-is, без каких-либо цветовых преобразований, как в dcraw, так и в LibRaw.

[вернуться к оглавлению]
Alex Tutubalin
Last modified: Tue Sep 16 14:44:48 MSD 2008