108#include "lensserious.h"
109#include "lensserious_db.h"
110#include "lensserious_vendor.h"
191#define DT_LENS_MODIFY_DISTORTION_PACK \
192 (DT_LENS_MODIFY_DISTORTION | DT_LENS_MODIFY_GEOMETRY | DT_LENS_MODIFY_SCALE)
195#define DT_LENS_MODIFY_ANSEL_MASK 0xFF000000u
205#define DT_LENS_MODIFY_ALL_AXES ((int)~DT_LENS_MODIFY_ANSEL_MASK)
212 "the axis space and Ansel's own bits must not overlap");
216 "every correction axis must live in the axis half");
217_Static_assert((DT_LENS_SOURCE_BITS << DT_LENS_SOURCE_SHIFT_VIGNETTING) > 0,
218 "no source field may reach the sign bit of modify_flags");
221 "the source fields must not overlap each other");
279 "projection numbering must match ls_lens_type_t: stored params depend on it");
392 const gboolean tca_override,
442 p->modify_flags &= ~_lens_axis_flags(axis);
545 default:
return FALSE;
669 const int found_version,
const char *detail)
671 const char *reason = (!
IS_NULL_PTR(detail) && detail[0]) ? detail :
"no further detail";
675 case LS_DB_OPEN_NO_FILE:
679 case LS_DB_OPEN_UNREADABLE:
685 "[lens] `%s' exists but could not be read: %s. Check its permissions, and "
686 "that it is not truncated\n", path, reason);
689 case LS_DB_OPEN_SCHEMA:
695 "[lens] `%s' is a lens database of schema v%d, and this Ansel reads v%d. It "
696 "is almost certainly left over from an older install: rebuild and reinstall "
697 "so the file is replaced, or delete it if it is a stale copy in your "
698 "configuration directory.\n",
699 path, found_version, ls_db_schema_required());
719 ls_db_open_status_t config_status = LS_DB_OPEN_NO_FILE;
720 int config_version = -1;
721 char config_detail[256] = { 0 };
725 tls->
db = ls_db_open_diagnostic(config_path, &config_status, &config_version, config_detail,
726 sizeof(config_detail));
728 ls_db_open_status_t data_status = LS_DB_OPEN_NO_FILE;
729 int data_version = -1;
730 char data_detail[256] = { 0 };
735 tls->
db = ls_db_open_diagnostic(path, &data_status, &data_version, data_detail,
736 sizeof(data_detail));
748 "[lens] no calibration database, so no lens correction is available.\n");
755 if(config_status != LS_DB_OPEN_OK && config_status != LS_DB_OPEN_NO_FILE)
759 (config_status == LS_DB_OPEN_OK) ? config_path : path,
760 ls_db_schema_version(tls->
db));
793 if(found) *
out = cam;
830 const char *lens_name)
832 if(
IS_NULL_PTR(lens_name) || !lens_name[0])
return -1;
838 snprintf(
key,
sizeof(
key),
"%lld\x1f%.4f\x1f%.4f\x1f%s", mount_id, (
double)crop,
839 (
double)focal, lens_name);
845 const int n = ls_db_match_lens(db, NULL, lens_name, mount_id, crop,
m,
846 (
int)(
sizeof(
m) /
sizeof(*
m)));
848 for(
int i = 0;
i <
n;
i++)
851 if(ls_db_lens_by_id(db,
m[
i].lens_id, &cand) != 1)
continue;
856 && (focal < cand.min_focal - 0.05f || focal > cand.max_focal + 0.05f))
916 return _(
"_lens correction");
921 return _(
"vignette|chromatic aberrations|distortion");
928 _(
"linear, RGB, scene-referred"),
929 _(
"geometric and reconstruction, RGB"),
930 _(
"linear, RGB, scene-referred"));
955 void *new_params,
const int new_version)
957 if(old_version == 2 && new_version == 5)
974 } dt_iop_lensfun_params_v2_t;
976 const dt_iop_lensfun_params_v2_t *o = (dt_iop_lensfun_params_v2_t *)old_params;
982 n->modify_flags = o->modify_flags;
983 n->inverse = o->inverse;
987 n->aperture = o->aperture;
988 n->distance = o->distance;
989 n->target_geom = o->target_geom;
990 n->tca_override = o->tca_override;
991 g_strlcpy(
n->camera, o->camera,
sizeof(
n->camera));
992 g_strlcpy(
n->lens, o->lens,
sizeof(
n->lens));
1001 if(old_version == 3 && new_version == 5)
1017 } dt_iop_lensfun_params_v3_t;
1019 const dt_iop_lensfun_params_v3_t *o = (dt_iop_lensfun_params_v3_t *)old_params;
1028 memcpy(
n, o,
sizeof(*o));
1034 n->tca_r = o->tca_b;
1035 n->tca_b = o->tca_r;
1040 if(old_version == 4 && new_version == 5)
1057 } dt_iop_lensfun_params_v4_t;
1059 const dt_iop_lensfun_params_v4_t *o = (dt_iop_lensfun_params_v4_t *)old_params;
1068 n->tca_r = o->tca_b;
1069 n->tca_b = o->tca_r;
1079 const char *found_or = strstr(orig_lens,
" or ");
1080 const char *found_parenthesis = strstr(orig_lens,
" (");
1082 if(found_or || found_parenthesis)
1084 size_t pos_or = (size_t)(found_or - orig_lens);
1085 size_t pos_parenthesis = (size_t)(found_parenthesis - orig_lens);
1086 size_t pos = pos_or < pos_parenthesis ? pos_or : pos_parenthesis;
1090 char *new_lens = (
char *)malloc(pos + 1);
1092 strncpy(new_lens, orig_lens, pos);
1093 new_lens[pos] =
'\0';
1099 char *new_lens = strdup(orig_lens);
1105 char *new_lens = strdup(orig_lens);
1126 int mods_filter, gboolean force_inverse, ls_modifier_t *mod,
1127 ls_modifier_t *vig_mod)
1129 memset(mod, 0,
sizeof(*mod));
1130 if(mods_done) *mods_done = 0;
1137 int mods_todo =
d->modify_flags & mods_filter;
1159 const int reverse = force_inverse ? !
d->inverse :
d->inverse;
1182 const float knots_scale =
d->knots_scale * ((
d->scale > 0.f) ?
d->scale : 1.f);
1190 int knot_want = want & ~LS_ENABLE_GEOMETRY;
1193 knot_want &= ~LS_ENABLE_TCA;
1195 got = ls_modifier_init_knots(mod, &
d->ls_knots, w, h, knots_scale, knot_want, reverse);
1217 if((want & LS_ENABLE_TCA) && !(knot_want & LS_ENABLE_TCA) &&
d->ls_have)
1219 ls_modifier_t tca_mod;
1220 if(ls_modifier_init(&tca_mod, &
d->ls_lens,
d->crop, w, h,
d->focal,
d->aperture,
1221 d->distance, 1.f, (
int)
d->target_geom, LS_ENABLE_TCA, reverse)
1224 mod->tca = tca_mod.tca;
1225 mod->enabled |= LS_ENABLE_TCA;
1226 got |= LS_ENABLE_TCA;
1241 if((want & LS_ENABLE_GEOMETRY) &&
d->ls_have &&
d->crop > 0.f &&
d->focal > 0.f)
1243 if(ls_modifier_set_projection(mod, (
int)
d->ls_lens.type, (
int)
d->target_geom,
1245 got |= LS_ENABLE_GEOMETRY;
1249 got = ls_modifier_init(mod, &
d->ls_lens,
d->crop, w, h,
d->focal,
d->aperture,
1250 d->distance,
d->scale, (
int)
d->target_geom, want, reverse);
1262 if(mod->geometry_unsupported) done &= ~DT_LENS_MODIFY_GEOMETRY;
1280 if(!vig_wanted || vig_embedded == geom_embedded)
1289 else if(vig_embedded)
1290 ls_modifier_init_knots(vig_mod, &
d->ls_knots, w, h, 1.f, LS_ENABLE_VIGNETTING, reverse);
1292 ls_modifier_init(vig_mod, &
d->ls_lens,
d->crop, w, h,
d->focal,
d->aperture,
1293 d->distance, 1.f, (
int)
d->target_geom, LS_ENABLE_VIGNETTING, reverse);
1301 if(vig_wanted && (vig_mod->enabled & LS_ENABLE_VIGNETTING))
1304 done &= ~DT_LENS_MODIFY_VIGNETTING;
1307 if(mods_done) *mods_done = done;
1315 const dt_aligned_pixel_simd_t half =
dt_simd_set1(0.5f);
1320 for(
int k = 0;
k <
ch *
width;
k++) buf[
k] = 0.5f;
1337 const void *
const ivoid,
void *
const ovoid)
1344 const int ch_width =
ch * roi_in->
width;
1360 ls_modifier_t modifier;
1361 ls_modifier_t vig_modifier;
1362 get_modifier(&modflags, orig_w, orig_h,
d, used_lf_mask,
FALSE, &modifier, &vig_modifier);
1364 " calibrations, crop %.4f, focal %.1f)\n", modflags,
d->modify_flags,
1365 d->ls_lens.n_dist,
d->ls_lens.n_tca,
d->ls_lens.n_vig, (
double)
d->crop,
1385 && ls_eval_from_modifier(&vig_modifier, &vp);
1393 const size_t bufsize = (size_t)roi_out->
width * 2 * 3;
1395 size_t padded_bufsize;
1400#pragma omp parallel for default(none) \
1401 firstprivate(roi_out, roi_in, padded_bufsize, modifier, ch, d, buf, ovoid, ivoid, ch_width, interpolation, raw_monochrome, mask_display, have_vig, vp)
1403 for(
int y = 0; y < roi_out->
height; y++)
1406 ls_modifier_apply_subpixel_geometry(&modifier, roi_out->
x, roi_out->
y + y, roi_out->
width, 1, bufptr);
1410 for(
int x = 0;
x < roi_out->
width;
x++, bufptr += 6,
out +=
ch)
1412 dt_aligned_pixel_simd_t pixel = { 0.f };
1413 for(
int c = 0; c < 3; c++)
1415 if(
d->do_nan_checks && (!isfinite(bufptr[c * 2]) || !isfinite(bufptr[c * 2 + 1])))
1421 const float *
const inptr = (
const float *
const)ivoid + (
size_t)c;
1422 const float pi0 = fmaxf(fminf(bufptr[c * 2] - roi_in->
x, roi_in->
width - 1.0f), 0.0f);
1423 const float pi1 = fmaxf(fminf(bufptr[c * 2 + 1] - roi_in->
y, roi_in->
height - 1.0f), 0.0f);
1431 const float v = ls_eval_vignette_factor(&vp, (
float)(roi_out->
x +
x),
1432 (
float)(roi_out->
y + y));
1433 for(
int c = 0; c < 3; c++) pixel[c] *=
v;
1435 if(raw_monochrome) pixel[0] = pixel[2] = pixel[1];
1439 if(
d->do_nan_checks && (!isfinite(bufptr[2]) || !isfinite(bufptr[3])))
1446 const float *
const inptr = (
const float *
const)ivoid + (
size_t)3;
1447 const float pi0 = fmaxf(fminf(bufptr[2] - roi_in->
x, roi_in->
width - 1.0f), 0.0f);
1448 const float pi1 = fmaxf(fminf(bufptr[3] - roi_in->
y, roi_in->
height - 1.0f), 0.0f);
1454 else for(
int c = 0; c <
ch; c++)
out[c] = pixel[c];
1458 for(
int c = 0; c < 3; c++)
out[c] = pixel[c];
1472 for(
int y = 0; y < roi_out->
height; y++)
1475 ls_modifier_apply_vignetting(&modifier, roi_out->
x, roi_out->
y + y, roi_out->
width, 1,
1476 out, (
int)((
ch * roi_out->
width) *
sizeof(
float)));
1491 const size_t buf2size = (size_t)roi_out->
width * 2 * 3;
1492 size_t padded_buf2size;
1498#pragma omp parallel for default(none) \
1499 firstprivate(roi_out, roi_in, ovoid, ivoid, ch, padded_buf2size, modifier, mask_display, raw_monochrome, interpolation, ch_width, d, buf2, have_vig, vp)
1501 for(
int y = 0; y < roi_out->
height; y++)
1504 ls_modifier_apply_subpixel_geometry(&modifier, roi_out->
x, roi_out->
y + y, roi_out->
width, 1, buf2ptr);
1507 for(
int x = 0;
x < roi_out->
width;
x++, buf2ptr += 6,
out +=
ch)
1509 dt_aligned_pixel_simd_t pixel = { 0.f };
1510 for(
int c = 0; c < 3; c++)
1512 if(
d->do_nan_checks && (!isfinite(buf2ptr[c * 2]) || !isfinite(buf2ptr[c * 2 + 1])))
1518 const float *bufptr = ((
const float *)ivoid) + c;
1519 const float pi0 = fmaxf(fminf(buf2ptr[c * 2] - roi_in->
x, roi_in->
width - 1.0f), 0.0f);
1520 const float pi1 = fmaxf(fminf(buf2ptr[c * 2 + 1] - roi_in->
y, roi_in->
height - 1.0f), 0.0f);
1527 pixel[c] *= ls_eval_vignette_factor(&vp, buf2ptr[c * 2], buf2ptr[c * 2 + 1]);
1529 if(raw_monochrome) pixel[0] = pixel[2] = pixel[1];
1532 if(
d->do_nan_checks && (!isfinite(buf2ptr[2]) || !isfinite(buf2ptr[3])))
1539 const float *bufptr = ((
const float *)ivoid) + 3;
1540 const float pi0 = fmaxf(fminf(buf2ptr[2] - roi_in->
x, roi_in->
width - 1.0f), 0.0f);
1541 const float pi1 = fmaxf(fminf(buf2ptr[3] - roi_in->
y, roi_in->
height - 1.0f), 0.0f);
1547 else for(
int c = 0; c <
ch; c++)
out[c] = pixel[c];
1551 for(
int c = 0; c < 3; c++)
out[c] = pixel[c];
1565 for(
int y = 0; y < roi_in->
height; y++)
1568 ls_modifier_apply_vignetting(&modifier, roi_in->
x, roi_in->
y + y, roi_in->
width, 1,
out,
1569 (
int)((
ch * roi_in->
width) *
sizeof(
float)));
1596 ls_modifier_t modifier;
1601 const int devid = pipe->
devid;
1602 const int iwidth = roi_in->
width;
1603 const int iheight = roi_in->
height;
1604 const int owidth = roi_out->
width;
1605 const int oheight = roi_out->
height;
1606 const int roi_in_x = roi_in->
x;
1607 const int roi_in_y = roi_in->
y;
1608 const int roi_out_x = roi_out->
x;
1609 const int roi_out_y = roi_out->
y;
1613 size_t origin[] = { 0, 0, 0 };
1614 size_t oregion[] = { (size_t)owidth, (
size_t)oheight, 1 };
1615 size_t isizes[] = { (size_t)
ROUNDUPDWD(iwidth, devid), (size_t)
ROUNDUPDHT(iheight, devid), 1 };
1616 size_t osizes[] = { (size_t)
ROUNDUPDWD(owidth, devid), (size_t)
ROUNDUPDHT(oheight, devid), 1 };
1627 if(err != CL_SUCCESS)
goto error;
1631 switch(interpolation->
id)
1647 ls_modifier_t vig_modifier;
1648 get_modifier(&modflags, orig_w, orig_h,
d, used_lf_mask,
FALSE, &modifier, &vig_modifier);
1662 have_eval = ls_eval_from_modifier(&modifier, &
p) != 0;
1673 if(ls_eval_from_modifier(&vig_modifier, &vp)) ls_eval_adopt_vignetting(&
p, &vp);
1696 if(err != CL_SUCCESS)
goto error;
1704 const int vx =
d->inverse ? roi_out_x : roi_in_x;
1705 const int vy =
d->inverse ? roi_out_y : roi_in_y;
1706 const int vw =
d->inverse ? owidth : iwidth;
1707 const int vh =
d->inverse ? oheight : iheight;
1716 d->inverse ? osizes : isizes);
1717 if(err != CL_SUCCESS)
goto error;
1722 if(err != CL_SUCCESS)
goto error;
1759 tiling->factor_cl = 2.0f;
1760 tiling->maxbuf_cl = 1.0f;
1769 float *
const __restrict points,
size_t points_count)
1779 ls_modifier_t modifier;
1780 get_modifier(&modflags, orig_w, orig_h,
d, used_lf_mask,
TRUE, &modifier, NULL);
1785 for(
size_t i = 0;
i < points_count * 2;
i += 2)
1788 ls_modifier_apply_subpixel_geometry(&modifier, points[
i], points[
i + 1], 1, 1, buf);
1792 points[
i + 1] = buf[3];
1801 float *
const __restrict points,
size_t points_count)
1811 ls_modifier_t modifier;
1818 for(
size_t i = 0;
i < points_count * 2;
i += 2)
1821 ls_modifier_apply_subpixel_geometry(&modifier, points[
i], points[
i + 1], 1, 1, buf);
1825 points[
i + 1] = buf[3];
1835 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
1849 ls_modifier_t modifier;
1853 FALSE, &modifier, NULL);
1864 const size_t bufsize = (size_t)roi_out->
width * 2 * 3;
1865 size_t padded_bufsize;
1869 for(
int y = 0; y < roi_out->
height; y++)
1872 ls_modifier_apply_subpixel_geometry(&modifier, roi_out->
x, roi_out->
y + y, roi_out->
width, 1, bufptr);
1875 float *_out =
out + (size_t)y * roi_out->
width;
1876 for(
int x = 0;
x < roi_out->
width;
x++, bufptr += 6, _out++)
1878 if(
d->do_nan_checks && (!isfinite(bufptr[2]) || !isfinite(bufptr[3])))
1885 const float pi0 = bufptr[2] - roi_in->
x;
1886 const float pi1 = bufptr[3] - roi_in->
y;
1916 ls_modifier_t modifier;
1921 const int xoff = roi_in->
x;
1922 const int yoff = roi_in->
y;
1925 const int awidth = abs(
width);
1926 const int aheight = abs(
height);
1927 const int xstep = (
width < 0) ? -1 : 1;
1928 const int ystep = (
height < 0) ? -1 : 1;
1930 float xm = FLT_MAX, xM = -FLT_MAX, ym = FLT_MAX, yM = -FLT_MAX;
1931 const size_t nbpoints = 2 * awidth + 2 * aheight;
1940#pragma omp parallel default(none) reduction(min : xm, ym) reduction(max : xM, yM) \
1941 firstprivate(modifier, xoff, yoff, awidth, aheight, width, height, nbpoints, ystep, xstep, buf)
1945 for(
int i = 0;
i < awidth;
i++)
1946 ls_modifier_apply_subpixel_geometry(&modifier, xoff +
i * xstep, yoff, 1, 1, buf + 6 *
i);
1948 for(
int i = 0;
i < awidth;
i++)
1949 ls_modifier_apply_subpixel_geometry(&modifier, xoff +
i * xstep, yoff + (
height - 1), 1, 1, buf + 6 * (awidth +
i));
1951 for(
int j = 0; j < aheight; j++)
1952 ls_modifier_apply_subpixel_geometry(&modifier, xoff, yoff + j * ystep, 1, 1, buf + 6 * (2 * awidth + j));
1954 for(
int j = 0; j < aheight; j++)
1955 ls_modifier_apply_subpixel_geometry(&modifier, xoff + (
width - 1), yoff + j * ystep, 1, 1, buf + 6 * (2 * awidth + aheight + j));
1961 for(
size_t k = 0;
k < nbpoints;
k++)
1964 for(
size_t c = 0; c < 6; c+=2)
1966 const float x = buf[6 *
k + c];
1967 const float y = buf[6 *
k + c + 1];
1968 xm = isnan(
x) ? xm :
MIN(xm,
x);
1969 xM = isnan(
x) ? xM :
MAX(xM,
x);
1970 ym = isnan(y) ? ym :
MIN(ym, y);
1971 yM = isnan(y) ? yM :
MAX(yM, y);
1979 if(!isfinite(xm) || !(0 <= xm && xm < orig_w)) xm = 0;
1980 if(!isfinite(xM) || !(1 <= xM && xM < orig_w)) xM = orig_w;
1981 if(!isfinite(ym) || !(0 <= ym && ym < orig_h)) ym = 0;
1982 if(!isfinite(yM) || !(1 <= yM && yM < orig_h)) yM = orig_h;
1985 roi_in->
x = fmaxf(0.0f, roundf(xm - interpolation->
width));
1986 roi_in->
y = fmaxf(0.0f, roundf(ym - interpolation->
width));
1987 roi_in->
width = roundf(fminf(orig_w - roi_in->
x, xM - roi_in->
x + interpolation->
width));
1988 roi_in->
height = roundf(fminf(orig_h - roi_in->
y, yM - roi_in->
y + interpolation->
width));
1991 roi_in->
x = CLAMP(roi_in->
x, 0, (
int)floorf(orig_w));
1992 roi_in->
y = CLAMP(roi_in->
y, 0, (
int)floorf(orig_h));
1993 roi_in->
width = CLAMP(roi_in->
width, 1, (
int)ceilf(orig_w) - roi_in->
x);
1994 roi_in->
height = CLAMP(roi_in->
height, 1, (
int)ceilf(orig_h) - roi_in->
y);
2045 memset(&
d->ls_lens, 0,
sizeof(
d->ls_lens));
2054 long long mount_id = 0;
2055 float camera_crop = 0.f;
2070 d->crop = camera.crop_factor;
2071 camera_crop = camera.crop_factor;
2072 mount_id = camera.mount_id;
2089 if(
p->lens[0] && mount_id > 0)
2091 const long long lens_id =
_ls_find_lens(mount_id, camera_crop,
p->focal,
p->lens);
2093 if(lens_id >= 0 && !
IS_NULL_PTR(db) && ls_db_lens_by_id(db, lens_id, &
d->ls_lens) == 1)
2105 "[lens] `%s' is not a camera this database knows, so `%s' cannot be resolved to"
2106 " one lens; correcting from the database is declined\n",
p->camera,
p->lens);
2132 d->ls_lens.type = LS_LENS_RECTILINEAR;
2133 d->ls_lens.crop_factor =
d->crop;
2134 d->ls_lens.min_focal =
p->focal;
2135 d->ls_lens.max_focal =
p->focal;
2143 d->ls_lens.n_tca = 1;
2144 d->ls_lens.tca[0].model = LS_TCA_LINEAR;
2145 d->ls_lens.tca[0].focal =
p->focal;
2146 d->ls_lens.tca[0].terms[0] =
p->tca_r;
2147 d->ls_lens.tca[0].terms[1] =
p->tca_b;
2148 for(
int i = 2;
i < 6;
i++)
d->ls_lens.tca[0].terms[
i] = 0.f;
2151 d->modify_flags =
p->modify_flags;
2153 d->inverse =
p->inverse;
2154 d->scale =
p->scale;
2155 d->focal =
p->focal;
2156 d->aperture =
p->aperture;
2157 d->distance =
p->distance;
2158 d->target_geom =
p->target_geom;
2159 d->do_nan_checks =
TRUE;
2160 d->tca_override =
p->tca_override;
2173 d->knots_scale = 1.f;
2175 gboolean wants_embedded =
FALSE;
2193 "[lens] an axis asks for the vendor profile but this file carries none;"
2194 " correcting from the community profile instead\n");
2197 "[lens] this file's vendor profile could not be decoded;"
2198 " correcting from the community profile instead\n");
2201 d->knots_scale = (scale > 0.f) ? scale : 1.f;
2202 d->knots_have =
TRUE;
2213 d->do_nan_checks =
FALSE;
2215 else if((
int)
d->target_geom == (
int)
d->ls_lens.type)
2217 d->do_nan_checks =
FALSE;
2269 float *points,
size_t points_count, gboolean inverse)
2278 ls_modifier_t modifier;
2285 for(
size_t i = 0;
i < points_count * 2;
i += 2)
2288 ls_modifier_apply_subpixel_geometry(&modifier, points[
i], points[
i + 1], 1, 1, buf);
2292 points[
i + 1] = buf[3];
2352 const int program = 2;
2371 const dt_image_t *img = &
module->dev->image_storage;
2378 g_strlcpy(
d->lens, new_lens,
sizeof(
d->lens));
2380 g_strlcpy(
d->camera, img->
exif_model,
sizeof(
d->camera));
2414 d->modify_flags &= ~DT_LENS_MODIFY_TCA;
2419 for(
char cnt = 0, *c =
model; c <
model + 100 && *c !=
'\0'; c++)
2421 if(++cnt == 2) *c =
'\0';
2430 char mount[128] = { 0 };
2433 ls_db_mount_name(db, cam.mount_id, mount,
sizeof(mount));
2434 const gboolean fixed_lens = (mount[0] !=
'\0') && islower((
unsigned char)mount[0]);
2436 long long lens_id =
_ls_find_lens(cam.mount_id, cam.crop_factor,
d->focal,
d->lens);
2438 if(lens_id < 0 && fixed_lens)
2443 g_strlcpy(
d->lens,
"",
sizeof(
d->lens));
2445 const int n = ls_db_lenses_for_mount(db, cam.mount_id, NULL, 0);
2448 long long *ids = (
long long *)
dt_alloc_align(
sizeof(
long long) * (size_t)
n);
2451 ls_db_lenses_for_mount(db, cam.mount_id, ids,
n);
2454 size_t shortest = SIZE_MAX;
2455 for(
int i = 0;
i <
n;
i++)
2457 char maker[128] =
"", lmodel[256] =
"";
2458 if(ls_db_lens_name(db, ids[
i],
maker,
sizeof(
maker), lmodel,
sizeof(lmodel)) <= 0)
2460 const size_t len = strlen(lmodel);
2465 g_strlcpy(
d->lens, lmodel,
sizeof(
d->lens));
2476 if(ls_db_lens_by_id(db, lens_id, &lens) == 1)
2480 d->crop = cam.crop_factor;
2482 module->workflow_enabled = dt_image_needs_rawprepare(img);
2513 if(
x == 0)
return 1;
2535 int length = array->len;
2536 g_ptr_array_set_size(array, length + 1);
2537 const void **root = (
const void **)array->pdata;
2539 int m = 0, l = 0,
r = length - 1;
2542 if(l <=
r && !root[
r])
r--;
2547 int cmp = compare(root[
m], item);
2562 memmove(root +
m + 1, root +
m,
sizeof(
void *) * (length -
m));
2569 int length = array->len;
2570 void **root = array->pdata;
2572 int l = 0,
r = length - 1;
2575 if(!length)
return -1;
2583 cmp = compare(root[
m], item);
2599 int length = array->len;
2600 g_ptr_array_set_size(array, length + 1);
2601 root = (
const void **)array->pdata;
2602 memmove(root + index + 1, root + index,
sizeof(
void *) * (length - index));
2625 char maker[128] =
"",
model[256] =
"", variant[128] =
"";
2629 variant,
sizeof(variant)) != 1
2630 || ls_db_camera_by_id(db, camera_id, &cam) != 1)
2633 g_strlcpy(
p->camera,
model,
sizeof(
p->camera));
2634 p->crop = cam.crop_factor;
2650 char maker[128] =
"",
model[256] =
"", variant[128] =
"";
2654 variant,
sizeof(variant)) != 1
2655 || ls_db_camera_by_id(db, camera_id, &cam) != 1)
2657 gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
g->camera_model))),
"");
2658 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->camera_model),
"");
2663 g->camera_id = camera_id;
2666 gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
g->camera_model))), fm);
2672 char _variant[
sizeof(variant) + 4];
2674 snprintf(_variant,
sizeof(_variant),
" (%s)", variant);
2678 char mount[128] =
"";
2679 ls_db_mount_name(db, cam.mount_id, mount,
sizeof(mount));
2681 fm = g_strdup_printf(_(
"maker:\t\t%s\n"
2684 "crop factor:\t%.1f"),
2685 maker,
model, _variant, mount, cam.crop_factor);
2686 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->camera_model), fm);
2698 const long long camera_id =
2699 (
long long)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem),
"lens-camera-id"));
2728 GPtrArray *makers, *submenus;
2732 gtk_widget_destroy(GTK_WIDGET(
g->camera_menu));
2733 g->camera_menu = NULL;
2741 submenus = g_ptr_array_new();
2742 for(
int i = 0;
i <
n;
i++)
2744 char maker[128] =
"",
model[256] =
"", variant[128] =
"";
2746 variant,
sizeof(variant)) != 1)
2757 submenu = gtk_menu_new();
2761 submenu = (
GtkWidget *)g_ptr_array_index(submenus, idx);
2764 item = gtk_menu_item_new_with_label(
model);
2767 gchar *fm = g_strdup_printf(
"%s (%s)",
model, variant);
2768 item = gtk_menu_item_new_with_label(fm);
2771 gtk_widget_show(item);
2772 g_object_set_data(G_OBJECT(item),
"lens-camera-id", GINT_TO_POINTER((gint)ids[
i]));
2774 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
2777 g->camera_menu = GTK_MENU(gtk_menu_new());
2778 for(
unsigned i = 0;
i < makers->len;
i++)
2780 GtkWidget *item = (
GtkWidget *)gtk_menu_item_new_with_label((
const gchar *)g_ptr_array_index(makers,
i));
2781 gtk_widget_show(item);
2782 gtk_menu_shell_append(GTK_MENU_SHELL(
g->camera_menu), item);
2783 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), (
GtkWidget *)g_ptr_array_index(submenus,
i));
2786 g_ptr_array_free(submenus,
TRUE);
2787 g_ptr_array_free(makers,
TRUE);
2796 const int n = ls_db_list_cameras(db, NULL, 0);
2797 if(
n <= 0)
return NULL;
2798 long long *ids = (
long long *)
dt_alloc_align(
sizeof(
long long) * (size_t)
n);
2800 *out_n = ls_db_list_cameras(db, ids,
n);
2806 while(txt[0] && isspace(txt[0])) txt++;
2807 size_t len = strlen(txt);
2808 if(len > sz_model - 1) len = sz_model - 1;
2809 memcpy(
model, txt, len);
2826 dt_gui_menu_popup(GTK_MENU(
g->camera_menu), button, GDK_GRAVITY_SOUTH, GDK_GRAVITY_NORTH);
2836 if(text) (
void)sscanf(text,
"%f", &
p->focal);
2845 if(text) (
void)sscanf(text,
"%f", &
p->aperture);
2854 if(text) (
void)sscanf(text,
"%f", &
p->distance);
2862 gtk_widget_destroy(widget);
2878 default:
return _(
"unknown");
2894 char l_maker[128] =
"", l_model[256] =
"";
2896 || ls_db_lens_name(db, lens_id, l_maker,
sizeof(l_maker), l_model,
sizeof(l_model)) <= 0)
2899 g_strlcpy(
p->lens, l_model,
sizeof(
p->lens));
2915 gdouble focal_values[]
2916 = { -INFINITY, 4.5, 8, 10, 12, 14, 15, 16, 17, 18, 20, 24, 28, 30, 31, 35,
2917 38, 40, 43, 45, 50, 55, 60, 70, 75, 77, 80, 85, 90, 100, 105, 110,
2918 120, 135, 150, 200, 210, 240, 250, 300, 400, 500, 600, 800, 1000, INFINITY };
2919 gdouble aperture_values[]
2920 = { -INFINITY, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.4, 1.8, 2, 2.2, 2.5, 2.8, 3.2, 3.4, 4, 4.5, 5.0,
2921 5.6, 6.3, 7.1, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 29, 32, 38, INFINITY };
2925 char l_maker[128] =
"", l_model[256] =
"";
2926 float min_focal = 0.f, max_focal = 0.f, min_ap = 0.f, max_ap = 0.f;
2927 const gboolean have = (lens_id >= 0) && !
IS_NULL_PTR(db)
2928 && (ls_db_lens_by_id(db, lens_id, &lens_v) == 1)
2929 && (ls_db_lens_name(db, lens_id, l_maker,
sizeof(l_maker),
2930 l_model,
sizeof(l_model)) > 0);
2931 if(have) ls_db_lens_range(db, lens_id, &min_focal, &max_focal, &min_ap, &max_ap);
2950 maker = l_maker[0] ? l_maker : NULL;
2951 model = l_model[0] ? l_model : NULL;
2956 fm = g_strdup_printf(
"%s, %s",
maker,
model);
2958 fm = g_strdup_printf(
"%s",
model);
2959 gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
g->lens_model))), fm);
2963 char focal[100], aperture[100], mounts[200];
2965 if(min_focal < max_focal)
2966 snprintf(focal,
sizeof(focal),
"%g-%gmm", min_focal, max_focal);
2968 snprintf(focal,
sizeof(focal),
"%gmm", min_focal);
2970 snprintf(aperture,
sizeof(aperture),
"%g-%g", min_ap, max_ap);
2972 snprintf(aperture,
sizeof(aperture),
"%g", min_ap);
2975 ls_db_lens_mounts(db, lens_id, mounts,
sizeof(mounts));
2977 fm = g_strdup_printf(_(
"maker:\t\t%s\n"
2979 "focal range:\t%s\n"
2981 "crop factor:\t%.1f\n"
2987 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->lens_model), fm);
2991 gtk_container_foreach(GTK_CONTAINER(
g->lens_param_box),
delete_children, NULL);
2993 int ffi = 1, fli = -1;
2994 for(
i = 1;
i <
sizeof(focal_values) /
sizeof(gdouble) - 1;
i++)
2996 if(focal_values[
i] < min_focal) ffi =
i + 1;
2997 if(focal_values[
i] > max_focal && fli == -1) fli =
i;
2999 if(focal_values[ffi] > min_focal)
3001 focal_values[ffi - 1] = min_focal;
3004 if(max_focal == 0 || fli < 0) fli =
sizeof(focal_values) /
sizeof(gdouble) - 2;
3005 if(focal_values[fli + 1] < max_focal)
3007 focal_values[fli + 1] = max_focal;
3010 if(fli < ffi) fli = ffi + 1;
3018 gtk_widget_set_tooltip_text(w, _(
"focal length (mm)"));
3019 snprintf(txt,
sizeof(txt),
"%.*f",
precision(
p->focal, 10.0),
p->focal);
3021 for(
int k = 0;
k < fli - ffi;
k++)
3023 snprintf(txt,
sizeof(txt),
"%.*f",
precision(focal_values[ffi +
k], 10.0), focal_values[ffi +
k]);
3027 gtk_box_pack_start(GTK_BOX(
g->lens_param_box), w,
TRUE,
TRUE, 0);
3032 ffi = 1, fli =
sizeof(aperture_values) /
sizeof(gdouble) - 1;
3033 for(
i = 1;
i <
sizeof(aperture_values) /
sizeof(gdouble) - 1;
i++)
3034 if(aperture_values[
i] < min_ap) ffi =
i + 1;
3035 if(aperture_values[ffi] > min_ap)
3037 aperture_values[ffi - 1] = min_ap;
3043 gtk_widget_set_tooltip_text(w, _(
"f-number (aperture)"));
3044 snprintf(txt,
sizeof(txt),
"%.*f",
precision(
p->aperture, 10.0),
p->aperture);
3046 for(
int k = 0;
k < fli - ffi;
k++)
3048 snprintf(txt,
sizeof(txt),
"%.*f",
precision(aperture_values[ffi +
k], 10.0), aperture_values[ffi +
k]);
3052 gtk_box_pack_start(GTK_BOX(
g->lens_param_box), w,
TRUE,
TRUE, 0);
3058 gtk_widget_set_tooltip_text(w, _(
"distance to subject"));
3059 snprintf(txt,
sizeof(txt),
"%.*f",
precision(
p->distance, 10.0),
p->distance);
3062 for(
int k = 0;
k < 25;
k++)
3064 if(val > 1000.0f) val = 1000.0f;
3065 snprintf(txt,
sizeof(txt),
"%.*f",
precision(val, 10.0), val);
3067 if(val >= 1000.0f)
break;
3071 gtk_box_pack_start(GTK_BOX(
g->lens_param_box), w,
TRUE,
TRUE, 0);
3075 gtk_widget_show_all(
g->lens_param_box);
3091 const long long lens_id =
3092 (
long long)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem),
"lens-id"));
3115 GPtrArray *makers, *submenus;
3119 gtk_widget_destroy(GTK_WIDGET(
g->lens_menu));
3120 g->lens_menu = NULL;
3128 submenus = g_ptr_array_new();
3129 for(
int i = 0;
i <
n;
i++)
3142 submenu = gtk_menu_new();
3146 submenu = (
GtkWidget *)g_ptr_array_index(submenus, idx);
3148 item = gtk_menu_item_new_with_label(
model);
3149 gtk_widget_show(item);
3150 g_object_set_data(G_OBJECT(item),
"lens-id", GINT_TO_POINTER((gint)ids[
i]));
3151 g_signal_connect(G_OBJECT(item),
"activate", G_CALLBACK(
lens_menu_select), self);
3152 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item);
3155 g->lens_menu = GTK_MENU(gtk_menu_new());
3156 for(
unsigned i = 0;
i < makers->len;
i++)
3158 GtkWidget *item = gtk_menu_item_new_with_label((
const gchar *)g_ptr_array_index(makers,
i));
3159 gtk_widget_show(item);
3160 gtk_menu_shell_append(GTK_MENU_SHELL(
g->lens_menu), item);
3161 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), (
GtkWidget *)g_ptr_array_index(submenus,
i));
3164 g_ptr_array_free(submenus,
TRUE);
3165 g_ptr_array_free(makers,
TRUE);
3187 const gboolean have_cam = (
g->camera_id >= 0) && (ls_db_camera_by_id(db,
g->camera_id, &cam) == 1);
3191 enum { MAX_HITS = 32 };
3192 ls_db_match_t
m[MAX_HITS];
3193 const int n = ls_db_match_lens(db, NULL,
model, have_cam ? cam.mount_id : 0,
3194 have_cam ? cam.crop_factor : 0.f,
m, MAX_HITS);
3195 if(
n <= 0)
return NULL;
3196 long long *ids = (
long long *)
dt_alloc_align(
sizeof(
long long) * (size_t)
n);
3198 for(
int i = 0;
i <
n;
i++) ids[
i] =
m[
i].lens_id;
3205 const int total = ls_db_list_lenses(db, NULL, 0);
3206 if(total <= 0)
return NULL;
3207 long long *all = (
long long *)
dt_alloc_align(
sizeof(
long long) * (size_t)total);
3209 const int got = ls_db_list_lenses(db, all, total);
3218 for(
int i = 0;
i < got;
i++)
3219 if(ls_db_lens_fits_mount(db, all[
i], cam.mount_id) == 1) all[keep++] = all[
i];
3236 dt_gui_menu_popup(GTK_MENU(
g->lens_menu), button, GDK_GRAVITY_SOUTH, GDK_GRAVITY_NORTH);
3330 gtk_widget_set_visible(
g->reverse,
p->inverse != 0);
3377 for(
int i = 0;
i <
g->axis_rows[axis];
i++)
3378 if(
g->axis_row[axis][
i] == source)
return i;
3449 default: have =
FALSE;
break;
3455 g->axis_row[axis][
n++] = src;
3457 g->axis_rows[axis] =
n;
3481 if(
g->axis_source[axis] == w)
return axis;
3498 if(row < 0 || row >=
g->axis_rows[axis])
return;
3525 g->axis_source[axis] = w;
3527 gtk_widget_set_tooltip_text(w, _(
tooltip));
3531 g->axis_rows[axis] = 0;
3532 g_signal_connect(G_OBJECT(w),
"value-changed",
3565 memset(&
d, 0,
sizeof(
d));
3579 ls_modifier_t modifier;
3581 scale = ls_modifier_autoscale(&modifier);
3618 memset(&
d, 0,
sizeof(
d));
3647 g->camera_menu = NULL;
3648 g->lens_menu = NULL;
3652 gtk_widget_set_name(self->
gui->
widget,
"lens-module");
3695 N_(
"correct the lens's light falloff, and where to take it from"));
3699 N_(
"correct the lens's geometric distortion, and where to take it from"));
3704 gtk_widget_set_tooltip_text(
g->target_geom, _(
"target geometry"));
3723 g_signal_connect(G_OBJECT(
g->scale),
"quad-pressed", G_CALLBACK(
autoscale_pressed), self);
3724 gtk_widget_set_tooltip_text(
g->scale, _(
"auto scale"));
3728 N_(
"correct lateral chromatic aberration, and where to take it from"));
3738 gtk_widget_set_tooltip_text(
g->tca_r, _(
"Transversal Chromatic Aberration red"));
3742 gtk_widget_set_tooltip_text(
g->tca_b, _(
"Transversal Chromatic Aberration blue"));
3749 gtk_widget_set_tooltip_text(
g->reverse, _(
"correct distortions or apply them"));
3770 gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
g->camera_model))),
p->camera);
3771 gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
g->lens_model))),
p->lens);
3772 gtk_widget_set_tooltip_text(
g->camera_model,
"");
3773 gtk_widget_set_tooltip_text(
g->lens_model,
"");
3797 if(
g->camera_id >= 0 &&
p->lens[0])
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_combobox_clear(GtkWidget *widget)
void dt_bauhaus_combobox_set_editable(GtkWidget *widget, int editable)
int dt_bauhaus_combobox_get(GtkWidget *widget)
const char * dt_bauhaus_combobox_get_text(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
void dt_bauhaus_widget_set_quad_paint(GtkWidget *widget, dt_bauhaus_quad_paint_f f, int paint_flags, void *paint_data)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
return vector dt_simd_set1(valid ?(scaling+NORM_MIN) :NORM_MIN)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
dt_store_simd_aligned(out, dt_mat3x4_mul_vec4(vin, dt_colormatrix_row_to_simd(matrix, 0), dt_colormatrix_row_to_simd(matrix, 1), dt_colormatrix_row_to_simd(matrix, 2)))
gboolean dt_image_is_monochrome(const dt_image_t *img)
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
#define dt_dev_add_history_item(dev, module, enable, redraw)
gboolean dt_dev_module_geometry_gui(dt_develop_t *dev, dt_iop_module_t *module, dt_iop_roi_t *in, dt_iop_roi_t *out)
One module's own input and output rectangles at full resolution, from the geometry service.
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
GtkWidget * status
result of the last capture
void dt_loc_get_datadir(char *datadir, size_t bufsize)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
Where things are on the image, answered without a pipeline.
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
void dt_iop_compute_module_hash(dt_iop_module_t *module, GList *masks)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
@ IOP_FLAGS_TILING_FULL_ROI
GtkWidget * dt_iop_button_new(dt_iop_module_t *self, const gchar *label, GCallback callback, gboolean local, guint accel_key, GdkModifierType mods, DTGTKCairoPaintIconFunc paint, gint paintflags, GtkWidget *box)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
#define IOP_GUI_ALLOC(module)
const struct dt_interpolation * dt_interpolation_new(enum dt_interpolation_type type)
__DT_CLONE_TARGETS__ float dt_interpolation_compute_sample(const struct dt_interpolation *itor, const float *in, const float x, const float y, const int width, const int height, const int samplestride, const int linestride)
@ DT_INTERPOLATION_BICUBIC
@ DT_INTERPOLATION_BILINEAR
@ DT_INTERPOLATION_MITCHELL
@ DT_INTERPOLATION_USERPREF_WARP
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)
#define DT_LENS_MODIFY_ANSEL_MASK
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 const char *const _lens_source_names[DT_LENS_SOURCE_LAST]
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)
static long long * _camera_all_ids(int *out_n)
Every camera in the database, as ids the caller must free with dt_free_align().
const char ** description(struct dt_iop_module_t *self)
static void _lens_rebuild_axis_rows(dt_iop_module_t *self)
Every axis, for a fresh image.
static const char * _lens_type_name(int type)
A projection's name, replacing lfLens::GetLensTypeDesc().
static void _lens_fill_vignette_row(float *const buf, const int width, const int ch)
static int _lens_used_mask(dt_iop_module_t *self)
The lensfun modify mask this image allows: monochrome sensors get no TCA correction.
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 ptr_array_find_sorted(const GPtrArray *array, const void *item, GCompareFunc compare)
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 int _lens_mask_for_mono(const gboolean monochrome)
Which axes may be attempted on this image.
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 void _lens_free_data(void *ptr)
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 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 reload_defaults(dt_iop_module_t *module)
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.
dt_lens_modify_t
What modify_flags holds, bit by bit.
@ DT_LENS_MODIFY_GEOMETRY
@ DT_LENS_MODIFY_VIGNETTING
@ DT_LENS_SOURCE_SHIFT_VIGNETTING
@ DT_LENS_MODIFY_DISTORTION
@ DT_LENS_SOURCE_SHIFT_TCA
@ DT_LENS_SOURCE_SHIFT_DISTORTION
dt_lens_source_t
Where one axis takes its correction from. The same vocabulary for all three.
@ DT_LENS_SOURCE_EMBEDDED
static void lens_comboentry_distance_update(GtkWidget *widget, dt_iop_module_t *self)
static char * _lens_sanitize(const char *orig_lens)
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 const dt_lens_source_t _lens_axis_sources[DT_LENS_AXIS_LAST][DT_LENS_SOURCE_LAST]
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 gboolean _lens_flags_move_pixels(const int modify_flags)
Does this flag word describe anything that MOVES pixels?
static void autoscale_pressed(GtkWidget *button, gpointer user_data)
__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)
static ls_db_t * _ls_db(void)
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 void camera_menu_select(GtkMenuItem *menuitem, gpointer user_data)
static const dt_geometry_vtable_t _lens_geometry_vtable
static gboolean _ls_find_camera(const char *maker, const char *model, ls_camera_t *out)
The camera an EXIF maker/model names.
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 void lens_comboentry_focal_update(GtkWidget *widget, dt_iop_module_t *self)
static void camera_menusearch_clicked(GtkWidget *button, gpointer user_data)
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_comboentry_aperture_update(GtkWidget *widget, dt_iop_module_t *self)
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 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_axis_source_changed(GtkWidget *widget, gpointer user_data)
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?
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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.
dt_lens_axis_t
The correction axes, as an index rather than a bit – so a caller can loop.
@ DT_LENS_AXIS_DISTORTION
@ DT_LENS_AXIS_VIGNETTING
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)
static gboolean _lens_source_applicable(const dt_lens_axis_t axis, const dt_lens_source_t source)
Whether source means anything on axis.
static void ptr_array_insert_index(GPtrArray *array, const void *item, int index)
gboolean geometry_record(dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
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_tr...
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 precision(double x, double adj)
void gui_init(struct dt_iop_module_t *self)
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.
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
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 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.
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)
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 void _lens_gui_update_sensitivity(dt_iop_module_t *self)
void cleanup_global(dt_iop_module_so_t *module)
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)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static void lens_menu_fill(dt_iop_module_t *self, const long long *ids, int n)
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 void lens_menusearch_clicked(GtkWidget *button, gpointer user_data)
static float get_autoscale(dt_iop_module_t *self, dt_iop_lensfun_params_t *p)
static GPrivate _ls_tls_key
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)
void gui_cleanup(struct dt_iop_module_t *self)
@ DT_LENS_FISHEYE_EQUISOLID
@ DT_LENS_FISHEYE_ORTHOGRAPHIC
@ DT_LENS_FISHEYE_STEREOGRAPHIC
@ DT_LENS_EQUIRECTANGULAR
static int ptr_array_insert_sorted(GPtrArray *array, const void *item, GCompareFunc compare)
static void lens_menu_select(GtkMenuItem *menuitem, gpointer user_data)
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 gboolean _lens_data_available(const dt_iop_lensfun_data_t *d)
Does this pipe data hold ANY resolvable correction source?
static void target_geometry_changed(GtkWidget *widget, gpointer user_data)
static void parse_model(const char *txt, char *model, size_t sz_model)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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 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 camera_set(dt_iop_module_t *self, long long camera_id)
Show a camera in the panel. VIEW ONLY – writes no parameter.
static void delete_children(GtkWidget *widget, gpointer data)
static void _ls_tls_free(gpointer data)
void init_global(dt_iop_module_so_t *module)
#define DT_LENS_MODIFY_ALL_AXES
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 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.
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)
#define DT_LENS_MODIFY_DISTORTION_PACK
The three lensfun axes that always move together, as one flag.
static _ls_tls_t * _ls_tls_get(void)
This thread's cache block, allocated on first use. NULL only if that allocation failed,...
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)
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.
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 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.
_lib_location_type_t type
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
#define DT_ALIGNED_ARRAY
Align an object on a cacheline boundary, so AVX2 can load it whole.
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
int dt_opencl_create_kernel(const int prog, const char *name)
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
#define __OMP_PARALLEL_FOR__(...)
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
void dt_concat_path_file(char destination[4096], const char path[4096], const char *const file)
Append a constant filename to a variable, stack-based, fixed-sized, directory, and add a / in-between...
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_get_perthread(buf, padsize)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
#define DT_PIXEL_SIMD_CHANNELS
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
gboolean cache_output_on_ram
One module instance's contribution, as data.
const dt_geometry_vtable_t * vtable
void(* free_data)(void *data)
A module's geometry, evaluated. Pure functions of the record's own data.
float exif_focus_distance
ls_vendor_data_t exif_correction
enum dt_interpolation_type id
dt_iop_lensfun_data_t data
dt_lens_type_t target_geom
int kernel_lens_distort_bicubic
int kernel_lens_distort_bilinear
int kernel_lens_distort_mitchell
dt_lens_source_t axis_row[DT_LENS_AXIS_LAST][DT_LENS_SOURCE_LAST]
int axis_rows[DT_LENS_AXIS_LAST]
GtkWidget * axis_source[DT_LENS_AXIS_LAST]
GtkWidget * lens_param_box
dt_lens_type_t target_geom
dt_iop_global_data_t * data
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__