января 12, 2019


ПРЕД.

10.2. Darktable  и OpenCL

10.2.2. Как работает OpenCL

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

К счастью, отраслевой консорциум, возглавляемый The Khronos Group, разработал открытый стандартизованный интерфейс под названием OpenCL. Он позволяет использовать ваш GPU в качестве числового устройства обработки. OpenCL предлагает C99-подобный язык программирования, в котором уделено большое внимание параллельным вычислениям. Приложению, которое хочет использовать OpenCL, будет нужен исходный код, поддерживающий спецификации OpenCL, который оно передаст во время выполнения аппаратно-зависимому компилятору OpenCL. Таким образом, приложение может использовать OpenCL на разных графических архитектурах (даже в одно и тоже время). Все аппаратные "секреты" скрыты в компиляторе и обычно не видны пользователю (или приложению). Скомпилированный код OpenCL загружается на ваш графический процессор и - с помощью определенных вызовов API - он готов производить вычисления для вас.

января 11, 2019


ПРЕД.

Глава 10. Специальные темы

10.2. Darktable и OpenCL

Для повышения производительности darktable может использовать процессор видеокарты (GPU), используя технологию OpenCL.

10.2.1. Предыстория

Обработка изображений с высоким разрешением - это сложная задача, требующая современного компьютера. Как с точки зрения требований к памяти, так и с точки зрения требований к мощности процессора, получение изображения наилучшего качества обычного объёма в 15, 20 или 25 мегапикселей может быстро привести к нехватке ресурсов компьютера.

Приложение darktable не является в этом исключением. Наше решение не рисковать качеством обработки, привело к тому, что все вычисления выполняются с числами с плавающей точкой в буфере 4х32бит. Это медленнее, чем "обычные" 8 или 16-битные целочисленные вычисления, но устраняет большинство проблем постеризации или потери информации.

Многое было оптимизировано, чтобы сделать darktable как можно быстрее. Если вы используете текущую версию darktable на современном компьютере, вы можете не заметить "медлительность". Тем не менее, есть условия и некоторые модули, в которых вы будете чувствовать (или слышать вой вашего процессорного вентилятора), как ваш "бедный" многоядерный процессор вынужден справляться с работой.

Именно здесь и появляется OpenCL. OpenCL позволяет нам использовать огромную мощь современных видеокарт. Требование компьютерных игр к отображению высокодетализированных 3D-миров в современных шутерах от первого лица способствовало развитию графических процессоров. Корпорации ATI, NVIDIA поставили огромную вычислительную мощность в свои GPU для удовлетворения этих требований. Результатом этого являются современные графические карты с высокопараллельными графическими процессорами для быстрого вычисления поверхностей и текстур с высокой частотой кадров.

Вы не геймер, и не пользуетесь этой мощностью? Тогда вы должны хотя бы использовать её в darktable! Для задач высокопараллельных вычислений с плавающей точкой современные графические процессоры намного быстрее, чем центральные процессоры. Это особенно верно, когда вы хотите сделать те же самые шаги обработки над миллионами элементов. Типичный случай: обработка изображений высокого разрешения.

января 10, 2019

darktable 2.4 > Специальные темы

ПРЕД.


Глава 10. Специальные темы

