Skip to content

Latest commit

 

History

History
129 lines (106 loc) · 8.43 KB

File metadata and controls

129 lines (106 loc) · 8.43 KB

darktable core concepts: images, modules, and pipes

darktable produces a displayed or exported image by passing image data through a sequence of image operations (IOPs). Each one might change exposure, crop the image, or convert its colors. darktable records their settings in the edit history, which it stores in the library database and, by default, in an XMP sidecar file. It renders the image again from the source file and the edit history each time it needs to display or export it. Editing never changes the source image file.

The main objects

Term in code Simple meaning
Image operation (IOP), also called a module or processing module One kind of image change, such as exposure. Its code lives in src/iop/.
Module type (dt_iop_module_so_t) The loaded code and resources shared by all instances of one IOP, such as OpenCL kernels. so means "shared object": each IOP is built as a separate plugin library.
Module instance (dt_iop_module_t) One use of an IOP in an edit, with its own settings. In the darkroom, an instance is usually shown as a module panel (some, like finalscale, never have a visible UI panel); export (including darktable-cli) uses instances without panels. Users can usually add, remove, enable, disable, or reset instances.
Pixelpipe (dt_dev_pixelpipe_t, often called a pipe) The pipeline used to produce a particular output, such as the main darkroom view, its smaller preview or an exported image. Each pipe has its own sequence of pieces (next row), one per module instance.
Piece (dt_dev_pixelpipe_iop_t) One module instance's processing state in one pipe. It holds prepared processing data; piece->module points back to the module instance.
dt_image_t Information about an image, such as its ID and dimensions. It is not the pixels being processed.
dev (dt_develop_t) A working context for processing one image at a time. It holds image information (dt_image_t), module instances, edit history, and, when used for display, pipes.

"Module" has other meanings in darktable too: utility modules (the side panels of each view, in src/libs/) and view modules (lighttable, darkroom, and others, in src/views/).

In IOP code, a variable named module usually means a module instance. So does the parameter self in most IOP functions, and self->dev points back to its dev. In init_global() and cleanup_global(), self is the module type instead.

How the objects connect

A dev holds module instances and edit history. It has at least one instance of every IOP, whether or not the edit uses it. An instance with no history items keeps its default settings and default enabled state, which is off for most IOPs.

A dev used for display has three pipes: main-view, preview, and second-window. A dev used for export has none of its own; export creates a pipe and fills it from that dev's module instances and history. Each pipe has one piece per module instance, including disabled ones. Pieces are not copies of history items. Repeated edits to the same exposure module instance update one piece per pipe; adding another exposure module instance gives each pipe a second piece.

A module instance holds editable settings and whether it is enabled. In the darkroom it can also hold widgets; export uses module instances without them. Each piece holds processing data prepared for its pipe and its own enabled state. The pipe or the module's commit_params() can override that state for this pipe only; for example, demosaic is switched off for an image that isn't raw. process() reads piece->data.

When darktable rebuilds a pipe's settings, it starts each piece with default settings, then applies the active history items in order. An edit that only changes the newest history item updates just the pieces of that module instance. An edit that adds a history item rebuilds the settings of all pieces as above. See Module Lifecycle for when each case applies.

darktable can create several dev objects:

  • the main darkroom one, which is reused when you switch images
  • separate ones for slideshow images, darkroom snapshots, duplicate manager previews, and the image pinned in the second window
  • ones without pipes of their own: for exports (including darktable-cli), and short-lived ones for operations such as copying history or applying styles

Lighttable and map normally display cached thumbnails rather than owning a dev each. A missing thumbnail is rendered through the export code, which uses a temporary dev.

Settings and processing

Term in code Simple meaning
self->params (params_t) The module instance's current editable settings. These are the values that edit history records.
History item (dt_dev_history_item_t) A saved step in an image's edit history: a module instance's settings, whether it was enabled, and related blending settings. The user can select an earlier step in the history panel; the later items stay saved but are not applied. The applied items are the active history.
piece->data (often data_t) The settings prepared for this pipe to use while processing. A simple IOP may keep a copy of params_t here; another may calculate a different data_t.
self->data (module type level) in init_global(dt_iop_module_so_t *self) Resources shared by all module instances of one type, often OpenCL kernels. Each instance accesses them through its global_data field.
self->data (module instance level) in functions using dt_iop_module_t *self Optional data shared by one module instance's pipes. Pipes run in parallel threads, so access must be locked. For example, rasterfile caches a mask (an image marking where an edit applies) loaded from a file, and protects it with a mutex.
self->gui_data (often gui_data_t) Widgets and other interface state. It is absent when there is no module GUI, such as during export.

When settings change, darktable records the edit in edit history and updates the affected pipes. commit_params() prepares each pipe's piece->data from the settings it is given. process() then reads that data and transforms input pixels into output pixels. Some IOPs can instead use process_cl() on an OpenCL device (usually a GPU); darktable falls back to process() if OpenCL fails.

The pipe can reuse a cached result when its inputs and settings still match. This avoids repeating work when only part of the edit has changed.

Settings, prepared data, and instance data

params_t holds settings in a form that suits the user and the edit history; data_t holds them in a form that suits the processing code, and commit_params() converts one into the other. For example, color equalizer's white level is set in EV but processed as a multiplier, so commit_params() stores 2^EV (colorequal.c). Color balance rgb's hue shift is set in degrees and converted to radians (colorbalancergb.c).

Instance-level self->data lies between the two. It lasts as long as the module instance, across commits and renders, but it is never saved. It is not shared between instances: each instance has its own, shared by that instance's pipes and its GUI. The module decides when to refresh it. The data can outlive an image: when you switch images in the darkroom, one instance of each IOP is kept and reused. So rasterfile keys its cached mask on the settings and the image ID. It reloads the mask when either one changes, and also retries after a failed load.

Other terms

  • Processing order: IOPs run in a defined sequence. A later IOP receives the earlier IOP's output, so order can change the result. This is different from edit history, which records changes over time.
  • ROI (region of interest): The area and scale of the image requested for a processing step. The main view, preview, and export can request different regions or sizes. IOPs that change geometry (crop, rotate, lens correction) convert between their input and output ROI; see Regions of Interest.

For details, see IOP Module API for module settings and callbacks, Module Lifecycle for when those callbacks run, and Pixelpipe Architecture for pipe execution and caching. The corresponding types are declared in develop.h, imageop.h, and pixelpipe_hb.h.