72#define exposure2white(x) exp2f(-(x))
125 const int new_version)
127 if(old_version == 1 && new_version == 2)
129 typedef struct dt_iop_basicadj_params_v1_t
141 } dt_iop_basicadj_params_v1_t;
143 const dt_iop_basicadj_params_v1_t *old = old_params;
147 new->exposure = old->exposure;
148 new->hlcompr = old->hlcompr;
149 new->hlcomprthresh = old->hlcomprthresh;
150 new->contrast = old->contrast;
151 new->preserve_colors = old->preserve_colors;
152 new->middle_grey = old->middle_grey;
153 new->brightness = old->brightness;
154 new->saturation = old->saturation;
155 new->clip = old->clip;
164 return _(
"this module is deprecated. please use the quick access panel instead.");
169 return _(
"basic adjustments");
176 _(
"linear, RGB, scene-referred"),
177 _(
"non-linear, RGB"),
178 _(
"non-linear, RGB, scene-referred"));
201 g->button_down =
g->draw_selected_region = 0;
202 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_select_region),
g->draw_selected_region);
231 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off), 1);
238 if(
g->call_auto_exposure == 0)
240 g->box_cood[0] =
g->box_cood[1] =
g->box_cood[2] =
g->box_cood[3] = 0.f;
241 g->call_auto_exposure = 1;
257 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->
gui->
off), 1);
264 if(gtk_toggle_button_get_active(togglebutton))
266 g->draw_selected_region = 1;
269 g->draw_selected_region = 0;
271 g->posx_from =
g->posx_to =
g->posy_from =
g->posy_to = 0;
286 if(
g->call_auto_exposure == 2)
288 g->call_auto_exposure = -1;
296 g->call_auto_exposure = 0;
323 const float def_middle_grey
324 = (work_profile) ? (dt_ioppr_get_profile_info_middle_grey(work_profile) * 100.f) : 18.42f;
348 float point[2] = { (float)
x, (
float)y };
369 if(fabsf(
g->posx_from -
g->posx_to) > 1 && fabsf(
g->posy_from -
g->posy_to) > 1)
371 g->box_cood[0] =
g->posx_from;
372 g->box_cood[1] =
g->posy_from;
373 g->box_cood[2] =
g->posx_to;
374 g->box_cood[3] =
g->posy_to;
378 g->call_auto_exposure = 1;
398 if((which == 3) || (which == 1 &&
type == GDK_2BUTTON_PRESS))
406 float point[2] = { (float)
x, (
float)y };
410 g->posx_from =
g->posx_to =
point[0];
411 g->posy_from =
g->posy_to =
point[1];
427 if(!
g->draw_selected_region || !
g->button_down)
return;
428 if(
g->posx_from ==
g->posx_to &&
g->posy_from ==
g->posy_to)
return;
435 const float posx_from = fmin(
g->posx_from,
g->posx_to);
436 const float posx_to = fmax(
g->posx_from,
g->posx_to);
437 const float posy_from = fmin(
g->posy_from,
g->posy_to);
438 const float posy_to = fmax(
g->posy_from,
g->posy_to);
441 cairo_set_line_width(cr, 1.0 / zoom_scale);
442 cairo_set_source_rgb(cr, .2, .2, .2);
449 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
451 cairo_rectangle(cr, posx_from, posy_from, (posx_to - posx_from), (posy_to - posy_from));
453 cairo_translate(cr, 1.0 / zoom_scale, 1.0 / zoom_scale);
454 cairo_set_source_rgb(cr, .8, .8, .8);
455 cairo_rectangle(cr, posx_from + 1.0 / zoom_scale, posy_from, (posx_to - posx_from) - 3. / zoom_scale,
456 (posy_to - posy_from) - 2. / zoom_scale);
471 p->middle_grey = (work_profile) ? (dt_ioppr_get_rgb_matrix_luminance(self->
picked_color,
474 work_profile->unbounded_coeffs_in,
486static inline float get_gamma(
const float x,
const float gamma)
488 return powf(
x, gamma);
493 return (
x > 1.f) ?
get_gamma(
x, gamma) :
lut[CLAMP((
int)(
x * 0x10000ul), 0, 0xffff)];
496static inline float get_contrast(
const float x,
const float contrast,
const float middle_grey,
497 const float inv_middle_grey)
499 return powf(
x * inv_middle_grey, contrast) * middle_grey;
502static inline float get_lut_contrast(
const float x,
const float contrast,
const float middle_grey,
503 const float inv_middle_grey,
const float *
const lut)
505 return (
x > 1.f) ?
get_contrast(
x, contrast, middle_grey, inv_middle_grey)
506 :
lut[CLAMP((
int)(
x * 0x10000ul), 0, 0xffff)];
531 const float brightness =
p->brightness * 2.f;
532 const float gamma = (brightness >= 0.0f) ? 1.0f / (1.0f + brightness) : (1.0f - brightness);
533 const float contrast =
p->contrast + 1.0f;
534 const float middle_grey = (
p->middle_grey > 0.f) ? (
p->middle_grey / 100.f) : 0.1842f;
535 const float inv_middle_grey = 1.f / middle_grey;
537 const int process_gamma = (
p->brightness != 0.f);
538 const int plain_contrast = (!
p->preserve_colors &&
p->contrast != 0.f);
541 if(process_gamma || plain_contrast)
543 for(
unsigned int i = 0;
i < 0x10000;
i++)
545 const float percentage = (float)
i / (
float)0x10000ul;
546 if(process_gamma)
d->lut_gamma[
i] =
get_gamma(percentage, gamma);
547 if(plain_contrast)
d->lut_contrast[
i] =
get_contrast(percentage, contrast, middle_grey, inv_middle_grey);
568 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->bt_select_region),
g->draw_selected_region);
580 g->call_auto_exposure = 0;
581 g->draw_selected_region = 0;
582 g->posx_from =
g->posx_to =
g->posy_from =
g->posy_to = 0.f;
583 g->box_cood[0] =
g->box_cood[1] =
g->box_cood[2] =
g->box_cood[3] = 0.f;
598 gtk_widget_set_tooltip_text(
g->sl_black_point, _(
"adjust the black level to unclip negative RGB values.\n"
599 "you should never use it to add more density in blacks!\n"
600 "if poorly set, it will clip near-black colors out of gamut\n"
601 "by pushing RGB values into negatives"));
606 gtk_widget_set_tooltip_text(
g->sl_exposure, _(
"adjust the exposure correction"));
610 gtk_widget_set_tooltip_text(
g->sl_hlcompr, _(
"highlight compression adjustment"));
614 gtk_widget_set_tooltip_text(
g->sl_contrast, _(
"contrast adjustment"));
617 gtk_widget_set_tooltip_text(
g->cmb_preserve_colors, _(
"method to preserve colors when applying contrast"));
622 gtk_widget_set_tooltip_text(
g->sl_middle_grey, _(
"middle gray adjustment"));
627 gtk_widget_set_tooltip_text(
g->sl_brightness,_(
"brightness adjustment"));
630 gtk_widget_set_tooltip_text(
g->sl_saturation,_(
"saturation adjustment"));
633 gtk_widget_set_tooltip_text(
g->sl_vibrance, _(
"vibrance adjustment"));
639 gtk_box_pack_start(GTK_BOX(autolevels_box),
g->bt_auto_levels,
TRUE,
TRUE, 0);
643 gtk_widget_set_tooltip_text(
g->bt_select_region,
644 _(
"apply auto exposure based on a region defined by the user\n"
645 "click and drag to draw the area\n"
646 "right click to cancel"));
648 gtk_box_pack_start(GTK_BOX(autolevels_box),
g->bt_select_region,
TRUE,
TRUE, 0);
654 gtk_widget_set_tooltip_text(
g->sl_clip, _(
"adjusts clipping value for auto exposure calculation"));
694 const int m =
d < 4.9090934652977266E-91;
695 d =
m ? 2.037035976334486E90 *
d :
d;
697 q =
m ? q - (300 + 0x03fe) : q - 0x03fe;
702static inline double ldexpk(
double x, int32_t q)
704 int32_t
m = q < 0 ? -1 : 0;
705 m = (((
m + q) >> 9) -
m) << 7;
720 double x = (
m - 1) / (
m + 1);
721 const double x2 =
x *
x;
723 double t = 0.148197055177935105296783;
724 t = fma(
t, x2, 0.153108178020442575739679);
725 t = fma(
t, x2, 0.181837339521549679055568);
726 t = fma(
t, x2, 0.22222194152736701733275);
727 t = fma(
t, x2, 0.285714288030134544449368);
728 t = fma(
t, x2, 0.399999999989941956712869);
729 t = fma(
t, x2, 0.666666666666685503450651);
732 x =
x *
t + 0.693147180559945286226764 * e;
734 if(!isfinite(
d))
x = INFINITY;
736 if(
d == 0)
x = -INFINITY;
743 const double sRGBGammaCurve = 2.4;
744 return (
x <= 0.00304) ? (
x * 12.92) : (1.055 * exp(
log(
x) / sRGBGammaCurve) - 0.055);
749 const double sRGBGammaCurve = 2.4;
750 return (
x <= 0.03928) ? (
x / 12.92) : (exp(
log((
x + 0.055) / 1.055) * sRGBGammaCurve));
755 uint32_t **_histogram,
unsigned int *_hist_size,
int *_histcompr)
759 const int histcompr = 3;
760 const unsigned int hist_size = 65536 >> histcompr;
761 uint32_t *histogram = NULL;
762 const float mul = hist_size;
765 sizeof(uint32_t) * hist_size,
773 memset(histogram, 0,
sizeof(uint32_t) * hist_size);
775 if(box_area[2] > box_area[0] && box_area[3] > box_area[1])
777 for(
int y = box_area[1]; y <= box_area[3]; y++)
779 const float *
const in = img + (size_t)
ch *
width * y;
780 for(
int x = box_area[0];
x <= box_area[2];
x++)
782 const float *
const pixel = in +
x *
ch;
784 for(
int c = 0; c < 3; c++)
790 else if(pixel[c] >= 1.f)
792 histogram[hist_size - 1]++;
796 const uint32_t
R = (uint32_t)(pixel[c] * mul);
807 const float *
const pixel = img +
i;
809 for(
int c = 0; c < 3; c++)
815 else if(pixel[c] >= 1.f)
817 histogram[hist_size - 1]++;
821 const uint32_t
R = (uint32_t)(pixel[c] * mul);
829 *_histogram = histogram;
830 *_hist_size = hist_size;
831 *_histcompr = histcompr;
836static void _get_sum_and_average(
const uint32_t *
const histogram,
const int hist_size,
float *_sum,
float *_avg)
841 for(
int i = 0;
i < hist_size;
i++)
843 float val = histogram[
i];
854static inline float hlcurve(
const float level,
const float hlcomp,
const float hlrange)
858 float val = level + (hlrange - 1.f);
866 float Y = val / hlrange;
875 float R = hlrange / (val * hlcomp);
876 return log1pf(Y) *
R;
885static void _get_auto_exp(
const uint32_t *
const histogram,
const unsigned int hist_size,
const int histcompr,
886 const float defgain,
const float clip,
const float midgray,
float *_expcomp,
887 float *_bright,
float *_contr,
float *_black,
float *_hlcompr,
float *_hlcomprthresh)
894 float hlcomprthresh = 0.f;
896 float scale = 65536.0f;
898 const int imax = 65536 >> histcompr;
900 float sum = 0.f, hisum = 0.f, losum = 0.f;
907 int median = 0, count = histogram[0];
909 while(count < sum / 2)
912 count += histogram[
median];
915 if(
median == 0 || ave < 1.f)
928 float octile[8] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }, ospread = 0.f;
933 for(;
i <
MIN((
int)ave, imax);
i++)
937 octile[count] += histogram[
i];
939 if(octile[count] > sum / 8.f || (count == 7 && octile[count] > sum / 16.f))
941 octile[count] =
xlog(1. + (
float)
i) /
log(2.f);
946 losum += histogram[
i];
953 octile[count] += histogram[
i];
955 if(octile[count] > sum / 8.f || (count == 7 && octile[count] > sum / 16.f))
957 octile[count] =
xlog(1.f + (
float)
i) /
log(2.f);
962 hisum += histogram[
i];
966 if(losum == 0.f || hisum == 0.f)
978 if(octile[6] > log1pf((
float)imax) / log2(2.f))
980 octile[6] = 1.5f * octile[5] - 0.5f * octile[4];
985 if(octile[7] > log1pf((
float)imax) / log2(2.f))
987 octile[7] = 1.5f * octile[6] - 0.5f * octile[5];
998 for(
int ii = 1; ii < 8; ii++)
1000 if(octile[ii] == 0.0f)
1002 octile[ii] = octile[ii - 1];
1008 for(
int ii = 1; ii < 6; ii++)
1010 ospread += (octile[ii + 1] - octile[ii])
1011 /
MAX(0.5f, (ii > 2 ? (octile[ii + 1] - octile[3]) : (octile[3] - octile[ii])));
1024 hlcomprthresh = 0.f;
1029 unsigned int clipped = 0;
1030 int rawmax = (imax)-1;
1032 while(histogram[rawmax] + clipped <= 0 && rawmax > 1)
1034 clipped += histogram[rawmax];
1039 unsigned int clippable = (int)(sum * clip);
1041 int whiteclip = (imax)-1;
1043 while(whiteclip > 1 && (histogram[whiteclip] + clipped) <= clippable)
1045 clipped += histogram[whiteclip];
1053 while(shc < whiteclip - 1 && histogram[shc] + clipped <= clippable)
1055 clipped += histogram[shc];
1060 rawmax <<= histcompr;
1061 whiteclip <<= histcompr;
1062 ave = ave * (1 << histcompr);
1069 const float expcomp1 = (logf(midgray * scale / (ave - shc + midgray * shc))) /
DT_M_LN2f;
1074 expcomp2 = 0.5f * ((15.5f - histcompr - (2.f * oct7 - oct6)) + logf(scale / rawmax) /
DT_M_LN2f);
1078 expcomp2 = 0.5f * ((15.5f - histcompr - (2.f * octile[7] - octile[6])) + logf(scale / rawmax) /
DT_M_LN2f);
1081 if(fabsf(expcomp1) - fabsf(expcomp2) > 1.f)
1083 expcomp = (expcomp1 * fabsf(expcomp2) + expcomp2 * fabsf(expcomp1)) / (fabsf(expcomp1) + fabsf(expcomp2));
1087 expcomp = 0.5 * (
double)expcomp1 + 0.5 * (
double)expcomp2;
1090 const float gain = expf(expcomp *
DT_M_LN2f);
1092 const float corr = sqrtf(gain * scale / rawmax);
1096 hlcomprthresh = 0.f;
1099 const float comp = (gain * ((float)whiteclip) / scale - 1.f) * 2.3f;
1100 hlcompr = (comp / (fmaxf(0.0f, expcomp) + 1.0f));
1101 hlcompr = fmaxf(0.f, fminf(100.f, hlcompr));
1105 const float midtmp = gain * sqrtf(
median * ave) / scale;
1109 bright = (midgray - midtmp) * 15.0f / (midtmp);
1113 bright = (midgray - midtmp) * 15.0f / (0.10833 - 0.0833f * midtmp);
1116 bright = 0.25f *
MAX(0.f, bright);
1119 contr = (midgray * 100.f) * (1.1f - ospread);
1120 contr =
MAX(0.f,
MIN(100.f, contr));
1122 double whiteclipg =
gamma2(whiteclip * corr);
1127 const float increment = corr * (1 << histcompr);
1129 for(
int ii = 0; ii<65536>> histcompr; ii++)
1132 gavg += histogram[ii] *
gamma2(val);
1140 const int maxwhiteclip = (gavg - black) * 4 / 3
1143 if(whiteclipg < maxwhiteclip)
1145 whiteclipg = maxwhiteclip;
1153 black = (black / whiteclipg);
1155 expcomp = CLAMP(expcomp, -5.0f, 12.0f);
1157 bright =
MAX(-100.f,
MIN(bright, 100.f));
1167 fprintf(stderr,
"[_get_auto_exp] expcomp is NaN!!!\n");
1172 fprintf(stderr,
"[_get_auto_exp] black is NaN!!!\n");
1177 fprintf(stderr,
"[_get_auto_exp] bright is NaN!!!\n");
1182 fprintf(stderr,
"[_get_auto_exp] contr is NaN!!!\n");
1187 fprintf(stderr,
"[_get_auto_exp] hlcompr is NaN!!!\n");
1189 if(isnan(hlcomprthresh))
1191 hlcomprthresh = 0.f;
1192 fprintf(stderr,
"[_get_auto_exp] hlcomprthresh is NaN!!!\n");
1195 *_expcomp = expcomp;
1199 *_hlcompr = hlcompr;
1200 *_hlcomprthresh = hlcomprthresh;
1203static inline __attribute__((always_inline))
int _auto_exposure(
const float *
const img,
const int width,
const int height,
int *box_area,
1204 const float clip,
const float midgray,
float *_expcomp,
float *_bright,
float *_contr,
1205 float *_black,
float *_hlcompr,
float *_hlcomprthresh)
1207 uint32_t *histogram = NULL;
1208 unsigned int hist_size = 0;
1211 const float defGain = 0.0f;
1218 _get_auto_exp(histogram, hist_size, histcompr, defGain, clip, midgray, _expcomp, _bright, _contr, _black,
1219 _hlcompr, _hlcomprthresh);
1230 box_out[0] = box_out[1] = box_out[2] = box_out[3] = 0;
1236 dt_boundingbox_t box_cood = {
g->box_cood[0],
g->box_cood[1],
g->box_cood[2],
g->box_cood[3] };
1238 box_cood[0] *= pipe->
iwidth;
1240 box_cood[2] *= pipe->
iwidth;
1246 box_cood[0] *= roi_in->
scale;
1247 box_cood[1] *= roi_in->
scale;
1248 box_cood[2] *= roi_in->
scale;
1249 box_cood[3] *= roi_in->
scale;
1251 box_cood[0] -= roi_in->
x;
1252 box_cood[1] -= roi_in->
y;
1253 box_cood[2] -= roi_in->
x;
1254 box_cood[3] -= roi_in->
y;
1259 box[0] = fminf(box_cood[0], box_cood[2]);
1260 box[1] = fminf(box_cood[1], box_cood[3]);
1261 box[2] = fmaxf(box_cood[0], box_cood[2]);
1262 box[3] = fmaxf(box_cood[1], box_cood[3]);
1265 if(!(box[0] >=
width || box[1] >=
height || box[2] < 0 || box[3] < 0))
1272 if(!(box[2] - box[0] < 1 || box[3] - box[1] < 1))
1274 box_out[0] = box[0];
1275 box_out[1] = box[1];
1276 box_out[2] = box[2];
1277 box_out[3] = box[3];
1302 g->call_auto_exposure = -1;
1309 if(_auto_exposure((
const float *
const)ivoid, roi_in->
width, roi_in->
height, box,
g->params.clip,
1310 g->params.middle_grey / 100.f, &
g->params.exposure, &
g->params.brightness,
1311 &
g->params.contrast, &
g->params.black_point, &
g->params.hlcompr, &
g->params.hlcomprthresh))
1317 g->call_auto_exposure = 2;
1326 const float black_point =
p->black_point;
1327 const float hlcompr =
p->hlcompr;
1328 const float hlcomprthresh =
p->hlcomprthresh;
1329 const float saturation =
p->saturation + 1.0f;
1330 const float vibrance =
p->vibrance / 1.4f;
1331 const float contrast =
p->contrast + 1.0f;
1333 const float scale = 1.0f / (white -
p->black_point);
1334 const float middle_grey = (
p->middle_grey > 0.f) ? (
p->middle_grey / 100.f) : 0.1842f;
1335 const float inv_middle_grey = 1.f / middle_grey;
1336 const float brightness =
p->brightness * 2.f;
1337 const float gamma = (brightness >= 0.0f) ? 1.0f / (1.0f + brightness) : (1.0f - brightness);
1339 const float hlcomp = hlcompr / 100.0f;
1340 const float shoulder = ((hlcomprthresh / 100.f) / 8.0f) + 0.1f;
1341 const float hlrange = 1.0f - shoulder;
1343 const int plain_contrast = (!
p->preserve_colors &&
p->contrast != 0.f);
1344 const int preserve_colors = (
p->contrast != 0.f) ?
p->preserve_colors : 0;
1345 const int process_gamma = (
p->brightness != 0.f);
1346 const int process_saturation_vibrance = (
p->saturation != 0.f)||(
p->vibrance != 0.f);
1347 const int process_hlcompr = (
p->hlcompr > 0.f);
1349 const float *
const in = (
const float *
const)ivoid;
1350 float *
const out = (
float *
const)
ovoid;
1351 const size_t stride = (size_t)roi_out->
height * roi_out->
width *
ch;
1353 for(
size_t k = 0;
k < stride;
k +=
ch)
1355 for(
size_t c = 0; c < 3; c++)
1358 out[
k + c] = (in[
k + c] - black_point) * scale;
1364 const float lum = (work_profile) ? dt_ioppr_get_rgb_matrix_luminance(
out +
k,
1367 work_profile->unbounded_coeffs_in,
1373 const float ratio =
hlcurve(lum, hlcomp, hlrange);
1375 for(
size_t c = 0; c < 3; c++)
1382 for(
size_t c = 0; c < 3; c++)
1388 if(plain_contrast &&
out[
k + c] > 0.f)
1396 const float lum =
dt_rgb_norm(
out +
k, preserve_colors, work_profile);
1399 const float contrast_lum = powf(lum * inv_middle_grey, contrast) * middle_grey;
1400 ratio = contrast_lum / lum;
1403 for(
size_t c = 0; c < 3; c++)
1410 if(process_saturation_vibrance)
1412 const float average = (
out[
k] +
out[
k+1] +
out[
k+2]) / 3;
1414 const float P = vibrance * (1 - powf(
delta, fabsf(vibrance)));
1416 for(
size_t c = 0; c < 3; c++)
1418 out[
k + c] = average + (saturation +
P) * (
out[
k+c] - average);
1422 out[
k + 3] = in[
k + 3];
1427#undef exposure2white
void cleanup(dt_imageio_module_format_t *self)
static float get_lut_gamma(const float x, const float gamma, const float *const lut)
const char ** description(struct dt_iop_module_t *self)
__DT_CLONE_TARGETS__ int process(struct 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 __DT_CLONE_TARGETS__ void _get_sum_and_average(const uint32_t *const histogram, const int hist_size, float *_sum, float *_avg)
static __DT_CLONE_TARGETS__ void _get_auto_exp(const uint32_t *const histogram, const unsigned int hist_size, const int histcompr, const float defgain, const float clip, const float midgray, float *_expcomp, float *_bright, float *_contr, float *_black, float *_hlcompr, float *_hlcomprthresh)
static void _auto_levels_callback(GtkButton *button, dt_iop_module_t *self)
static double longBitsToDouble(int64_t i)
static float get_gamma(const float x, const float gamma)
static int ilogbp1(double d)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
#define exposure2white(x)
void gui_focus(struct dt_iop_module_t *self, gboolean in)
static float get_contrast(const float x, const float contrast, const float middle_grey, const float inv_middle_grey)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _signal_profile_user_changed(gpointer instance, uint8_t profile_type, gpointer user_data)
static double xlog(double d)
void gui_update(struct dt_iop_module_t *self)
static float get_lut_contrast(const float x, const float contrast, const float middle_grey, const float inv_middle_grey, const float *const lut)
void change_image(struct dt_iop_module_t *self)
static void _select_region_toggled_callback(GtkToggleButton *togglebutton, dt_iop_module_t *self)
void gui_init(struct dt_iop_module_t *self)
int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
static __DT_CLONE_TARGETS__ int _get_auto_exp_histogram(const float *const img, const int width, const int height, int *box_area, uint32_t **_histogram, unsigned int *_hist_size, int *_histcompr)
static double igamma2(double x)
int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
static void _turn_selregion_picker_off(struct dt_iop_module_t *self)
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 __DT_CLONE_TARGETS__ void _get_selected_area(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_iop_basicadj_gui_data_t *g, const dt_iop_roi_t *const roi_in, int *box_out)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static int64_t doubleToRawLongBits(double d)
static double gamma2(double x)
void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
static void _turn_select_region_off(struct dt_iop_module_t *self)
void gui_cleanup(struct dt_iop_module_t *self)
static void _develop_ui_pipe_finished_callback(gpointer instance, gpointer user_data)
static void _color_picker_callback(GtkWidget *button, dt_iop_module_t *self)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
const char * deprecated_msg()
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
static double ldexpk(double x, int32_t q)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, 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 float hlcurve(const float level, const float hlcomp, const float hlrange)
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
void dt_bauhaus_slider_set_soft_max(GtkWidget *widget, float val)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static float dt_camera_rgb_luminance(const float4 rgb)
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
static float dt_rgb_norm(const float4 in, const int norm, const int work_profile, constant dt_colorspaces_iccprofile_info_cl_t *profile_info, read_only image2d_t lut)
#define dt_dev_add_history_item(dev, module, enable, redraw)
#define dt_dev_pixelpipe_update_history_all(dev)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_current_profile_info(dt_iop_module_t *module, const struct dt_dev_pixelpipe_t *pipe)
__DT_CLONE_TARGETS__ dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
int dt_dev_distort_transform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor in GUI logical coordinates.
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
gboolean dt_dev_rescale_roi(dt_develop_t *dev, cairo_t *cr, int32_t width, int32_t height)
Scale the ROI to fit within given width/height, centered.
gboolean dt_dev_pixelpipe_has_preview_output(const dt_develop_t *dev, const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *roi)
void dt_dev_coordinates_widget_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Coordinate conversion helpers between widget, normalized image, and absolute image spaces.
void dt_dev_coordinates_image_abs_to_raw_norm(dt_develop_t *dev, float *points, size_t num_points)
@ DT_DEV_TRANSFORM_DIR_BACK_INCL
float dt_boundingbox_t[4]
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)
void dt_iop_gui_leave_critical_section(dt_iop_module_t *const module)
Release what dt_iop_gui_enter_critical_section() took. Also a no-op headless.
void dt_iop_request_focus(dt_iop_module_t *module)
Move darkroom focus to module, or clear it with NULL.
@ IOP_FLAGS_SUPPORTS_BLENDING
void dt_iop_gui_enter_critical_section(dt_iop_module_t *const module)
Take the module's GUI lock, serialising access to its dt_iop_gui_data_t.
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)
GtkWidget * dt_action_button_new(dt_lib_module_t *self, const gchar *label, gpointer callback, gpointer data, const gchar *tooltip, guint accel_key, GdkModifierType mods)
_lib_location_type_t type
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_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
#define __OMP_PARALLEL_FOR__(...)
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define dt_pixelpipe_cache_free_align(mem)
@ DT_COLORSPACES_PROFILE_TYPE_WORK
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_CONTROL_PROFILE_USER_CHANGED
This signal is raised when a profile is changed by the user 1 uint32_t : the profile type that has ch...
@ DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED
This signal is raised when develop preview pipe process is finished no param, no returned value.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
const float uint32_t state[4]
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
float lut_contrast[0x10000]
dt_iop_basicadj_params_t params
GtkWidget * cmb_preserve_colors
GtkWidget * sl_saturation
GtkWidget * sl_black_point
GtkWidget * sl_brightness
GtkWidget * bt_auto_levels
dt_boundingbox_t box_cood
GtkWidget * sl_middle_grey
dt_iop_basicadj_params_t params
GtkWidget * bt_select_region
dt_iop_rgb_norms_t preserve_colors
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_aligned_pixel_t picked_color
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
int nonlinearlut
Non-zero when the profile has tone curves at all; tested as a boolean everywhere, but it is really th...
int lutsize
Entry count of each of the six LUTs. Always 65536 in practice: both callers of dt_ioppr_init_profile_...
float * lut_in[3]
Per-channel encoded -> linear tone curve, lutsize entries each, sampled over [0,1]....
dt_colormatrix_t matrix_in
RGB -> XYZ (D50), row-major. matrix_in[1][*] is the luminance row. NaN in [0][0] marks the whole prof...
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__
typedef double((*spd)(unsigned long int wavelength, double TempK))