В этой главе затрагивается несколько технических тем, которые могут помочь вам запустить darktable на конкретном оборудовании или оптимизировать производительность. Много дополнительной технической справочной информации, советов и трюков описано в обширном разделе блога, который вы можете найти на домашней странице приложения [http://www.darktable.org].

10.1. Darktable и память

Требования к памяти у darktable высоки. Простой расчет сделает это понятным. Если у вас есть 20-мегапиксельное изображение, то darktable по соображениям точности в рамках работы приложения будет хранить каждый пиксель изображения как ячейку размером 4x32бит и использовать операции с плавающей точкой. Для каждого полного изображения такого размера потребуется около 300МБ памяти. Поскольку мы хотим обрабатывать изображение, нам понадобится, по крайней мере, два буфера для каждого модуля - один для ввода и один для вывода. Если у нас будет более сложный модуль, его алгоритм может дополнительно потребовать несколько промежуточных буферов того же размера. Без дальнейшей оптимизации, нам может потребоваться памяти между 600МБ и 3ГБ только для хранения и обработки данных изображения. Кроме того у нас есть программный код darktable, код и данные всех динамических системных библиотек, а также не забываем о дополнительных буферах, где darktable хранит промежуточные изображения для быстрого доступа во время работы (mip map cache). В общем, для работы darktable хотел бы видеть, как минимум 4ГБ, чтобы успешно запускаться

10.1.1. Объём системной памяти

Из того, что сказано ранее, очевидно, что вашему компьютеру нужна корректная настройка памяти для работы darktable. Мы рекомендуем вам иметь не менее 4ГБ физической оперативной памяти плюс 4-8ГБ в разделе (файле) подкачки. Последнее требуется, так как ваша система может временно разместить неиспользуемые данные на диск, чтобы освободить физическую память.

Теоретически вы можете запускать darktable с меньшим количеством физической оперативной памяти и сбалансировать недостающий объём памяти достаточным количеством в разделе (файле) подкачки. Тем не менее, вы должны быть готовы к тому, что ваша система может начать сильно "тормозить", поскольку она будет постоянно считывать или записывать страницы данных на жесткий диск и с него. Существуют положительные отзывы о том, что это неплохо работает у отдельных пользователей, но для других данный подход может стать чрезвычайно медленным и неприемлемым ...

10.1.2. Доступное адресное пространство

Помимо объёма системной памяти существует еще один ограничивающий фактор: доступное адресное пространство вашей аппаратной архитектуры. Сколько памяти может быть адресовано процессом зависит от количества выделяемых бит для адресов, предлагаемых вашим процессором. Для CPU с 32-разрядными адресными регистрами это 2^32 байта, что составляет в общей сложности 4ГБ. Это абсолютный верхний предел памяти, который может использоваться процессом, и это представляет собой сложную ситуацию для darktable, как мы видели выше.

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

Прим. переводчика: термин "тайлинг" в русском языке не относится к устоявшемуся термину, в различных источниках он может быть заменён терминами "плитка" или "черепица", иногда его оставляют без перевода "tiling".

10.1.3. Фрагментация памяти

К сожалению, это еще не всё. Существует эффект, называемый фрагментацией памяти, который возникает при работе программного обеспечения, которое требует масштабного управления памятью. Если такая программа выделяет 5 раз по 300 Мбайт за раз и снова освобождает ее, эта память обычно должна быть доступна для одного большого выделения на 1,5 ГБ после этого. Это, однако, часто бывает не так. Менеджер распределение памяти системы больше не может видеть эту область как один непрерывный блок в 1,5 ГБ, а только как ряд из областей по 300МБ. Если нет другой свободной области в 1,5ГБ, то распределение не произойдёт. Во время запуска программы данный механизм забирает все больше и больше блоков памяти в пользу блоков меньшего размера. В darktable 2.0 кэш миниатюр (mip map cache) выделяет несколько небольших блоков памяти для каждого миниатюры, поэтому эта проблема возрастает ещё больше. По этой причине, начиная с darktable 2.0, не рекомендуется использовать 32-разрядные системы.

10.1.4. Дополнительные ограничения

Как будто описанного ранее не было достаточно, но существуют дополнительные ограничения, которые могут ограничивать доступ к памяти. На некоторых старых материнских платах вам необходимо активировать опцию "memory remapping" в BIOS, чтобы включить всю физически установленную память. Кроме того, если вы используете 32-битную ОС, вам, вероятно, понадобится версия ядра, которая имеет технологию "Physical Address Extension" (PAE). Часто, но не всегда, это относится к дистрибутивам Linux. Многие дистрибутивы поставляют разные ядра, некоторые с поддержкой PAE, а некоторые без PAE и вам нужно выбрать правильный. Чтобы проверить правильность установки системы, используйте команду "free" в терминале и проверьте вывод. Если на выходе отображается меньше ОЗУ, чем вы установили, у вас есть проблема, требующая исправления; например, у вас установлено 4ГБ, но ваше ядро видит только 3ГБ или меньше. Чтобы получить дополнительную помощь, вам необходимо проконсультироваться с руководством по BIOS и информацией о вашем дистрибутиве Linux.

10.1.5. Настройка darktable на 32-битной системе

Как мы видели, 32-битные системы представляют собой сложную среду для darktable. Тем не менее, некоторые пользователи работают с darktable на них, если основные требования в отношении системной памяти и темы, упомянутые в разделах выше, рассматриваются надлежащим образом.

Для запуска приложения есть несколько параметров настройки. Если вы произведёте первичную установку приложения, то darktable определит тип вашей системы и установит консервативные значения по умолчанию. Однако если вы обновите darktable c более старой версии (например, с 0.9.3 и до 1.0), скорее всего, у вас будут неоптимальные настройки. Последствиями для darktable могут быть частые прерывания работы из-за сбоев в распределении памяти или, что наиболее типично, darktable будет неспособен должным образом импортировать новую съёмку. Как частый симптом вы будете видеть черепа вместо миниатюр для многих ваших фотографий.

Если это так, найдите минуту, чтобы оптимизировать настройки. Вы найдете их в разделе "Основные настройки" (раздел 8.2, "Основные настройки" ) в диалоговом окне настроек darktable. Вы также можете найти эти параметры в качестве переменных конфигурации в $HOME/.config/darktable/darktablerc (%homepath%\\AppData\\Local\\darktable\\darktablerc для ОС Windows) и редактировать их там.

Ниже приведено краткое описание соответствующих параметров и их настроек:

"Количество фоновых потоков"
Этот параметр определяет максимальное количество потоков, разрешенных выполняться параллельно при импорте съёмки или выполнении других фоновых операций. В 32-битных системах вы можете иметь только один поток. Поэтому вам нужно установить этот параметр в 1; значения выше приведут к краху.

"Максимальный объём памяти (в МБ) для мозаики"
Этот параметр сообщает darktable сколько памяти (в МБ) оно может выделить для хранения буферов изображений во время операций модуля. Если изображение не может быть обработано в этих пределах в одном фрагменте, то оно будет обрабатываться несколькими частями, одна часть за другой. Установите это значение в 500Мб в качестве отправной точки. Вы можете поэкспериментировать с параметром позже, возможно, вы немного его увеличите, чтобы уменьшить издержки на тайлинг.

"Минимальный объём буфера (в МБ) для мозаики"
Это второй параметр, контролирующий тайлинг. Он устанавливает нижний предел размера промежуточных буферов изображений в мегабайтах. Параметр необходим, чтобы избежать чрезмерного деления изображения на фрагменты в некоторых случаях (для некоторых модулей). Установите этот параметр в значение 8МБ. Вы можете, при необходимости, увеличить его до 16МБ позже.

"Память в мегабайтах для кэша миниатюр"
Определяет, сколько миниатюр может храниться в памяти одновременно. В качестве отправной точки установите примерно на 256МБ. Начиная с darktable 2.0, кэш выделяет несколько небольших буферов на каждую миниатюру, что вызывает значительную фрагментацию памяти. Как объяснялось ранее, это создает проблемы для 32-битных систем. По этой причине, начиная с darktable 2.0, не рекомендуется использовать 32-разрядные системы.

10.1.6. Darktable на 64-битных системах

Здесь особо сказать нечего. Конечно, для 64-битных систем требуется достаточное количество системной памяти, поэтому рекомендуем минимум 4ГБ плюс настройку раздела (файла) подкачки. С другой стороны, 64-разрядная архитектура не страдает от ограничений присущим 32-битным архитектурам, таким как небольшое адресное пространство и фрагментация.

Большинство современных 64-разрядных процессоров Intel или AMD будут иметь доступное адресное пространство в диапазоне до нескольких терабайт. Под словом "современные" в этом контексте понимает, все процессоры AMD и Intel, выпущенные с 2003 и 2004 года, соответственно, и предлагающие 64-разрядный режим. Дистрибутивы Linux 64-бит доступны уже много лет.

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

В 64-разрядной системе вы можете спокойно оставить параметры конфигурации, связанные с тайлингом, по умолчанию: "Максимальный объём памяти (в МБ) для мозаики" имеет значение 1500МБ и "Минимальный объём буфера (в МБ) для мозаики" установлено на 16МБ. Если вы переходите от 32-разрядной к 64-разрядной системе, вам нужно будет проверить эти параметры и вручную изменить их, если необходимо, в диалоге настроек darktable.

Как правило, нет необходимости ограничивать себя количеством фоновых потоков в 64-битной системе. В многопроцессорной системе число от двух до восьми потоков может значительно ускорить создание миниатюр против одного потока. Причина заключается не в том, чтобы максимально использовать все ядра процессора, darktable их и так использует в пиксельном конвейере параллельно, но в скрытии задержки операций ввода-вывода.

Одно исключение стоит упомянуть. Если вы используете darktable для обработки сшитых панорам, например TIFF, созданных Hugin, то эти изображения могут достигать значительных размеров. Каждый фоновый поток должен выделять достаточное количество памяти для буферов хранения одного полного изображения, плюс промежуточные результаты и вывод. Это может быстро привести к нехватке памяти даже в хорошо оборудованной 64-битной системе. В этом случае уменьшите количество фоновых потоков до одного.

января 08, 2019


ПРЕД.
Глава 9. Создание сценариев на Lua

9.2. API-интерфейс Lua

API-интерфейс darktable Lua описан в его собственном руководстве с подробным описанием всех структур данных и функций. Вы можете загрузить руководство API с веб-страницы darktable [http://www.darktable.org/resources/]..

января 03, 2019

darktable 2.4 > Создание сценариев на Lua

ПРЕД.


Глава 9. Создание сценариев на Lua

Для повышения функциональности darktable поставляется с универсальным интерфейсом для использования языка сценариев.

9.1. Использование Lua

Lua может использоваться для выполнения определённых действий, которые darktable будет выполнять всякий раз, когда запускается указанное событие. Один из примеров позволяет вызвать внешнее приложение во время экспорта файла, чтобы применить дополнительные шаги обработки за пределами darktable.

Darktable использует Lua [http://www.lua.org/], который является независимым проектом, основанным в 1993 году и предоставляющим мощный, быстрый, легкий, встраиваемый язык сценариев. Lua широко используется многими приложениями с открытым исходным кодом, в коммерческих программах и для программирования игр.

Darktable использует версию Lua 5.2. Описание принципов и синтаксиса Lua выходит за рамки этого руководства пользователя. Подробное введение см. в "Руководство Lua" [http://lua.org.ru/contents_ru.html] и [http://www.lua.org/manual/5.2/manual.html].

Прим. переводчика: В версиях darktable 2.4.4. и более новых используется версия Lua 5.3.

9.1.1. Основные принципы

При запуске darktable автоматически запускает два сценария Lua:
  • скрипт с названием luarc в $DARKTABLE/share/darktable
  • скрипт luarc в каталоге конфигурации пользователя
$DARKTABLE обозначает каталог установки darktable в системе.

Это единственный раз, когда darktable будет запускать сценарии Lua самостоятельно. Сценарий может зарегистрировать вызов выполнения некоторых действий при наступлении определённых событий в darktable. Этот механизм вызова является основным способом запуска сценариев lua.

9.1.2. Пример простого lua сценария

Начнем с простого примера. Выведем некоторое сообщение на консоль. Создадим файл luarc в каталоге конфигурации пользователя darktable (обычно "~/.config/darktable/" или "%homepath%\\AppData\\Local\\darktable\\" для ОС Windows.) и добавим следующую строку:
print(“Hello World!”)
Запустим darktable из консоли и увидим сообщение "Hello World!", напечатанное в консоли. Ничего особенного, но это только начало...

На данный момент в сценарии нет ничего особенного для darktable. Мы используем стандартную функцию print для вывода строки на консоль. Это хорошо, но мало, мы можем сделать больше и лучше. Чтобы получить доступ к API darktable, нам сначала нужно вызвать его командой require и сохранить возвращаемый объект в переменной. Как только это будет сделано, мы можем получить доступ к API darktable в качестве подполей возвращаемого объекта. Все это задокументировано в справочном руководстве по Lua API darktable (см. раздел 9.2, "Lua API").
local darktable = require “darktable”
darktable.print_error(“Hello World !”)
Запустим скрипт... и ничего не происходит. Функция darktable.print_error аналогична print, но будет выводить сообщение только в том случае, если мы включили вывод отладочных данных на терминал для подсистемы lua (запуск darktable с параметрами -d lua в командной строке). Это рекомендуемый способ вывода отладочных данных darktable сценария lua.

9.1.3. Вывод списка изображений с цветовой меткой

Первый пример представил нам начальные основы lua и позволил проверить, что все работает правильно. Давайте сделаем что-нибудь более сложное. Например, попробуем вывести на консоль список изображений, которые отмечены красной цветовой меткой. Но прежде всего, узнаем, как представлено изображение в darktable?
local darktable = require “darktable”
local debug = require “darktable.debug”
print(darktable.debug.dump(darktable.database[1]))
Выполнение приведенного выше кода выведет на экран много информации. Мы посмотрим на неё через мгновение, но сначала давайте рассмотрим сам код.

Во-первых, мы получаем доступ к API darktable и, во-вторых, доступ к необязательным разделам API со вспомогательными функциями darktable.debug, которые будут помогать нам отлаживать сценарии lua.

darktable.database представляет собой таблицу, предоставленную API, которая содержит все изображения из базы данных. Каждая запись в базе данных является объектом изображения. Объекты изображения - это сложные объекты, которые позволяют нам манипулировать нашим изображением различными способами (все это описано в разделе руководства по API -types_dt_lua_image_t). Чтобы вывести информацию об изображениях, мы используем функцию darktable.debug.dump, которая предоставляет рекурсивный доступ к содержимому передаваемого параметра. Поскольку изображения являются сложными объектами, которые косвенно ссылаются на другие сложные объекты, результирующий результат огромен. Ниже приведен сокращённый пример одного такого объекта изображения:
toplevel (userdata,dt_lua_image_t) : /images/100.JPG
                                      publisher (string) : “”
                                      path (string) : “/images”
                                      move (function)
   exif_aperture (number) : 2.7999999523163
                                     rights (string) : “”
                                     make_group_leader (function)
                                     exif_crop (number) : 0
                                     duplicate_index (number) : 0
                                     is_raw (boolean) : false
                                     exif_iso (number) : 200
                                     is_ldr (boolean) : true
                                     rating (number) : 1
                                     description (string) : “”
                                     red (boolean) : false
                                     get_tags (function)
                                     duplicate (function)
                                     creator (string) : “”
                                     latitude (nil)
                                     blue (boolean) : false
   exif_datetime_taken (string) : “2014:04:27 14:10:27”
                                     exif_maker (string) : “Panasonic”
                                     drop_cache (function)
                                     title (string) : “”
                                     reset (function)
                                     create_style (function)
                                     apply_style (function)
   film (userdata,dt_lua_film_t) : /images
      1 (userdata,dt_lua_image_t): .toplevel [......]
   exif_exposure (number) : 0.0062500000931323
                                     exif_lens (string) : “”
   detach_tag (function): toplevel.film.2.detach_tag
                                     exif_focal_length (number) : 4.5
   get_group_members (function): toplevel.film.2.get_group_members
                                     id (number) : 1
   group_with (function): toplevel.film.2.group_with
   delete (function): toplevel.film.2.delete
                                     purple (boolean) : false
                                     is_hdr (boolean) : false
                                     exif_model (string) : “DMC-FZ200”
                                     green (boolean) : false
                                     yellow (boolean) : false
                                     longitude (nil)
                                     filename (string) : “100.JPG”
                                     width (number) : 945
   attach_tag (function): toplevel.film.2.attach_tag
                                     exif_focus_distance (number) : 0
                                     height (number) : 648
                                     local_copy (boolean) : false
                                     copy (function): toplevel.film.2.copy
   group_leader (userdata,dt_lua_image_t): .toplevel
Как мы видим, объект изображения имеет большое количество полей, которые предоставляют всю информацию о нём. Нас интересует поле "red" (красная цветовая метка). Это поле является логическим, и документация сообщает нам, что оно может быть выбрано. Теперь нам просто нужно найти все изображения с этим полем и распечатать их.
darktable = require “darktable”
   for _,v in ipairs(darktable.database) do
      if v.red then
print(tostring(v))
   end
end
Этот код должен быть достаточно прост для понимания на данный момент, но он содержит несколько интересных аспектов относительно lua, которые стоит выделить:
  • ipairs является стандартной функцией lua, которая будет перебирать все числовые индексы таблицы. Мы используем её здесь, потому что darktable.database имеет нечисловые индексы, которые являются функциями управления самой базой данных (например, добавление или удаление изображений).
  • Перебор таблицы возвращает 2 значения: ключ и объект изображения. В lua принято использовать переменную с именем "_" для хранения значений, которые нам не нужны в дальнейшем.
  • Обратите внимание, что мы используем стандартную функцию lua, tostring, а не специфическую для darktable darktable.debug.dump. Стандартная функция вернет имя для объекта, тогда как функция отладки будет печатать содержимое. Использование функция debug будет излишним. Это отличный инструмент отладки, но его нельзя использовать ни для чего другого.

9.1.4. Добавление простого вызова сценария комбинацией клавиш

До сих пор все наши скрипты выполнялись во время запуска приложения. Это ограниченное использование и не позволяет нам реагировать на реальные действия пользователя. Чтобы сделать более сложные вещи, нам нужно зарегистрировать функцию, которая будет вызываться при определённом событии. Наиболее распространенным событием для реагирования является сочетание клавиш.
darktable = require “darktable”
local function hello_shortcut(event, shortcut)
darktable.print(“Hello, I just received '”..event..
“' with parameter '”..shortcut..”'”)
end
darktable.register_event(“shortcut”,hello_shortcut,
“A shortcut that print its parameters”)
Теперь запустим darktable, перейдём в "Параметры darktable" => "Клавиатурные комбинации" => "Lua" => "A shortcut that print its parameters", назначим клавиатурную комбинацию и воспользуемся ею. На экране должно появиться сообщение.

Давайте детально рассмотрим код. Сначала мы определяем функцию с двумя параметрами. Эти параметры являются строками. Первый параметр - это тип события, которое запускает скрипт (в нашем случае это будет "shortcut"), а второй параметр – текстовое описание этого события ("A shortcut that print its parameters"). Сама функция вызывает darktable.print для вывода сообщения в всплывающем окне.

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

Попробуем сделать комбинацию клавиш немного более интерактивной. Сценарий будет просматривать изображение, которое пользователь в настоящее время выбрал или над которым находится курсор мыши, и повышать его рейтинг.
darktable = require “darktable”
darktable.register_event(“shortcut”,function(event,shortcut)
   local images = darktable.gui.action_images
    for _,v in pairs(images) do
      v.rating = v.rating + 1
   end
  end,”Increase the rating of an image”)
На этом этапе большая часть кода должна быть понятной. Всего несколько замечаний:
  • Вместо того чтобы отдельно объявлять функцию и ссылаться на нее, мы объявляем ее непосредственно в вызове darktable.register_event, этот способ эквивалентен ранее рассмотренному, но немного более компактен и сложнее для восприятия.
  • image.rating - это поле объекта изображения, которое содержит рейтинг (от 0 до 5 звезд, -1 означает отклонение изображения).
  • darktable.gui.action_images представляет собой таблицу, содержащую все изображения, представляющие интерес (входят в текущую коллекцию). Darktable будет воздействовать на выбранные изображения, если выбрано какое-либо изображение, или на изображение под курсором мыши, если изображений не выбрано. Эта функция позволяет легко следовать логике пользовательского интерфейса darktable в lua.

Если вы выберете изображение и несколько раз нажмете назначенную комбинацию клавиш, то всё будет работать правильно, но когда вы достигнете пяти звезд, darktable начнет выводить на консоль следующую ошибку:
                                      LUA ERROR : rating too high : 6
                                      stack traceback:
                                      [C]: in ?
                                      [C]: in function '__newindex'
./configdir/luarc:10: in function <./configdir/luarc:7>
                                         LUA ERROR : rating too high : 6
Таким образом сценарии на Lua сообщают нам об ошибках. Мы попытались установить рейтинг 6 для изображения, но рейтинг может достигать всего 5. Было бы правильно добавить проверку на правильность устанавливаемого рейтинга, но давайте рассмотрим сложный способ и отследим ошибку.
darktable.register_event(“shortcut”,function(event,shortcut)
   local images = darktable.gui.action_images
   for _,v in pairs(images) do
      result,message = pcall(function()
         v.rating = v.rating + 1
         end)
      if not result then
         darktable.print_error(“could not increase rating of image” ..
            tostring(v).. “:” ..message)
      end
   end
end,”Increase the rating of an image”)
Функция pcall улавливает любое исключение сгенерированное выполнением своего первого аргумента. Если нет исключения, то будет возвращено значение true плюс любой результат, возвращаемый функцией; если есть исключение, то будет возвращено false и сообщение об ошибке исключения. Далее мы просто проверяем эти результаты и выводим их на консоль...

9.1.5. Экспорт изображений с использованием Lua

Мы научились использовать lua для адаптации darktable к нашему конкретному рабочему процессу, давайте посмотрим, как использовать lua для несложного экспорта изображений. Darktable может экспортировать изображения в несколько интернет-сервисов, но всегда есть другие сервисы, которые ещё не поддерживаются. Если вы можете загрузить изображение в сервис через командную строку, вы можете использовать lua для её интеграции в пользовательский интерфейс darktable.

В следующем примере мы будем использовать lua для экспорта через scp (прим. переводчика: утилита удалённого копирования файлов, использующая в качестве транспорта ssh). Новое хранилище появится в пользовательском интерфейсе darktable и позволит экспортировать изображения в удаленное хранилище с помощью протокола ssh.
darktable = require "darktable"

darktable.preferences.register("scp_export","export_path",
   "string","target SCP path",
   "Complete path to copy to. Can include user and hostname","")

darktable.register_storage("scp_export","Export via scp",
   function( storage, image, format, filename,
        number, total, high_quality, extra_data)
      if coroutine.yield("RUN_COMMAND","scp "..filename.." "..
         darktable.preferences.read("scp_export",
            "export_path","string")) then
         darktable.print_error("scp failed for "..tostring(image))
      end
end)
Функция darktable.preferences.register добавляет новый параметр в меню "Параметры darktable" во вкладку "Параметры Lua". Параметры scp_export и export_path позволяют нам однозначно определить необходимые настройки. Эти поля используются повторно, когда мы читаем значение параметра. Параметр string сообщает Lua , что параметр является строкой. Он также может быть целым числом, именем файла или любым из типов, подробно описанных в руководстве по API, относящемся к types_lua_pref_type. Далее указывается текст параметра, отображаемый в меню "Параметры darktable", всплывающая подсказка при наведении мыши на поле ввода значения и значение по умолчанию.

Функция darktable.register_storage осуществляет вызов, который фактически регистрирует новое хранилище. Первый аргумент - это имя хранилища, второй - строка, которая будет отображаться в пользовательском интерфейсе, а последний - функция вызова для каждого экспортируемого изображения. Эта функция имеет множество параметров, но только параметр filename мы используем в этом примере. Он содержит имя временного файла, которое будет экспортировано darktable.

Этот код будет работать, но у него есть несколько ограничений. Это всего лишь простой пример:

  • Мы используем параметр для настройки целевого пути. Было бы лучше добавить элемент в пользовательский интерфейс модуля экспорта. Мы подробно расскажем, как это сделать в следующем разделе
  • Мы не проверяем возвращаемое значение scp. Команда может выполняться с ошибками, в частности, если пользователь неправильно установил параметр.
  • Этот сценарий не может считывать данные от пользователя. Доступ к удаленному хранилищу не должен использовать пароль. Пароль scp не может быть легко предоставлен, поэтому мы оставим сценарий таким каким он есть.
  • После выполнения сценария сообщения о выполнении не отображаются, только в левой нижней части приложения пользователю сообщается, что задание выполнено.
  • Мы используем функцию coroutine.yield для вызова внешней программы. Обычный os.execute блокирует другой код lua.

9.1.6. Создание элемента пользовательского интерфейса

Наш предыдущий пример был немного ограничен. В частности, использование параметра пути экспорта было не очень удобным. Мы можем сделать лучше, добавив элементы в пользовательский интерфейс диалогового окна экспорта.

Элементы пользовательского интерфейса создаются с помощью функции darktable_new_widget. Эта функция принимает вид виджета в качестве параметра и возвращает новый объект, соответствующий этому виджету. Затем можно установить для этого виджета различные поля, чтобы настроить его. Мы будем использовать этот объект в качестве параметра для различных функций, которые добавят его в пользовательский интерфейс darktable. Следующий простой пример добавляет "библиотеку" в режиме "Обзор" в виде простой надписи
local my_label = darktable.new_widget("label")
my_label.label = "Hello, world !"

dt.register_lib("test","test",false,{
   [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER",20},
   },my_label)
Существует хороший синтаксический трюк, который упрощает чтение и запись кода элемента интерфейса пользователя. Вы можете вызвать эти объекты как функции с таблицей ключевых значений в качестве аргументов. Это демонстрирует следующий пример. Он создает виджет контейнера с двумя встроенными виджетами: надпись и поле ввода текста.
   local my_widget = darktable.new_widget("box"){
      darktable.new_widget("label"){ label = "here => " },
      darktable.new_widget("entry"){ tooltip = "please enter text
here" }
   }
Теперь, когда мы это знаем, давайте немного улучшим наш скрипт.
darktable = require "darktable"

local scp_path = darktable.new_widget("entry"){
   tooltip="Complete path to copy to. Can include user and hostname",
   text = "",
   reset_callback = function(self) self.text = "" end
}

darktable.register_storage("scp_export","Export via scp",
   function( storage, image, format, filename,
        number, total, high_quality, extra_data)
      if coroutine.yield("RUN_COMMAND","scp "..filename.." "..
         scp_path.text
      ) then
         darktable.print_error("scp failed for "..tostring(image))
      end
      end,
      nil, --finalize
     nil, --supported
     nil, --initialize
    darktable.new_widget("box") {
    orientation ="horizontal",
    darktable.new_widget("label"){label = "target SCP PATH "},
    scp_path,
})

9.1.7. Распространение сценариев

До сих пор наш сценарий lua был в расположен в файле luarc. Это хороший способ для разработки своего скрипта, но не очень практичный для его распространения. Для этого мы должны разместить его в отдельном файле (модуле lua). Например, в файле scp-storage.lua как в примере:
--[[
SCP STORAGE
a simple storage to export images via scp

AUTHOR
Jérémy Rosen (jeremy.rosen@enst-bretagne.fr)

INSTALLATION
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR
is your darktable configuration directory
* add the following line in the file $CONFIGDIR/luarc
require "scp-storage"

USAGE
* select "Export via SCP" in the storage selection menu
* set the target directory
* export your images

LICENSE
GPLv2

]]
darktable = require "darktable"
darktable.configuration.check_version(...,{2,0,0})

local scp_path = darktable.new_widget("entry"){
   tooltip ="Complete path to copy to. Can include user and hostname",
   text = "",
   reset_callback = function(self) self.text = "" end
}

darktable.register_storage("scp_export","Export via scp",
   function( storage, image, format, filename,
        number, total, high_quality, extra_data)
      if coroutine.yield("RUN_COMMAND","scp "..filename.." "..
         scp_path.text
      ) then
         darktable.print_error("scp failed for "..tostring(image))
      end
      end,
      nil, --finalize
      nil, --supported
      nil, --initialize
      darktable.new_widget("box") {
      orientation ="horizontal",
      darktable.new_widget("label"){label = "target SCP PATH "},
      scp_path,
})
Darktable будет искать скрипты (следуя обычным правилам lua) в стандартных каталогах плюс в каталоге $CONFIGDIR/lua/?.lua. Поэтому наш скрипт можно вызвать, просто добавив require “scp-storage” в файл luarc. Несколько дополнительных заметок ...

  • Функция darktable.configuration.check_version проверяет совместимость. В параметр ... будет возвращено имя вашего скрипта, а параметр {2,0,0} будет версией API, с которой вы протестировали свой скрипт. Вы можете добавить несколько версий API, если вы разработает свой скрипт для нескольких версий darktable.
  • Обязательно объявите все свои функции как local, чтобы не загрязнять общее пространство имен.
  • Убедитесь, что вы не оставляете отладочные строки в своем коде, в частности darktable.print_error позволяет оставлять отладочные данные в конечном коде, не нарушая работу консоли.
  • Вы можете выбрать любую лицензию для своего скрипта, но скрипты, загруженные на веб-сайт darktable, должны соответствовать лицензии GPLv2.
  • После того, как вы заполнили все поля, проверили ваш код, вы можете загрузить его на нашу страницу сценариев [https://darktable.org/redmine/projects/darktable/wiki/LuaScripts] (прим. переводчика: в настоящий момент данный сайт предлагает искать скрипты по новому адресу [https://github.com/darktable-org/lua-scripts]).

9.1.8. Вызов Lua через DBus

Можно отправить команду lua в darktable через интерфейс DBus. Метод org.darktable.service.Remote.Lua принимает единственный строковый параметр, который интерпретируется как команда lua. Команда будет выполнена в текущем контексте lua и должна возвращать либо nil, либо строку. Результат будет возвращен в результат метода DBus.

Если вызов Lua приводит к ошибке, вызов метода DBus возвращает ошибку org.darktable.Error.LuaError с сообщением об ошибке lua в качестве сообщения, прикрепленного к ошибке DBus.

9.1.9. Использование darktable из сценариев lua

Предупреждение: эта возможность экспериментальная. Известно, что несколько элементов еще не работает в режиме использования darktable как библиотеки. Тщательное тестирование настоятельно рекомендуется.

Интерфейс lua позволяет использовать darktable из любого сценария lua. Загружая darktable в качестве библиотеки и предоставляя вам большую часть lua API (darktable используется без графического интерфейса, поэтому функции связанные с ним недоступны).

В качестве примера следующая программа будет распечатывать список всех изображений вашей библиотеки:
#!/usr/bin/env lua
package = require "package"
package.cpath=package.cpath..";./lib/darktable/lib?.so"

dt = require("darktable")(
"--library", "./library.db",
"--datadir", "./share/darktable",
"--moduledir", "./lib/darktable",
"--configdir", "./configdir",
"--cachedir","cachedir",
"--g-fatal-warnings")

require("darktable.debug")

for k,v in ipairs(dt.database) do
   print(tostring(v))
end
Обратите внимание на третью строку, указывающую на местоположение файла libdarktable.so.

Также обратите внимание, что вызов require возвращает функцию, которая может быть вызвана только один раз, и позволяет установить параметр командной строки darktable. В качестве файла библиотеки вы можете использовать :memory: в параметре –library, он будет особенно полезен здесь, если вы не хотите работать в своей библиотеке изображений.

января 02, 2019


ПРЕД.
Глава 8. Общие настройки и установки

8.5. Профили

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

Darktable поставляется с набором предустановленных профилей для нескольких модулей. Кроме того, вы можете определить свои собственные профили из любого модуля в режиме "Обработка" (см. раздел 3.2.3, "Профили модуля").

Предустановленные профили отображаются с символом блокировки. Их свойства автоматического применения не могут быть изменены.

Двойной щелчок на пользовательском профиле откроет меню.

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

"Показывать этот профиль только для фотографий, соответствующим указанным критериям"
Активируйте этот параметр, чтобы скрыть профиль в режиме "Обработка", если он не соответствует определенным условиям.

"Камера"
Значение, сопоставляемое с полем Exif, которое описывает вашу модель камеры; используйте "%" в качестве символа подстановки, обозначающего любую модель.

"Производитель"
Значение, сопоставляемое с полем Exif, которое описывает производителя вашей камеры; используйте "%" в качестве символа подстановки, обозначающего любого производителя.

"Объектив"
Значение, сопоставляемое с полем Exif, которое описывает ваш объектив; используйте "%" в качестве символа подстановки, обозначающего любой объектив.

"ISO"
Профиль используется только, если значение ISO вашего изображения находится в заданном диапазоне.

"Экспозиция"
Профиль используется только, если время экспозиции вашего изображения находится в пределах заданного диапазона; установите "+" в качестве верхнего значения, чтобы соответствует произвольно длинным экспозициям.

"Диафрагма"
Профиль используется только, если диафрагма вашего изображения находится в пределах заданного диапазона; установите "f/0" как наименьшее значение, для соответствия любым открытым диафрагмам; установите "f/+" в качестве верхнего значения для соответствия любым закрытым диафрагмам.

"Фокусное расстояние"
Профиль используется только, если фокусное расстояние вашего изображения находится в пределах заданного диапазона (от 0 до 1000).

Прим. переводчика: Параметр "Контейнер" не описан в официальном руководстве.

"Контейнер"
Определяет формат файла, к которому будет применён профиль.

января 01, 2019


ПРЕД.
Глава 8. Общие настройки и установки

8.4. Горячие клавиши

Darktable имеет большой набор комбинаций клавиш ("горячих" клавиш), которые настраиваются пользователем через диалог настроек.

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

Вы можете экспортировать свои сопоставления в файл или импортировать сопоставления из файла. Нажмите "По умолчанию", чтобы сбросить все комбинации до состояния по умолчанию.

Ниже приведена таблица с комбинациями клавиш для действий, доступных в darktable.

Общие параметры/Выход Ctrl+Q
Общие параметры/Режим светового стола (режим "Обзор") L
Общие параметры/Режим обработки (режим "Обработка") D
Общие параметры/Режим съёмки (режим "Камера") T
Общие параметры/Режим карты (режим "Карта") M
Общие параметры/Режим слайдшоу (режим "Слайдшоу") S
Общие параметры/Режим печати (режим "Печать") P
Общие параметры/Переключить режим .
Общие параметры/Переключить видимость заголовка Ctrl+H
Общие параметры/Переключить боковые панели Tab
Общие параметры/Переключить полноэкранный режим F11
Общие параметры/Покинуть полноэкранный режим Escape
Общие параметры/Приблизить Ctrl++
Общие параметры/Отдалить Ctrl+-
Операции с изображениями/Ориентация/Повернуть на 90° по часовой стрелке ]
Операции с изображениями/Ориентация/Повернуть на 90° против часовой стрелки [
Модули/История изменений/Копировать всё Ctrl+C
Модули/История изменений/Копировать Ctrl+Shift+C
Модули/История изменений/Вставить всё Ctrl+V
Модули/История изменений/Вставить Ctrl+Shift+V
Модули/Экспорт снимков/Экспортировать Ctrl+E
Модули/Лента снимков/Синяя метка F4
Модули/Лента снимков/Зелёная метка F3
Модули/Лента снимков/Пурпурная метка F5
Модули/Лента снимков/Красная метка F1
Модули/Лента снимков/Жёлтая метка F2
Модули/Лента снимков/Скопировать список изменений Ctrl+С
Модули/Лента снимков/Скопировать часть изменений Ctrl+Shift+С
Модули/Лента снимков/Создать копию снимка Ctrl+D
Модули/Лента снимков/Обратить выделение Ctrl+I
Модули/Лента снимков/Вставить список изменений Ctrl+V
Модули/Лента снимков/Вставить часть изменений Ctrl+Shift+V
Модули/Лента снимков/Оценка 0 0
Модули/Лента снимков/Оценка 1 1
Модули/Лента снимков/Оценка 2 2
Модули/Лента снимков/Оценка 3 3
Модули/Лента снимков/Оценка 4 4
Модули/Лента снимков/Оценка 5 5
Модули/Лента снимков/Отклонить R
Модули/Лента снимков/Выделить всё Ctrl+A
Модули/Лента снимков/Снять выделение Ctrl+Shift+A
Модули/Действия/Дубликат (Создать копию) Ctrl+D
Модули/Действия/Сгруппировать Ctrl+G
Модули/Действия/Убрать из коллекции (Удалить из базы данных) Delete
Модули/Действия/Разгруппировать Ctrl+Shift+G
Модули/Импорт/Импортировать съёмку Ctrl+Shift+I
Модули/Выделение/Обратить выделение Ctrl+I
Модули/Выделение/Выделить всё Ctrl+A
Модули/Выделение/Снять выделение Ctrl+Shift+A
Модули/Обзор/Приблизить Alt+2
Модули/Обзор/Макс. приближение Alt+1
Модули/Обзор/Макс. удаление Alt+4
Модули/Обзор/Отдалить Alt+3
Модули/LiveView/Переключить режим Live View V
Модули/Метаданные/Перейти к съёмке Ctrl+J
Модули/Недавние коллекции/Перейти к предыдущей подборке фотографий Ctrl+K
Модули/Метки/Метка Ctrl+T
Режимы/Обработка/Отменить Ctrl+Z
Режимы/Обработка/Вернуть Ctrl+Y
Режимы/Обработка/Уменьшить жёсткость кисти {
Режимы/Обработка/Уменьшить непрозрачность кисти <
Режимы/Обработка/Уменьшить радиус кисти [
Режимы/Обработка/Экспортировать Ctrl+E
Режимы/Обработка/Полноэкранный предпросмотр Z
Режимы/Обработка/Проверка цветового охвата Ctrl+G
Режимы/Обработка/Предыдущая фотография BackSpace
Режимы/Обработка/Следующая фотография Пробел
Режимы/Обработка/Увеличить жёсткость кисти }
Режимы/Обработка/Увеличить непрозрачность кисти >
Режимы/Обработка/Увеличить радиус кисти ]
Режимы/Обработка/Индикатор ошибок экспозиции O
Режимы/Обработка/Программная цветопроба Ctrl+S
Режимы/Обработка/Переключить ленту фотографий Ctrl+F
Режимы/Обработка/Масштаб 1:1 Alt+1
Режимы/Обработка/Заполнение по высоте Alt+2
Режимы/Обработка/Заполнение по ширине Alt+3
Режимы/Обзор/Перейти на страницу ниже Page_Down
Режимы/Обзор/Перейти на страницу выше Page_Up
Режимы/Обзор/Перейти выше G
Режимы/Обзор/Предпросмотр с определением фокуса Ctrl+Z
Режимы/Обзор/Предпросмотр Z
Режимы/Обзор/Оценка 0 0
Режимы/Обзор/Оценка 1 1
Режимы/Обзор/Оценка 2 2
Режимы/Обзор/Оценка 3 3
Режимы/Обзор/Оценка 4 4
Режимы/Обзор/Оценка 5 5
Режимы/Обзор/Отклонить R
Режимы/Обзор/Заново выровнять фотографии по сетке L
Режимы/Обзор/Прокрутить в центр `
Режимы/Обзор/Прокрутить вниз Down
Режимы/Обзор/Прокрутить влево Left
Режимы/Обзор/Прокрутить вправо Right
Режимы/Обзор/Прокрутить вверх Up
Режимы/Обзор/Выбрать один снимок Enter
Режимы/Обзор/Выбрать снимки (прим. переводчика: в приложении данный пункт переведён как "инвертировать выбор", что не соответствует действительности) Пробел
Режимы/Карта/Отменить Ctrl+Z
Режимы/Карта/Вернуть Ctrl+Y
Режимы/Карта/Переключить ленту фотографий Ctrl+F
Режимы/Печать/Переключить ленту фотографий Ctrl+F
Режимы/Слайдшоу/Начать и остановить Пробел
Режимы/Камера/Переключить ленту фотографий Ctrl+F