Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
lens.c File Reference
#include "common/global_mutexes.h"
#include "common/paths.h"
#include "common/utility.h"
#include "system/macros.h"
#include "common/module_versioning.h"
#include "common/logging.h"
#include "system/mem_alloc.h"
#include "system/openmp.h"
#include "system/target_clones.h"
#include "caches/pixelpipe_cache_alloc.h"
#include "glib.h"
#include "widgets/bauhaus.h"
#include "pixel/interpolation.h"
#include "common/file_location.h"
#include "common/imagebuf.h"
#include "common/opencl.h"
#include "develop/develop.h"
#include "develop/imageop.h"
#include "develop/imageop_gui.h"
#include "develop/tiling.h"
#include "iop/iop_api.h"
#include <assert.h>
#include <ctype.h>
#include <gtk/gtk.h>
#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "widgets/popup.h"
#include "widgets/widget_style.h"
#include "control/signal.h"
#include "develop/geometry/geometry.h"
#include "lensserious.h"
#include "lensserious_db.h"
#include "lensserious_vendor.h"
+ Include dependency graph for lens.c:

Go to the source code of this file.

Data Structures

struct  dt_iop_lensfun_params_t
 
struct  dt_iop_lensfun_gui_data_t
 
struct  dt_iop_lensfun_global_data_t
 
struct  _ls_tls_t
 
struct  dt_iop_lensfun_data_t
 
struct  dt_iop_lens_geometry_t
 

Macros

#define DT_LENS_MODIFY_DISTORTION_PACK    (DT_LENS_MODIFY_DISTORTION | DT_LENS_MODIFY_GEOMETRY | DT_LENS_MODIFY_SCALE)
 The three lensfun axes that always move together, as one flag.
 
#define DT_LENS_MODIFY_ANSEL_MASK   0xFF000000u
 
#define DT_LENS_MODIFY_ALL_AXES   ((int)~DT_LENS_MODIFY_ANSEL_MASK)
 

Typedefs

typedef enum dt_lens_modify_t dt_lens_modify_t
 What modify_flags holds, bit by bit.
 
typedef enum dt_lens_axis_t dt_lens_axis_t
 The correction axes, as an index rather than a bit – so a caller can loop.
 
typedef enum dt_lens_source_t dt_lens_source_t
 Where one axis takes its correction from. The same vocabulary for all three.
 
typedef enum dt_lens_type_t dt_lens_type_t
 
typedef enum dt_iop_lensfun_modflag_t dt_iop_lensfun_modflag_t
 
typedef struct dt_iop_lensfun_params_t dt_iop_lensfun_params_t
 
typedef struct dt_iop_lensfun_gui_data_t dt_iop_lensfun_gui_data_t
 
typedef struct dt_iop_lensfun_global_data_t dt_iop_lensfun_global_data_t
 
typedef struct _ls_tls_t _ls_tls_t
 
typedef struct dt_iop_lensfun_data_t dt_iop_lensfun_data_t
 
typedef struct dt_iop_lens_geometry_t dt_iop_lens_geometry_t
 

Enumerations

enum  dt_lens_modify_t {
  DT_LENS_MODIFY_TCA = 0x00000001 ,
  DT_LENS_MODIFY_VIGNETTING = 0x00000002 ,
  DT_LENS_MODIFY_DISTORTION = 0x00000008 ,
  DT_LENS_MODIFY_GEOMETRY = 0x00000010 ,
  DT_LENS_MODIFY_SCALE = 0x00000020 ,
  DT_LENS_SOURCE_SHIFT_TCA = 24 ,
  DT_LENS_SOURCE_SHIFT_DISTORTION = 26 ,
  DT_LENS_SOURCE_SHIFT_VIGNETTING = 28 ,
  DT_LENS_SOURCE_BITS = 0x3
}
 What modify_flags holds, bit by bit. More...
 
enum  dt_lens_axis_t {
  DT_LENS_AXIS_TCA = 0 ,
  DT_LENS_AXIS_DISTORTION ,
  DT_LENS_AXIS_VIGNETTING ,
  DT_LENS_AXIS_LAST
}
 The correction axes, as an index rather than a bit – so a caller can loop. More...
 
enum  dt_lens_source_t {
  DT_LENS_SOURCE_OFF = 0 ,
  DT_LENS_SOURCE_LENSFUN ,
  DT_LENS_SOURCE_EMBEDDED ,
  DT_LENS_SOURCE_MANUAL ,
  DT_LENS_SOURCE_LAST
}
 Where one axis takes its correction from. The same vocabulary for all three. More...
 
enum  dt_lens_type_t {
  DT_LENS_UNKNOWN = 0 ,
  DT_LENS_RECTILINEAR = 1 ,
  DT_LENS_FISHEYE = 2 ,
  DT_LENS_PANORAMIC = 3 ,
  DT_LENS_EQUIRECTANGULAR = 4 ,
  DT_LENS_FISHEYE_ORTHOGRAPHIC = 5 ,
  DT_LENS_FISHEYE_STEREOGRAPHIC = 6 ,
  DT_LENS_FISHEYE_EQUISOLID = 7 ,
  DT_LENS_FISHEYE_THOBY = 8
}
 
enum  dt_iop_lensfun_modflag_t { LENSFUN_MODFLAG_MASK = DT_LENS_MODIFY_DISTORTION | DT_LENS_MODIFY_TCA | DT_LENS_MODIFY_VIGNETTING }
 

Functions

static int _lens_axis_flags (const dt_lens_axis_t axis)
 The enable bits for one axis. Three of them for distortion; see the pack.
 
static int _lens_axis_presence_bit (const dt_lens_axis_t axis)
 The single bit that says whether an axis is on.
 
static int _lens_axis_shift (const dt_lens_axis_t axis)
 How far up modify_flags this axis's two source bits sit.
 
static gboolean _lens_source_applicable (const dt_lens_axis_t axis, const dt_lens_source_t source)
 Whether source means anything on axis.
 
static dt_lens_source_t _lens_source_decode (const int modify_flags, const gboolean tca_override, const dt_lens_axis_t axis)
 Decode one axis's source out of a raw flag word.
 
static dt_lens_source_t _lens_source_get (const dt_iop_lensfun_params_t *p, const dt_lens_axis_t axis)
 Where this axis takes its correction from.
 
static void _lens_source_set (dt_iop_lensfun_params_t *p, const dt_lens_axis_t axis, dt_lens_source_t source)
 Point one axis at a source, leaving every other axis alone.
 
static gboolean _lens_source_is (const dt_iop_lensfun_params_t *p, const dt_lens_axis_t axis, const dt_lens_source_t source)
 Is this axis taking its correction from source?
 
static gboolean _lens_axis_enabled (const dt_iop_lensfun_params_t *p, const dt_lens_axis_t axis)
 Is this axis correcting at all, from wherever?
 
static gboolean _lens_flags_move_pixels (const int modify_flags)
 Does this flag word describe anything that MOVES pixels?
 
static gboolean _lens_source_is_library_served (const dt_lens_source_t source)
 Is this source served by the LensSerious path, once the data has been prepared?
 
static gboolean _lens_flags_have_axis (const int modify_flags, const dt_lens_axis_t axis)
 Is this axis present in a flag word – typically get_modifier()'s done?
 
static int _lens_mask_for_mono (const gboolean monochrome)
 Which axes may be attempted on this image.
 
static gboolean _lens_image_embeds (dt_iop_module_t *self, const dt_lens_axis_t axis)
 Does THIS image carry a maker's profile for this axis?
 
static void _lens_rebuild_axis_rows (dt_iop_module_t *self)
 Every axis, for a fresh image.
 
static void _lens_gui_update_sensitivity (dt_iop_module_t *self)
 
static void _ls_tls_free (gpointer data)
 
static _ls_tls_t_ls_tls_get (void)
 This thread's cache block, allocated on first use. NULL only if that allocation failed, in which case every caller below degrades to "no database" rather than crashing.
 
static void _lens_report_db_failure (const char *path, const ls_db_open_status_t status, const int found_version, const char *detail)
 This thread's database handle, opened on first use.
 
static ls_db_t * _ls_db (void)
 
static gboolean _ls_find_camera (const char *maker, const char *model, ls_camera_t *out)
 The camera an EXIF maker/model names.
 
static long long _ls_find_lens (long long mount_id, float crop, float focal, const char *lens_name)
 The lens a free-text name names, as an id.
 
static gboolean _lens_data_available (const dt_iop_lensfun_data_t *d)
 Does this pipe data hold ANY resolvable correction source?
 
const char * name ()
 
const char * aliases ()
 
const char ** description (struct dt_iop_module_t *self)
 
int default_group ()
 
int operation_tags ()
 
int flags ()
 
int default_colorspace (dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
 
int legacy_params (dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
 
static char * _lens_sanitize (const char *orig_lens)
 
static __DT_CLONE_TARGETS__ int get_modifier (int *mods_done, int w, int h, const dt_iop_lensfun_data_t *d, int mods_filter, gboolean force_inverse, ls_modifier_t *mod, ls_modifier_t *vig_mod)
 Resolve the lens at one shooting configuration. THE modifier factory.
 
static void _lens_fill_vignette_row (float *const buf, const int width, const int ch)
 
__DT_CLONE_TARGETS__ int process (dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
 
int process_cl (struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
 
void tiling_callback (struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
 
int distort_transform (dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const __restrict points, size_t points_count)
 
int distort_backtransform (dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const __restrict points, size_t points_count)
 
void distort_mask (struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
 
void modify_roi_out (struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *roi_in)
 
void modify_roi_in (struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_out, dt_iop_roi_t *roi_in)
 
static const dt_iop_lensfun_params_t_lens_effective_params (dt_iop_module_t *self, const dt_iop_lensfun_params_t *const p)
 Which parameters are actually in force.
 
static void _lens_build_data (dt_iop_module_t *self, const dt_iop_lensfun_params_t *const p, dt_iop_lensfun_data_t *d)
 Build the lensfun state from resolved parameters. THE constructor.
 
static int _lens_used_mask (dt_iop_module_t *self)
 The lensfun modify mask this image allows: monochrome sensors get no TCA correction.
 
void commit_params (struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
static void _lens_free_data (void *ptr)
 
static int _lens_geometry_apply (const void *data, const dt_geometry_record_t *const record, float *points, size_t points_count, gboolean inverse)
 Apply the correction to points. inverse selects the direction, as get_modifier() means it: distort_transform() passes TRUE, distort_backtransform() passes FALSE.
 
static int _lens_geometry_transform (const void *data, const dt_geometry_record_t *const record, dt_geometry_chain_t *chain, float *points, size_t points_count)
 
static int _lens_geometry_backtransform (const void *data, const dt_geometry_record_t *const record, dt_geometry_chain_t *chain, float *points, size_t points_count)
 
gboolean geometry_record (dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
 
void init_pipe (struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
void cleanup_pipe (struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
void init_global (dt_iop_module_so_t *module)
 
static float get_autoscale (dt_iop_module_t *self, dt_iop_lensfun_params_t *p)
 
void reload_defaults (dt_iop_module_t *module)
 
void cleanup_global (dt_iop_module_so_t *module)
 
static int precision (double x, double adj)
 
static int ptr_array_insert_sorted (GPtrArray *array, const void *item, GCompareFunc compare)
 
static int ptr_array_find_sorted (const GPtrArray *array, const void *item, GCompareFunc compare)
 
static void ptr_array_insert_index (GPtrArray *array, const void *item, int index)
 
static void _lens_params_set_camera (dt_iop_module_t *self, const long long camera_id)
 Write the camera the user picked into the params. USER INTERACTION ONLY.
 
static void camera_set (dt_iop_module_t *self, long long camera_id)
 Show a camera in the panel. VIEW ONLY – writes no parameter.
 
static void camera_menu_select (GtkMenuItem *menuitem, gpointer user_data)
 
static void camera_menu_fill (dt_iop_module_t *self, const long long *ids, int n)
 Build the camera picker from a list of database ids.
 
static long long * _camera_all_ids (int *out_n)
 Every camera in the database, as ids the caller must free with dt_free_align().
 
static void parse_model (const char *txt, char *model, size_t sz_model)
 
static void camera_menusearch_clicked (GtkWidget *button, gpointer user_data)
 
static void lens_comboentry_focal_update (GtkWidget *widget, dt_iop_module_t *self)
 
static void lens_comboentry_aperture_update (GtkWidget *widget, dt_iop_module_t *self)
 
static void lens_comboentry_distance_update (GtkWidget *widget, dt_iop_module_t *self)
 
static void delete_children (GtkWidget *widget, gpointer data)
 
static const char * _lens_type_name (int type)
 A projection's name, replacing lfLens::GetLensTypeDesc().
 
static void _lens_params_set_lens (dt_iop_module_t *self, const long long lens_id)
 Write the lens the user picked into the params. USER INTERACTION ONLY.
 
static void lens_set (dt_iop_module_t *self, long long lens_id)
 Show a lens in the panel, and offer the sources it makes available. VIEW ONLY – writes no parameter.
 
static void lens_menu_select (GtkMenuItem *menuitem, gpointer user_data)
 
static void lens_menu_fill (dt_iop_module_t *self, const long long *ids, int n)
 
static long long * _lens_ids_for_camera (dt_iop_module_t *self, const char *model, int *out_n)
 The lenses to offer for the camera currently shown, as ids.
 
static void lens_menusearch_clicked (GtkWidget *button, gpointer user_data)
 
static void target_geometry_changed (GtkWidget *widget, gpointer user_data)
 
static int _lens_source_row (const dt_iop_lensfun_gui_data_t *g, const dt_lens_axis_t axis, const dt_lens_source_t source)
 Show only the controls the current sources actually use.
 
static int _lens_corrections_available (dt_iop_module_t *self, const dt_iop_lensfun_params_t *const p)
 Which corrections this configuration will actually apply.
 
static int _lens_database_offers (dt_iop_module_t *self, const dt_iop_lensfun_params_t *p)
 Which axes the lens DATABASE could correct for this image, whatever is selected.
 
static dt_lens_source_t _lens_source_displayed (const dt_iop_lensfun_gui_data_t *g, const dt_iop_lensfun_params_t *p, const dt_lens_axis_t axis)
 The source the panel is SHOWING for this axis.
 
static void _lens_rebuild_axis_row (dt_iop_module_t *self, const dt_lens_axis_t axis)
 Rebuild each axis's combobox to hold exactly the sources THIS image can supply.
 
static dt_lens_axis_t _lens_axis_of_widget (const dt_iop_lensfun_gui_data_t *g, const GtkWidget *w)
 Which axis a combobox belongs to, by widget identity.
 
static void _lens_axis_source_changed (GtkWidget *widget, gpointer user_data)
 
static GtkWidget_lens_add_axis_combobox (dt_iop_module_t *self, dt_iop_lensfun_gui_data_t *g, const dt_lens_axis_t axis, const char *label, const char *tooltip)
 Build one axis's source combobox and pack it at the end of the module.
 
void gui_changed (dt_iop_module_t *self, GtkWidget *w, void *previous)
 
static void autoscale_pressed (GtkWidget *button, gpointer user_data)
 
void gui_init (struct dt_iop_module_t *self)
 
void gui_update (struct dt_iop_module_t *self)
 Refresh GUI controls from current params and configuration.
 
void gui_cleanup (struct dt_iop_module_t *self)
 

Variables

static GPrivate _ls_tls_key = G_PRIVATE_INIT(_ls_tls_free)
 
static const dt_geometry_vtable_t _lens_geometry_vtable
 
static const char *const _lens_source_names [DT_LENS_SOURCE_LAST]
 
static const dt_lens_source_t _lens_axis_sources [DT_LENS_AXIS_LAST][DT_LENS_SOURCE_LAST]
 

Macro Definition Documentation

◆ DT_LENS_MODIFY_ALL_AXES

#define DT_LENS_MODIFY_ALL_AXES   ((int)~DT_LENS_MODIFY_ANSEL_MASK)

Every correction axis – the ones that exist and the ones that do not yet.

A macro rather than another dt_lens_modify_t member for a reason that would otherwise bite silently: 0xFF000000 does not fit in a signed int, so an enumerator of that value makes the whole enumeration's underlying type implementation-defined, and with it the type of every constant beside it.

Definition at line 205 of file lens.c.

◆ DT_LENS_MODIFY_ANSEL_MASK

#define DT_LENS_MODIFY_ANSEL_MASK   0xFF000000u

Everything Ansel stores in modify_flags that is not an axis.

Definition at line 195 of file lens.c.

◆ DT_LENS_MODIFY_DISTORTION_PACK

#define DT_LENS_MODIFY_DISTORTION_PACK    (DT_LENS_MODIFY_DISTORTION | DT_LENS_MODIFY_GEOMETRY | DT_LENS_MODIFY_SCALE)

The three lensfun axes that always move together, as one flag.

Distortion, projection and scaling are three bits because lensfun numbers them separately and that numbering is serialized. They are ONE correction: nothing has ever offered them apart – reload_defaults() sets all three, the old GUI's mask preserved them untouched, and no code path clears one without the others – and the profile a camera embeds in a raw file describes the lot with a single curve. So they are set, read and tested as a pack, and the DISTORTION bit is what says whether the pack is on.

Definition at line 191 of file lens.c.

Typedef Documentation

◆ _ls_tls_t

typedef struct _ls_tls_t _ls_tls_t

◆ dt_iop_lens_geometry_t

◆ dt_iop_lensfun_data_t

◆ dt_iop_lensfun_global_data_t

◆ dt_iop_lensfun_gui_data_t

◆ dt_iop_lensfun_modflag_t

◆ dt_iop_lensfun_params_t

◆ dt_lens_axis_t

The correction axes, as an index rather than a bit – so a caller can loop.

◆ dt_lens_modify_t

What modify_flags holds, bit by bit.

ONE 32-bit int, serialized into every user's history since Ansel began, now carrying two unrelated things. This comment and the accessors below are the only places that know how; nothing else in the file touches a bit of it.

*   bit  31 30 │ 29 28 │ 27 26 │ 25 24 │ 23 ... 6 │  5   4   3   2   1   0
*        ──┬── │ ──┬── │ ──┬── │ ──┬── │ ──┬───── │  │   │   │   │   │   │
*          │   │   │   │   │   │   │   │   │      │  │   │   │   │   │   └ TCA
*          │   │   │   │   │   │   │   │   │      │  │   │   │   │   └──── VIGNETTING
*          │   │   │   │   │   │   │   │   │      │  │   │   │   └──────── (unused)
*          │   │   │   │   │   │   │   │   │      │  │   │   └──────────── DISTORTION
*          │   │   │   │   │   │   │   │   │      │  │   └──────────────── GEOMETRY
*          │   │   │   │   │   │   │   │   │      │  └──────────────────── SCALE
*          │   │   │   │   │   │   │   │   └ free for a future axis
*          │   │   │   │   │   │   └ TCA's source
*          │   │   │   │   └ DISTORTION's source
*          │   │   └ VIGNETTING's source
*          â”” free; 31 is the SIGN BIT and must stay clear
* 

Low half, bits 0..23 – WHICH corrections run. These five values are lensfun's own, and they must stay lensfun's: they are in every history and every preset ever saved. (Bit 2 is skipped because upstream skips it.) A future axis goes here too, and every mask below keeps working without being edited.

High half, bits 24..31 – WHERE each correction comes from. Two bits per axis, values from dt_lens_source_t. Ansel's own, growing down from the top so the two halves can each grow for a long time before meeting.

Zero means the lens database. Every edit ever saved has the high half clear, so clear has to keep decoding to what those edits meant. The opposite polarity would behave identically right up until someone opened an old edit.

Do not read or write any of this directly. _lens_source_get(), _lens_source_set() and the _lens_* predicates below are the interface, and they exist because the encoding has three traps in it: a shift whose width is not the axis's width, an axis whose enable bit is really three bits, and a legacy boolean that has to stay in step with one of the fields.

◆ dt_lens_source_t

Where one axis takes its correction from. The same vocabulary for all three.

OFF is stored as the axis's own enable bit being clear, and the rest in that axis's two source bits at the top of the word. Splitting it across the two halves is not elegance, it is compatibility: the enable bits are lensfun's and are already in everyone's history, so they keep their meaning and the new information goes somewhere that was empty in every edit ever saved.

ZERO THEREFORE MEANS LENSFUN, and that is what makes this shippable without bumping the params version. The opposite polarity would behave identically until someone opened an old edit.

Not every value is legal on every axis – only TCA can be MANUAL, because only TCA has coefficients a user can type. _lens_source_applicable() is the one place that knows which, so the GUI and the pixel path cannot disagree about it.

◆ dt_lens_type_t

Enumeration Type Documentation

◆ dt_iop_lensfun_modflag_t

Enumerator
LENSFUN_MODFLAG_MASK 

Definition at line 283 of file lens.c.

◆ dt_lens_axis_t

The correction axes, as an index rather than a bit – so a caller can loop.

Enumerator
DT_LENS_AXIS_TCA 
DT_LENS_AXIS_DISTORTION 
DT_LENS_AXIS_VIGNETTING 
DT_LENS_AXIS_LAST 

Definition at line 224 of file lens.c.

◆ dt_lens_modify_t

What modify_flags holds, bit by bit.

ONE 32-bit int, serialized into every user's history since Ansel began, now carrying two unrelated things. This comment and the accessors below are the only places that know how; nothing else in the file touches a bit of it.

*   bit  31 30 │ 29 28 │ 27 26 │ 25 24 │ 23 ... 6 │  5   4   3   2   1   0
*        ──┬── │ ──┬── │ ──┬── │ ──┬── │ ──┬───── │  │   │   │   │   │   │
*          │   │   │   │   │   │   │   │   │      │  │   │   │   │   │   └ TCA
*          │   │   │   │   │   │   │   │   │      │  │   │   │   │   └──── VIGNETTING
*          │   │   │   │   │   │   │   │   │      │  │   │   │   └──────── (unused)
*          │   │   │   │   │   │   │   │   │      │  │   │   └──────────── DISTORTION
*          │   │   │   │   │   │   │   │   │      │  │   └──────────────── GEOMETRY
*          │   │   │   │   │   │   │   │   │      │  └──────────────────── SCALE
*          │   │   │   │   │   │   │   │   └ free for a future axis
*          │   │   │   │   │   │   └ TCA's source
*          │   │   │   │   └ DISTORTION's source
*          │   │   └ VIGNETTING's source
*          â”” free; 31 is the SIGN BIT and must stay clear
* 

Low half, bits 0..23 – WHICH corrections run. These five values are lensfun's own, and they must stay lensfun's: they are in every history and every preset ever saved. (Bit 2 is skipped because upstream skips it.) A future axis goes here too, and every mask below keeps working without being edited.

High half, bits 24..31 – WHERE each correction comes from. Two bits per axis, values from dt_lens_source_t. Ansel's own, growing down from the top so the two halves can each grow for a long time before meeting.

Zero means the lens database. Every edit ever saved has the high half clear, so clear has to keep decoding to what those edits meant. The opposite polarity would behave identically right up until someone opened an old edit.

Do not read or write any of this directly. _lens_source_get(), _lens_source_set() and the _lens_* predicates below are the interface, and they exist because the encoding has three traps in it: a shift whose width is not the axis's width, an axis whose enable bit is really three bits, and a legacy boolean that has to stay in step with one of the fields.

Enumerator
DT_LENS_MODIFY_TCA 
DT_LENS_MODIFY_VIGNETTING 
DT_LENS_MODIFY_DISTORTION 
DT_LENS_MODIFY_GEOMETRY 
DT_LENS_MODIFY_SCALE 
DT_LENS_SOURCE_SHIFT_TCA 
DT_LENS_SOURCE_SHIFT_DISTORTION 
DT_LENS_SOURCE_SHIFT_VIGNETTING 
DT_LENS_SOURCE_BITS 

Definition at line 165 of file lens.c.

◆ dt_lens_source_t

Where one axis takes its correction from. The same vocabulary for all three.

OFF is stored as the axis's own enable bit being clear, and the rest in that axis's two source bits at the top of the word. Splitting it across the two halves is not elegance, it is compatibility: the enable bits are lensfun's and are already in everyone's history, so they keep their meaning and the new information goes somewhere that was empty in every edit ever saved.

ZERO THEREFORE MEANS LENSFUN, and that is what makes this shippable without bumping the params version. The opposite polarity would behave identically until someone opened an old edit.

Not every value is legal on every axis – only TCA can be MANUAL, because only TCA has coefficients a user can type. _lens_source_applicable() is the one place that knows which, so the GUI and the pixel path cannot disagree about it.

Enumerator
DT_LENS_SOURCE_OFF 

no correction on this axis

DT_LENS_SOURCE_LENSFUN 

the calibration database. The value old edits decode to.

DT_LENS_SOURCE_EMBEDDED 

the profile the camera wrote into the raw file

DT_LENS_SOURCE_MANUAL 

coefficients the user typed. TCA only.

DT_LENS_SOURCE_LAST 

Definition at line 249 of file lens.c.

◆ dt_lens_type_t

Enumerator
DT_LENS_UNKNOWN 
DT_LENS_RECTILINEAR 
DT_LENS_FISHEYE 
DT_LENS_PANORAMIC 
DT_LENS_EQUIRECTANGULAR 
DT_LENS_FISHEYE_ORTHOGRAPHIC 
DT_LENS_FISHEYE_STEREOGRAPHIC 
DT_LENS_FISHEYE_EQUISOLID 
DT_LENS_FISHEYE_THOBY 

Definition at line 258 of file lens.c.

Function Documentation

◆ _camera_all_ids()

static long long * _camera_all_ids ( int *  out_n)
static

Every camera in the database, as ids the caller must free with dt_free_align().

Definition at line 2791 of file lens.c.

References _ls_db(), dt_alloc_align(), IS_NULL_PTR, and n.

Referenced by camera_menusearch_clicked().

◆ _lens_add_axis_combobox()

static GtkWidget * _lens_add_axis_combobox ( dt_iop_module_t self,
dt_iop_lensfun_gui_data_t g,
const dt_lens_axis_t  axis,
const char *  label,
const char *  tooltip 
)
static

Build one axis's source combobox and pack it at the end of the module.

Called in panel order, so the caller's sequence IS the layout: each axis's dependent controls are created straight after its combobox and land under it.

Definition at line 3520 of file lens.c.

References _lens_axis_source_changed(), dt_bauhaus_combobox_new(), dt_bauhaus_get_global(), dt_bauhaus_widget_set_label(), DT_GUI_MODULE, g, dt_iop_module_t::gui, tooltip, TRUE, and dt_iop_module_gui_t::widget.

Referenced by gui_init().

◆ _lens_axis_enabled()

static gboolean _lens_axis_enabled ( const dt_iop_lensfun_params_t p,
const dt_lens_axis_t  axis 
)
inlinestatic

Is this axis correcting at all, from wherever?

Definition at line 467 of file lens.c.

References _lens_source_get(), DT_LENS_SOURCE_OFF, and p.

◆ _lens_axis_flags()

static int _lens_axis_flags ( const dt_lens_axis_t  axis)
inlinestatic

The enable bits for one axis. Three of them for distortion; see the pack.

Definition at line 330 of file lens.c.

References DT_LENS_AXIS_DISTORTION, DT_LENS_AXIS_TCA, DT_LENS_AXIS_VIGNETTING, DT_LENS_MODIFY_DISTORTION_PACK, DT_LENS_MODIFY_TCA, and DT_LENS_MODIFY_VIGNETTING.

Referenced by _lens_axis_presence_bit(), and _lens_source_set().

◆ _lens_axis_of_widget()

static dt_lens_axis_t _lens_axis_of_widget ( const dt_iop_lensfun_gui_data_t g,
const GtkWidget w 
)
static

Which axis a combobox belongs to, by widget identity.

Definition at line 3477 of file lens.c.

References DT_LENS_AXIS_LAST, and g.

Referenced by _lens_axis_source_changed().

◆ _lens_axis_presence_bit()

static int _lens_axis_presence_bit ( const dt_lens_axis_t  axis)
inlinestatic

The single bit that says whether an axis is on.

Not the same as _lens_axis_flags() for distortion: the pack is three bits, and asking "is any of them set" would call an old edit's leftover GEOMETRY bit an enabled distortion correction. The DISTORTION bit alone is the answer; the other two ride with it.

Definition at line 348 of file lens.c.

References _lens_axis_flags(), DT_LENS_AXIS_DISTORTION, and DT_LENS_MODIFY_DISTORTION.

Referenced by _lens_flags_have_axis(), and _lens_source_decode().

◆ _lens_axis_shift()

static int _lens_axis_shift ( const dt_lens_axis_t  axis)
inlinestatic

How far up modify_flags this axis's two source bits sit.

Definition at line 354 of file lens.c.

References DT_LENS_AXIS_DISTORTION, DT_LENS_AXIS_TCA, DT_LENS_AXIS_VIGNETTING, DT_LENS_SOURCE_SHIFT_DISTORTION, DT_LENS_SOURCE_SHIFT_TCA, and DT_LENS_SOURCE_SHIFT_VIGNETTING.

Referenced by _lens_source_decode(), and _lens_source_set().

◆ _lens_axis_source_changed()

◆ _lens_build_data()

static void _lens_build_data ( dt_iop_module_t self,
const dt_iop_lensfun_params_t *const  p,
dt_iop_lensfun_data_t d 
)
static

Build the lensfun state from resolved parameters. THE constructor.

d is zeroed or already owns a lens; either way it owns a fresh deep copy of the database's calibration on return as a VALUE – nothing is owned, nothing is freed, and no lock is taken.

Definition at line 2041 of file lens.c.

References _lens_source_is(), _ls_db(), _ls_find_camera(), _ls_find_lens(), d, dt_iop_module_t::dev, DT_DEBUG_ALWAYS, DT_DEBUG_PIPE, dt_image_is_monochrome(), DT_LENS_AXIS_LAST, DT_LENS_AXIS_TCA, DT_LENS_RECTILINEAR, DT_LENS_SOURCE_EMBEDDED, DT_LENS_SOURCE_MANUAL, dt_print(), dt_image_t::exif_correction, FALSE, i, dt_develop_t::image_storage, IS_NULL_PTR, p, dt_image_t::p_height, dt_image_t::p_width, TRUE, and void().

Referenced by _lens_corrections_available(), commit_params(), geometry_record(), and get_autoscale().

◆ _lens_corrections_available()

static int _lens_corrections_available ( dt_iop_module_t self,
const dt_iop_lensfun_params_t *const  p 
)
static

Which corrections this configuration will actually apply.

Returns
the DT_LENS_MODIFY_* axes that resolve, masked to what the GUI reports.

GUI THREAD ONLY, and it needs no pipeline: which corrections a lens can serve is a pure function of the lens, the shooting configuration and the user's own switches. The database answers it in ~0.2 ms.

This used to be discovered by RENDERING. process() and process_cl() wrote the resolved flags into gui_data from the pipeline thread under a critical section, and a preview-pipe-finished signal then woke the GUI to read them back. That is a data race whatever the lock does – gui_data belongs to the GUI thread, which may free it while a worker is mid-write – and it made a label depend on a frame having been drawn. Neither was necessary: nothing here needs a pixel.

Definition at line 3612 of file lens.c.

References _lens_build_data(), _lens_data_available(), _lens_mask_for_mono(), d, dt_iop_module_t::dev, dt_dev_module_geometry_gui(), dt_image_is_monochrome(), FALSE, get_modifier(), dt_image_t::height, dt_iop_roi_t::height, dt_develop_t::image_storage, IS_NULL_PTR, LENSFUN_MODFLAG_MASK, m, p, dt_image_t::width, and dt_iop_roi_t::width.

Referenced by _lens_database_offers().

◆ _lens_data_available()

static gboolean _lens_data_available ( const dt_iop_lensfun_data_t d)
inlinestatic

Does this pipe data hold ANY resolvable correction source?

One predicate for every entry point, because the duplicated inline test already drifted once inside a single diff: get_modifier() learned that a maker's embedded profile needs no database lens and no crop factor, while process(), process_cl(), the three distort_*() callbacks, modify_roi_in() and the geometry record kept the old database-only bail-out – so a body absent from the database but carrying its own profile (the exact case the embedded path exists for) copied its input and returned before get_modifier() was ever consulted, and would have desynced masks from pixels the day only some of the seven were patched.

Definition at line 908 of file lens.c.

References d, and dt_iop_lensfun_data_t::knots_have.

Referenced by _lens_corrections_available(), _lens_geometry_apply(), distort_backtransform(), distort_mask(), distort_transform(), get_autoscale(), get_modifier(), modify_roi_in(), process(), and process_cl().

◆ _lens_database_offers()

static int _lens_database_offers ( dt_iop_module_t self,
const dt_iop_lensfun_params_t p 
)
static

Which axes the lens DATABASE could correct for this image, whatever is selected.

_lens_corrections_available() answers what WILL run, because get_modifier() now drops any axis pointed at another source – which is what the "corrections done" label wants and exactly not what greying a row wants. Asking with every axis forced to the database separates the two questions: capability here, selection there.

Definition at line 3276 of file lens.c.

References _lens_corrections_available(), _lens_source_set(), DT_LENS_AXIS_LAST, DT_LENS_SOURCE_LENSFUN, and p.

Referenced by _lens_rebuild_axis_row().

◆ _lens_effective_params()

static const dt_iop_lensfun_params_t * _lens_effective_params ( dt_iop_module_t self,
const dt_iop_lensfun_params_t *const  p 
)
static

Which parameters are actually in force.

p->modified == 0 means an edit whose correction was never written down: the parameters in force are the module's DEFAULTS, recomputed by reload_defaults() from the image's EXIF and whatever the calibration database happens to say TODAY – not the ones in history.

That is not a feature, it is a defect with a long tail. An image corrected on "auto" when its lens had no vignetting calibration silently GAINS vignetting the day the database learns one: same file, same history, different picture, and no way for the user to see it coming or pin it down. Adding a second source made it worse still, since the same edit would move to the maker's profile the day the reader for it shipped.

So new edits no longer take this path: modified defaults to 1 and reload_defaults() sets it, which writes the decision into history where it can be reproduced. This function exists for the edits already saved with 0, which must keep rendering the way they always have – migrating them would change pictures the user never asked to change, which is the very complaint.

Definition at line 2028 of file lens.c.

References dt_iop_module_t::default_params, and p.

Referenced by _lens_gui_update_sensitivity(), _lens_rebuild_axis_row(), commit_params(), geometry_record(), gui_update(), and lens_set().

◆ _lens_fill_vignette_row()

static void _lens_fill_vignette_row ( float *const  buf,
const int  width,
const int  ch 
)
inlinestatic

Definition at line 1311 of file lens.c.

References ch, DT_PIXEL_SIMD_CHANNELS, dt_simd_set1(), dt_store_simd_aligned(), k, width, and x.

◆ _lens_flags_have_axis()

static gboolean _lens_flags_have_axis ( const int  modify_flags,
const dt_lens_axis_t  axis 
)
inlinestatic

Is this axis present in a flag word – typically get_modifier()'s done?

Definition at line 504 of file lens.c.

References _lens_axis_presence_bit().

Referenced by _lens_rebuild_axis_row(), process(), and process_cl().

◆ _lens_flags_move_pixels()

static gboolean _lens_flags_move_pixels ( const int  modify_flags)
inlinestatic

Does this flag word describe anything that MOVES pixels?

Vignetting is a gain and leaves geometry alone, so a mask that includes it would make distort_transform() claim it displaces points when it does not. Every caller wants this question and several used to spell out the same four-term test, which is how one of them came to be missing a term.

Definition at line 481 of file lens.c.

References DT_LENS_MODIFY_DISTORTION_PACK, and DT_LENS_MODIFY_TCA.

Referenced by _lens_geometry_apply(), distort_backtransform(), distort_mask(), distort_transform(), modify_roi_in(), process(), and process_cl().

◆ _lens_free_data()

static void _lens_free_data ( void ptr)
static

Definition at line 2259 of file lens.c.

References g.

Referenced by geometry_record().

◆ _lens_geometry_apply()

static int _lens_geometry_apply ( const void data,
const dt_geometry_record_t *const  record,
float *  points,
size_t  points_count,
gboolean  inverse 
)
static

Apply the correction to points. inverse selects the direction, as get_modifier() means it: distort_transform() passes TRUE, distort_backtransform() passes FALSE.

Definition at line 2268 of file lens.c.

References _lens_data_available(), _lens_flags_move_pixels(), d, DT_ALIGNED_ARRAY, g, get_modifier(), dt_iop_roi_t::height, i, dt_geometry_record_t::in, and dt_iop_roi_t::width.

Referenced by _lens_geometry_backtransform(), and _lens_geometry_transform().

◆ _lens_geometry_backtransform()

static int _lens_geometry_backtransform ( const void data,
const dt_geometry_record_t *const  record,
dt_geometry_chain_t chain,
float *  points,
size_t  points_count 
)
static

Definition at line 2305 of file lens.c.

References _lens_geometry_apply(), and FALSE.

◆ _lens_geometry_transform()

static int _lens_geometry_transform ( const void data,
const dt_geometry_record_t *const  record,
dt_geometry_chain_t chain,
float *  points,
size_t  points_count 
)
static

Definition at line 2299 of file lens.c.

References _lens_geometry_apply(), and TRUE.

◆ _lens_gui_update_sensitivity()

◆ _lens_ids_for_camera()

static long long * _lens_ids_for_camera ( dt_iop_module_t self,
const char *  model,
int *  out_n 
)
static

The lenses to offer for the camera currently shown, as ids.

Parameters
modelwhen non-NULL and non-empty, only lenses whose name matches it – the fuzzy matcher, so an abbreviated EXIF string finds the full name.
out_nhow many were written. Free the result with dt_free_align().

Replaces FindLenses(camera, NULL, model, LF_SEARCH_SORT_AND_UNIQUIFY). The SORT half is done by lens_menu_fill(), which groups by maker and inserts sorted; the UNIQUIFY half is not needed, because these are database ids and a row cannot repeat.

Definition at line 3179 of file lens.c.

References _ls_db(), dt_alloc_align(), dt_iop_gui_data(), g, i, IS_NULL_PTR, m, model, and n.

Referenced by gui_update(), and lens_menusearch_clicked().

◆ _lens_image_embeds()

static gboolean _lens_image_embeds ( dt_iop_module_t self,
const dt_lens_axis_t  axis 
)
static

Does THIS image carry a maker's profile for this axis?

Asked per axis rather than per file: the makers do not all write the same set. Sony and Fujifilm publish distortion, lateral CA and vignetting; Olympus publishes the first two and no falloff; a DNG carries whichever opcodes its writer chose to emit.

Distortion and chromatic aberration answer from the same table – one radial curve per channel IS the two of them together, which is why the vendor formats do not separate them either.

Definition at line 535 of file lens.c.

References dt_iop_module_t::dev, DT_LENS_AXIS_DISTORTION, DT_LENS_AXIS_TCA, DT_LENS_AXIS_VIGNETTING, dt_image_t::exif_correction, FALSE, dt_develop_t::image_storage, and IS_NULL_PTR.

Referenced by _lens_rebuild_axis_row(), and reload_defaults().

◆ _lens_mask_for_mono()

static int _lens_mask_for_mono ( const gboolean  monochrome)
inlinestatic

Which axes may be attempted on this image.

A monochrome sensor has no colour channels to misalign, so lateral chromatic aberration is not a correction that means anything there – upstream refuses it and so do we. Everything else is unrestricted, including an axis nobody has defined yet.

Definition at line 516 of file lens.c.

References DT_LENS_MODIFY_ALL_AXES.

Referenced by _lens_corrections_available(), _lens_used_mask(), distort_backtransform(), distort_transform(), process(), and process_cl().

◆ _lens_params_set_camera()

static void _lens_params_set_camera ( dt_iop_module_t self,
const long long  camera_id 
)
static

Write the camera the user picked into the params. USER INTERACTION ONLY.

Split out of camera_set(), which refreshes the view and nothing else. gui_update() calls that one on every panel refresh, and it used to write p->camera and p->crop as it went – so merely opening the module rewrote the edit, replacing the stored camera string with the database's own spelling of the same body and the stored crop with that row's crop factor, with nothing but whatever committed history next deciding whether it stuck. Parameters change on user interaction and in reload_defaults(). Nowhere else.

Definition at line 2620 of file lens.c.

References _ls_db(), IS_NULL_PTR, maker, model, p, and dt_iop_module_t::params.

Referenced by camera_menu_select().

◆ _lens_params_set_lens()

static void _lens_params_set_lens ( dt_iop_module_t self,
const long long  lens_id 
)
static

Write the lens the user picked into the params. USER INTERACTION ONLY.

The counterpart of _lens_params_set_camera(), for the same reason: lens_set() refreshes the view and is called from gui_update(), so it cannot be the thing that writes p->lens.

Definition at line 2889 of file lens.c.

References _ls_db(), IS_NULL_PTR, p, and dt_iop_module_t::params.

Referenced by lens_menu_select().

◆ _lens_rebuild_axis_row()

static void _lens_rebuild_axis_row ( dt_iop_module_t self,
const dt_lens_axis_t  axis 
)
static

Rebuild each axis's combobox to hold exactly the sources THIS image can supply.

Displayed means available. A source with nothing behind it gets no row, rather than a greyed one: bauhaus honours entry sensitivity when the list is scrolled but not when a row is clicked, so a greyed row stayed selectable and then silently did nothing – which is the same class of bug as the fallback that used to be silent.

Rebuilt per image because availability is a property of the image: whether the database matched a lens, and whether the file carries a maker's profile for that axis. It does NOT depend on the current params, so this runs from gui_update() and not from the change callback, which would otherwise rebuild the widget it is being called by.

OFF is always offered – refusing to correct is always possible – and it is always first, so the list has a fixed anchor whatever else appears.

Definition at line 3398 of file lens.c.

References _lens_axis_sources, _lens_database_offers(), _lens_effective_params(), _lens_flags_have_axis(), _lens_image_embeds(), _lens_source_get(), _lens_source_is(), _lens_source_names, _lens_source_row(), dt_iop_module_t::dev, dt_bauhaus_combobox_add(), dt_bauhaus_combobox_clear(), dt_bauhaus_combobox_set(), dt_gui_widget_freeze, dt_image_is_monochrome(), dt_iop_gui_data(), DT_LENS_AXIS_DISTORTION, DT_LENS_AXIS_TCA, DT_LENS_SOURCE_EMBEDDED, DT_LENS_SOURCE_LAST, DT_LENS_SOURCE_LENSFUN, DT_LENS_SOURCE_MANUAL, DT_LENS_SOURCE_OFF, FALSE, g, i, dt_develop_t::image_storage, IS_NULL_PTR, n, p, dt_iop_module_t::params, row, and TRUE.

Referenced by _lens_axis_source_changed(), and _lens_rebuild_axis_rows().

◆ _lens_rebuild_axis_rows()

static void _lens_rebuild_axis_rows ( dt_iop_module_t self)
static

Every axis, for a fresh image.

Definition at line 3469 of file lens.c.

References _lens_rebuild_axis_row(), and DT_LENS_AXIS_LAST.

Referenced by camera_menu_select(), gui_update(), and lens_set().

◆ _lens_report_db_failure()

static void _lens_report_db_failure ( const char *  path,
const ls_db_open_status_t  status,
const int  found_version,
const char *  detail 
)
static

This thread's database handle, opened on first use.

The user's configuration directory is searched before the installed data, so a database regenerated against newer upstream calibrations can be dropped in without rebuilding. A failed open is final for the thread: retrying per lookup would turn a missing file into a slow one.

Report one failed database path, in terms of what the reader should do about it.

Silent for "there is nothing there", which is the ordinary case for the configuration directory: only a user who ran ansel-lens-db-update has a file there, and saying so on every start would be noise about a non-event.

Definition at line 668 of file lens.c.

References DT_DEBUG_ALWAYS, DT_DEBUG_PIPE, dt_print(), IS_NULL_PTR, and status.

Referenced by _ls_db().

◆ _lens_sanitize()

static char * _lens_sanitize ( const char *  orig_lens)
static

Definition at line 1077 of file lens.c.

Referenced by reload_defaults().

◆ _lens_source_applicable()

static gboolean _lens_source_applicable ( const dt_lens_axis_t  axis,
const dt_lens_source_t  source 
)
inlinestatic

Whether source means anything on axis.

MANUAL is TCA's alone: it is the only axis whose correction is two numbers a user can reasonably type. The others would need a whole polynomial. The GUI asks this to decide which rows to offer and the read path asks it to decide what an out-of-range stored value decodes to, so the two cannot drift apart.

Definition at line 373 of file lens.c.

References DT_LENS_AXIS_TCA, DT_LENS_SOURCE_LAST, DT_LENS_SOURCE_MANUAL, and DT_LENS_SOURCE_OFF.

Referenced by _lens_source_decode(), _lens_source_set(), and reload_defaults().

◆ _lens_source_decode()

static dt_lens_source_t _lens_source_decode ( const int  modify_flags,
const gboolean  tca_override,
const dt_lens_axis_t  axis 
)
static

Decode one axis's source out of a raw flag word.

Parameters
modify_flagsthe stored word.
tca_overridethe legacy boolean that is the ONLY record of manual TCA in an edit saved before the source fields existed. Reading it here is what makes such an edit open as MANUAL rather than as a database correction with two mysterious sliders beside it.

Takes the two fields rather than a params block because the pixel path holds them in dt_iop_lensfun_data_t, which is not a params block. One decode, two callers.

Definition at line 391 of file lens.c.

References _lens_axis_presence_bit(), _lens_axis_shift(), _lens_source_applicable(), DT_LENS_AXIS_TCA, DT_LENS_SOURCE_BITS, DT_LENS_SOURCE_LENSFUN, DT_LENS_SOURCE_MANUAL, and DT_LENS_SOURCE_OFF.

Referenced by _lens_source_get(), and get_modifier().

◆ _lens_source_displayed()

static dt_lens_source_t _lens_source_displayed ( const dt_iop_lensfun_gui_data_t g,
const dt_iop_lensfun_params_t p,
const dt_lens_axis_t  axis 
)
static

The source the panel is SHOWING for this axis.

The stored one when this image can supply it, and OFF when it cannot. _lens_rebuild_axis_row() drops the rows an image has nothing behind and falls back to OFF when the stored source is one of them – deliberately WITHOUT rewriting the params, so merely opening an image never edits its history. The dependent controls therefore have to follow the widget rather than the params: reading p directly is how the scale slider, or the manual coefficients, could sit under a picker reading "no correction".

Definition at line 3295 of file lens.c.

References _lens_source_get(), _lens_source_row(), DT_LENS_SOURCE_OFF, g, and p.

Referenced by _lens_gui_update_sensitivity().

◆ _lens_source_get()

static dt_lens_source_t _lens_source_get ( const dt_iop_lensfun_params_t p,
const dt_lens_axis_t  axis 
)
inlinestatic

Where this axis takes its correction from.

Definition at line 414 of file lens.c.

References _lens_source_decode(), and p.

Referenced by _lens_axis_enabled(), _lens_rebuild_axis_row(), _lens_source_displayed(), and _lens_source_is().

◆ _lens_source_is()

static gboolean _lens_source_is ( const dt_iop_lensfun_params_t p,
const dt_lens_axis_t  axis,
const dt_lens_source_t  source 
)
inlinestatic

Is this axis taking its correction from source?

Definition at line 459 of file lens.c.

References _lens_source_get(), and p.

Referenced by _lens_build_data(), and _lens_rebuild_axis_row().

◆ _lens_source_is_library_served()

static gboolean _lens_source_is_library_served ( const dt_lens_source_t  source)
inlinestatic

Is this source served by the LensSerious path, once the data has been prepared?

MANUAL counts, and that is the whole trick of it. _lens_build_data() replaces the lens's own TCA calibration with a linear one built from the user's two coefficients, so by the time the library is asked there is nothing manual left to know about – it is an ordinary lens with ordinary terms, and asking for LS_ENABLE_TCA is exactly right.

EMBEDDED counts too, since commit_params resolves the maker's table into the pipe data the same way; OFF is the only source with nothing behind it.

Definition at line 497 of file lens.c.

References DT_LENS_SOURCE_EMBEDDED, DT_LENS_SOURCE_LENSFUN, and DT_LENS_SOURCE_MANUAL.

Referenced by get_modifier().

◆ _lens_source_row()

static int _lens_source_row ( const dt_iop_lensfun_gui_data_t g,
const dt_lens_axis_t  axis,
const dt_lens_source_t  source 
)
static

Show only the controls the current sources actually use.

The row a source sits on in THIS image's combobox, or -1 if it is not offered.

Geometry belongs to the database's projection model, and the manual TCA coefficients to TCA-as-typed-by-the-user; neither means anything when its axis is off or fed from somewhere else. Hiding rather than merely grey-listing them is what keeps the module short: with three sources per axis the panel would otherwise grow a row for every combination nobody selected.

Against what the widget currently holds, not against the catalogue: the rows are rebuilt per image, so a source the file cannot supply has no row at all and its index would otherwise point at whatever moved up into its place.

Definition at line 3374 of file lens.c.

References g, and i.

Referenced by _lens_rebuild_axis_row(), and _lens_source_displayed().

◆ _lens_source_set()

static void _lens_source_set ( dt_iop_lensfun_params_t p,
const dt_lens_axis_t  axis,
dt_lens_source_t  source 
)
static

Point one axis at a source, leaving every other axis alone.

Setting a source clears the others by construction – they are one field, not three flags – so there is no illegal combination to guard against and no invariant a caller can forget to restore.

An inapplicable source is stored as OFF rather than silently corrected to something plausible: a caller asking for manual vignetting has a bug, and turning the axis off makes it visible instead of hiding it behind a database correction nobody asked for.

Definition at line 431 of file lens.c.

References _lens_axis_flags(), _lens_axis_shift(), _lens_source_applicable(), DT_LENS_AXIS_TCA, DT_LENS_SOURCE_BITS, DT_LENS_SOURCE_MANUAL, DT_LENS_SOURCE_OFF, FALSE, p, and TRUE.

Referenced by _lens_axis_source_changed(), _lens_database_offers(), and reload_defaults().

◆ _lens_type_name()

static const char * _lens_type_name ( int  type)
static

A projection's name, replacing lfLens::GetLensTypeDesc().

Definition at line 2866 of file lens.c.

References DT_LENS_EQUIRECTANGULAR, DT_LENS_FISHEYE, DT_LENS_FISHEYE_EQUISOLID, DT_LENS_FISHEYE_ORTHOGRAPHIC, DT_LENS_FISHEYE_STEREOGRAPHIC, DT_LENS_FISHEYE_THOBY, DT_LENS_PANORAMIC, DT_LENS_RECTILINEAR, and type.

Referenced by lens_set().

◆ _lens_used_mask()

static int _lens_used_mask ( dt_iop_module_t self)
static

The lensfun modify mask this image allows: monochrome sensors get no TCA correction.

Definition at line 2222 of file lens.c.

References _lens_mask_for_mono(), dt_iop_module_t::dev, dt_image_is_monochrome(), and dt_develop_t::image_storage.

Referenced by geometry_record().

◆ _ls_db()

◆ _ls_find_camera()

static gboolean _ls_find_camera ( const char *  maker,
const char *  model,
ls_camera_t *  out 
)
static

The camera an EXIF maker/model names.

Returns
TRUE when found.

Definition at line 767 of file lens.c.

References _ls_db(), _ls_tls_get(), _ls_tls_t::cam, _ls_tls_t::cam_cached, _ls_tls_t::cam_found, _ls_tls_t::cam_key, FALSE, IS_NULL_PTR, key, maker, model, out, and TRUE.

Referenced by _lens_build_data(), gui_update(), and reload_defaults().

◆ _ls_find_lens()

static long long _ls_find_lens ( long long  mount_id,
float  crop,
float  focal,
const char *  lens_name 
)
static

The lens a free-text name names, as an id.

Parameters
mount_idthe camera's mount, to prefer lenses that fit it; 0 for no preference.
cropthe camera's crop factor, which decides between lenses that share a NAME and differ only in the sensor they were calibrated on; 0 to ignore it.

The name comes from EXIF or from what the user typed, so this is the fuzzy matcher, not a lookup.

The database lens best matching this name, at this focal length.

focal is not a preference, it is a REFUSAL: a lens whose range cannot contain the focal the picture was taken at did not take the picture, whatever its name scores.

That matters because a name is often not an identifier. 197 entries in the catalogue are called "fixed lens" and 195 more "festes objektiv" – one per compact body, the model being the only thing that tells them apart. When the camera resolves, the mount does that work. When it does not, the matcher is handed a name shared by hundreds of different optics and every one of them scores identically: on a Ricoh GR II (18.3 mm, APS-C) the five tied candidates included the GR Digital's 5.9 mm lens on a 4.8x crop sensor, and the arbitrary pick among equals took it. Its distortion polynomial, applied to a frame it was never measured on, visibly bent the image instead of straightening it.

The library's own tie-breaks cannot help here: it weighs crop factor, but the crop passed is the CAMERA's and is 0 when no camera resolved, so the tie-break is inert in exactly the case that needs it. Focal range it never sees – ls_db_match_lens() takes no focal. Filtering here keeps that API unchanged; pushing the test into the matcher, where it could also inform the score, is the better long-term home for it.

Every one of the 1562 catalogue entries carries a usable range, so nothing is filtered out for want of data.

Definition at line 829 of file lens.c.

References _ls_db(), _ls_tls_get(), i, IS_NULL_PTR, key, _ls_tls_t::lens_cached, _ls_tls_t::lens_id, _ls_tls_t::lens_key, m, n, and TRUE.

Referenced by _lens_build_data(), and reload_defaults().

◆ _ls_tls_free()

static void _ls_tls_free ( gpointer  data)
static

Definition at line 627 of file lens.c.

References _ls_tls_t::db, dt_free, and IS_NULL_PTR.

◆ _ls_tls_get()

static _ls_tls_t * _ls_tls_get ( void  )
static

This thread's cache block, allocated on first use. NULL only if that allocation failed, in which case every caller below degrades to "no database" rather than crashing.

Definition at line 639 of file lens.c.

References _ls_tls_key, IS_NULL_PTR, and _ls_tls_t::lens_id.

Referenced by _ls_db(), _ls_find_camera(), and _ls_find_lens().

◆ aliases()

const char * aliases ( )

Definition at line 919 of file lens.c.

◆ autoscale_pressed()

static void autoscale_pressed ( GtkWidget button,
gpointer  user_data 
)
static

◆ camera_menu_fill()

static void camera_menu_fill ( dt_iop_module_t self,
const long long *  ids,
int  n 
)
static

Build the camera picker from a list of database ids.

Parameters
idsthe cameras to offer, n of them. Grouped by maker into submenus, as before.

Definition at line 2725 of file lens.c.

References _ls_db(), camera_menu_select(), dt_free, dt_free_gpointer(), dt_iop_gui_data(), g, i, IS_NULL_PTR, maker, model, n, ptr_array_find_sorted(), ptr_array_insert_index(), ptr_array_insert_sorted(), and TRUE.

Referenced by camera_menusearch_clicked().

◆ camera_menu_select()

static void camera_menu_select ( GtkMenuItem *  menuitem,
gpointer  user_data 
)
static

◆ camera_menusearch_clicked()

static void camera_menusearch_clicked ( GtkWidget button,
gpointer  user_data 
)
static

◆ camera_set()

static void camera_set ( dt_iop_module_t self,
long long  camera_id 
)
static

Show a camera in the panel. VIEW ONLY – writes no parameter.

Parameters
camera_idthe database id, or < 0 to clear the widget.

It takes an ID rather than a pointer because a camera is no longer a durable object owned by a process-wide database – it is a row, read on demand. The menu items below carry the same id, so nothing holds a pointer whose lifetime it does not control.

Definition at line 2645 of file lens.c.

References _ls_db(), dt_free, dt_iop_gui_data(), g, IS_NULL_PTR, maker, and model.

Referenced by camera_menu_select(), and gui_update().

◆ cleanup_global()

◆ cleanup_pipe()

void cleanup_pipe ( struct dt_iop_module_t self,
dt_dev_pixelpipe_t pipe,
dt_dev_pixelpipe_iop_t piece 
)

Definition at line 2339 of file lens.c.

References dt_dev_pixelpipe_iop_t::data, dt_free_align, and IS_NULL_PTR.

◆ commit_params()

void commit_params ( struct dt_iop_module_t self,
dt_iop_params_t p1,
dt_dev_pixelpipe_t pipe,
dt_dev_pixelpipe_iop_t piece 
)

◆ default_colorspace()

int default_colorspace ( dt_iop_module_t self,
dt_dev_pixelpipe_t pipe,
const dt_dev_pixelpipe_iop_t piece 
)

Definition at line 949 of file lens.c.

References IOP_CS_RGB.

◆ default_group()

int default_group ( )

Definition at line 934 of file lens.c.

References IOP_GROUP_REPAIR.

◆ delete_children()

static void delete_children ( GtkWidget widget,
gpointer  data 
)
static

Definition at line 2859 of file lens.c.

References void().

Referenced by lens_set().

◆ description()

const char ** description ( struct dt_iop_module_t self)

Definition at line 924 of file lens.c.

References dt_iop_set_description().

◆ distort_backtransform()

◆ distort_mask()

◆ distort_transform()

◆ flags()

int flags ( )

Definition at line 944 of file lens.c.

References IOP_FLAGS_ALLOW_TILING, IOP_FLAGS_TILING_FULL_ROI, and IOP_FLAGS_UNSAFE_COPY.

◆ geometry_record()

◆ get_autoscale()

◆ get_modifier()

static __DT_CLONE_TARGETS__ int get_modifier ( int *  mods_done,
int  w,
int  h,
const dt_iop_lensfun_data_t d,
int  mods_filter,
gboolean  force_inverse,
ls_modifier_t *  mod,
ls_modifier_t *  vig_mod 
)
static

Resolve the lens at one shooting configuration. THE modifier factory.

Parameters
mods_donereceives the axes actually resolved, as DT_LENS_MODIFY_* – an axis with no calibration for this focal is absent, which is how every caller decides whether there is anything to do.
w,hthe frame the correction is expressed over, in pixels.
dthe committed correction state.
mods_filterthe axes the caller will accept, intersected with the user's own.
force_inverseflip the direction, for the callers that undo a correction.
modfilled in. It owns nothing: an ls_modifier_t is a value, so there is no counterpart to the delete modifier this replaces and no way to leak one.
Returns
non-zero when at least one axis resolved.

Definition at line 1125 of file lens.c.

References _lens_data_available(), _lens_source_decode(), _lens_source_is_library_served(), d, DT_LENS_AXIS_DISTORTION, DT_LENS_AXIS_LAST, DT_LENS_AXIS_TCA, DT_LENS_AXIS_VIGNETTING, DT_LENS_MODIFY_DISTORTION, DT_LENS_MODIFY_GEOMETRY, DT_LENS_MODIFY_SCALE, DT_LENS_MODIFY_TCA, DT_LENS_MODIFY_VIGNETTING, and DT_LENS_SOURCE_EMBEDDED.

Referenced by _lens_corrections_available(), _lens_geometry_apply(), distort_backtransform(), distort_mask(), distort_transform(), get_autoscale(), modify_roi_in(), process(), and process_cl().

◆ gui_changed()

void gui_changed ( dt_iop_module_t self,
GtkWidget w,
void previous 
)

Definition at line 3537 of file lens.c.

References p, and dt_iop_module_t::params.

Referenced by gui_update().

◆ gui_cleanup()

void gui_cleanup ( struct dt_iop_module_t self)

Definition at line 3816 of file lens.c.

References IOP_GUI_FREE.

◆ gui_init()

◆ gui_update()

◆ init_global()

◆ init_pipe()

void init_pipe ( struct dt_iop_module_t self,
dt_dev_pixelpipe_t pipe,
dt_dev_pixelpipe_iop_t piece 
)

◆ legacy_params()

int legacy_params ( dt_iop_module_t self,
const void *const  old_params,
const int  old_version,
void new_params,
const int  new_version 
)

Definition at line 954 of file lens.c.

References d, dt_iop_module_t::default_params, and n.

◆ lens_comboentry_aperture_update()

static void lens_comboentry_aperture_update ( GtkWidget widget,
dt_iop_module_t self 
)
static

◆ lens_comboentry_distance_update()

static void lens_comboentry_distance_update ( GtkWidget widget,
dt_iop_module_t self 
)
static

◆ lens_comboentry_focal_update()

static void lens_comboentry_focal_update ( GtkWidget widget,
dt_iop_module_t self 
)
static

◆ lens_menu_fill()

static void lens_menu_fill ( dt_iop_module_t self,
const long long *  ids,
int  n 
)
static

◆ lens_menu_select()

static void lens_menu_select ( GtkMenuItem *  menuitem,
gpointer  user_data 
)
static

◆ lens_menusearch_clicked()

static void lens_menusearch_clicked ( GtkWidget button,
gpointer  user_data 
)
static

◆ lens_set()

◆ modify_roi_in()

◆ modify_roi_out()

void modify_roi_out ( struct dt_iop_module_t self,
const struct dt_dev_pixelpipe_t pipe,
struct dt_dev_pixelpipe_iop_t piece,
dt_iop_roi_t roi_out,
const dt_iop_roi_t roi_in 
)

Definition at line 1896 of file lens.c.

◆ name()

const char * name ( )

Definition at line 914 of file lens.c.

◆ operation_tags()

int operation_tags ( )

Definition at line 939 of file lens.c.

References IOP_TAG_DISTORT.

◆ parse_model()

static void parse_model ( const char *  txt,
char *  model,
size_t  sz_model 
)
static

Definition at line 2804 of file lens.c.

References model.

Referenced by gui_update().

◆ precision()

static int precision ( double  x,
double  adj 
)
static

gui stuff: inspired by ufraws lensfun tab:

Definition at line 2509 of file lens.c.

References x.

Referenced by _update_slider(), dt_bauhaus_slider_set_normalized(), gui_post_expose(), and lens_set().

◆ process()

◆ process_cl()

◆ ptr_array_find_sorted()

static int ptr_array_find_sorted ( const GPtrArray *  array,
const void item,
GCompareFunc  compare 
)
static

Definition at line 2567 of file lens.c.

References m, and r.

Referenced by camera_menu_fill(), and lens_menu_fill().

◆ ptr_array_insert_index()

static void ptr_array_insert_index ( GPtrArray *  array,
const void item,
int  index 
)
static

Definition at line 2596 of file lens.c.

Referenced by camera_menu_fill(), and lens_menu_fill().

◆ ptr_array_insert_sorted()

static int ptr_array_insert_sorted ( GPtrArray *  array,
const void item,
GCompareFunc  compare 
)
static

Definition at line 2533 of file lens.c.

References m, and r.

Referenced by camera_menu_fill(), and lens_menu_fill().

◆ reload_defaults()

◆ target_geometry_changed()

static void target_geometry_changed ( GtkWidget widget,
gpointer  user_data 
)
static

◆ tiling_callback()

void tiling_callback ( struct dt_iop_module_t self,
const struct dt_dev_pixelpipe_t pipe,
const struct dt_dev_pixelpipe_iop_t piece,
struct dt_develop_tiling_t tiling 
)
Todo:
: check if that's sufficiently large

Definition at line 1733 of file lens.c.

Variable Documentation

◆ _lens_axis_sources

const dt_lens_source_t _lens_axis_sources[DT_LENS_AXIS_LAST][DT_LENS_SOURCE_LAST]
static
Initial value:

Definition at line 3358 of file lens.c.

Referenced by _lens_rebuild_axis_row().

◆ _lens_geometry_vtable

const dt_geometry_vtable_t _lens_geometry_vtable
static
Initial value:
= {
NULL,
}
static int _lens_geometry_backtransform(const void *data, const dt_geometry_record_t *const record, dt_geometry_chain_t *chain, float *points, size_t points_count)
Definition lens.c:2305
static int _lens_geometry_transform(const void *data, const dt_geometry_record_t *const record, dt_geometry_chain_t *chain, float *points, size_t points_count)
Definition lens.c:2299

Definition at line 2311 of file lens.c.

Referenced by geometry_record().

◆ _lens_source_names

const char* const _lens_source_names[DT_LENS_SOURCE_LAST]
static
Initial value:
= {
[DT_LENS_SOURCE_OFF] = N_("no correction"),
[DT_LENS_SOURCE_LENSFUN] = N_("community profile"),
[DT_LENS_SOURCE_EMBEDDED] = N_("vendor profile"),
[DT_LENS_SOURCE_MANUAL] = N_("manual correction"),
}

Definition at line 3348 of file lens.c.

Referenced by _lens_rebuild_axis_row().

◆ _ls_tls_key

GPrivate _ls_tls_key = G_PRIVATE_INIT(_ls_tls_free)
static

Definition at line 635 of file lens.c.

Referenced by _ls_tls_get().