104#define DT_GUI_CURVE_EDITOR_INSET DT_PIXEL_APPLY_DPI(1)
105#define DT_GUI_CURVE_INFL .3f
107#define DT_IOP_TONECURVE_RES 256
108#define DT_IOP_TONECURVE_MAXNODES 20
249 return _(
"tone curve");
270 _(
"corrective and creative"),
271 _(
"linear or non-linear, Lab, display-referred"),
272 _(
"non-linear, Lab"),
273 _(
"non-linear, Lab, display-referred"));
277 void *new_params,
const int new_version)
279 if(old_version == 1 && new_version == 5)
287 { { 0.0, 0.0 }, { 0.5, 0.5 }, { 1.0, 1.0 } },
288 { { 0.0, 0.0 }, { 0.5, 0.5 }, { 1.0, 1.0 } } },
296 n->tonecurve_nodes[
ch_L] = 6;
298 n->tonecurve_autoscale_ab = 1;
300 n->tonecurve_unbound_ab = 0;
301 n->preserve_colors = 0;
304 else if(old_version == 2 && new_version == 5)
309 else if(old_version == 3 && new_version == 5)
314 memcpy(
n->tonecurve, o->
tonecurve,
sizeof(
n->tonecurve));
319 n->tonecurve_unbound_ab = 0;
320 n->preserve_colors = 0;
323 else if(old_version == 4 && new_version == 5)
329 n->preserve_colors = 0;
344 const float xm_L = 1.0f /
d->unbounded_coeffs_L[0];
345 const float xm_ar = 1.0f /
d->unbounded_coeffs_ab[0];
346 const float xm_al = 1.0f - 1.0f /
d->unbounded_coeffs_ab[3];
347 const float xm_br = 1.0f /
d->unbounded_coeffs_ab[6];
348 const float xm_bl = 1.0f - 1.0f /
d->unbounded_coeffs_ab[9];
349 const float low_approximation =
d->table[0][(int)(0.01f * 0x10000ul)];
351 const size_t npixels = (size_t)roi_out->
width * roi_out->
height;
352 const int autoscale_ab =
d->autoscale_ab;
353 const int unbound_ab =
d->unbound_ab;
355 const float *
const restrict in = (
float*)
i;
356 float *
const restrict
out = (
float*)o;
358 for(
int k = 0;
k < 4*npixels;
k += 4)
360 const float L_in = in[
k] / 100.0f;
362 out[
k+0] = (L_in < xm_L) ?
d->table[
ch_L][CLAMP((
int)(L_in * 0x10000ul), 0, 0xffff)]
367 const float a_in = (in[
k+1] + 128.0f) / 256.0f;
368 const float b_in = (in[
k+2] + 128.0f) / 256.0f;
373 out[
k+1] =
d->table[
ch_a][CLAMP((
int)(a_in * 0x10000ul), 0, 0xffff)];
374 out[
k+2] =
d->table[
ch_b][CLAMP((
int)(b_in * 0x10000ul), 0, 0xffff)];
380 out[
k+1] = (a_in > xm_ar)
382 : ((a_in < xm_al) ?
dt_iop_eval_exp(
d->unbounded_coeffs_ab + 3, 1.0f - a_in)
383 :
d->table[
ch_a][CLAMP((
int)(a_in * 0x10000ul), 0, 0xffff)]);
384 out[
k+2] = (b_in > xm_br)
386 : ((b_in < xm_bl) ?
dt_iop_eval_exp(
d->unbounded_coeffs_ab + 9, 1.0f - b_in)
387 :
d->table[
ch_b][CLAMP((
int)(b_in * 0x10000ul), 0, 0xffff)]);
400 out[
k+1] = in[
k+1] * low_approximation;
401 out[
k+2] = in[
k+2] * low_approximation;
409 XYZ[c] = (
XYZ[c] < xm_L) ?
d->table[
ch_L][CLAMP((
int)(
XYZ[c] * 0x10000ul), 0, 0xffff)]
416 dt_Lab_to_prophotorgb(in +
k,
rgb);
419 for(
int c = 0; c < 3; c++)
421 rgb[c] = (
rgb[c] < xm_L) ?
d->table[
ch_L][CLAMP((
int)(
rgb[c] * 0x10000ul), 0, 0xffff)]
431 const float curve_lum = (lum < xm_L)
432 ?
d->table[
ch_L][CLAMP((
int)(lum * 0x10000ul), 0, 0xffff)]
434 ratio = curve_lum / lum;
436 for(
size_t c = 0; c < 3; c++)
438 rgb[c] = (ratio *
rgb[c]);
441 dt_prophotorgb_to_Lab(
rgb,
out +
k);
463 {
"Nikon D750",
"NIKON CORPORATION",
"NIKON D750", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.083508, 0.073677}, {0.212191, 0.274799}, {0.397095, 0.594035}, {0.495025, 0.714660}, {0.683565, 0.878550}, {0.854059, 0.950927}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.125000, 0.125000}, {0.250000, 0.250000}, {0.375000, 0.375000}, {0.500000, 0.500000}, {0.625000, 0.625000}, {0.750000, 0.750000}, {0.875000, 0.875000}}, {{0.000000, 0.000000}, {0.125000, 0.125000}, {0.250000, 0.250000}, {0.375000, 0.375000}, {0.500000, 0.500000}, {0.625000, 0.625000}, {0.750000, 0.750000}, {0.875000, 0.875000} }}, {8, 8, 8}, {2, 2, 2}, 1, 0, 0}},
465 {
"NIKON D5100",
"NIKON CORPORATION",
"NIKON D5100", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.000957, 0.000176}, {0.002423, 0.000798}, {0.005893, 0.003685}, {0.013219, 0.006619}, {0.023372, 0.011954}, {0.037580, 0.017817}, {0.069695, 0.035353}, {0.077276, 0.040315}, {0.123707, 0.082707}, {0.145249, 0.112105}, {0.189168, 0.186135}, {0.219576, 0.243677}, {0.290201, 0.385251}, {0.428150, 0.613355}, {0.506199, 0.700256}, {0.622833, 0.805488}, {0.702763, 0.870959}, {0.935053, 0.990139}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.050000, 0.050000}, {0.100000, 0.100000}, {0.150000, 0.150000}, {0.200000, 0.200000}, {0.250000, 0.250000}, {0.300000, 0.300000}, {0.350000, 0.350000}, {0.400000, 0.400000}, {0.450000, 0.450000}, {0.500000, 0.500000}, {0.550000, 0.550000}, {0.600000, 0.600000}, {0.650000, 0.650000}, {0.700000, 0.700000}, {0.750000, 0.750000}, {0.800000, 0.800000}, {0.850000, 0.850000}, {0.900000, 0.900000}, {0.950000, 0.950000}}, {{0.000000, 0.000000}, {0.050000, 0.050000}, {0.100000, 0.100000}, {0.150000, 0.150000}, {0.200000, 0.200000}, {0.250000, 0.250000}, {0.300000, 0.300000}, {0.350000, 0.350000}, {0.400000, 0.400000}, {0.450000, 0.450000}, {0.500000, 0.500000}, {0.550000, 0.550000}, {0.600000, 0.600000}, {0.650000, 0.650000}, {0.700000, 0.700000}, {0.750000, 0.750000}, {0.800000, 0.800000}, {0.850000, 0.850000}, {0.900000, 0.900000}, {0.950000, 0.950000}}}, {20, 20, 20}, {2, 2, 2}, 1, 0, 0}},
467 {
"Nikon D7000",
"NIKON CORPORATION",
"NIKON D7000", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.110633, 0.111192}, {0.209771, 0.286963}, {0.355888, 0.561236}, {0.454987, 0.673098}, {0.769212, 0.920485}, {0.800468, 0.933428}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.125000, 0.125000}, {0.250000, 0.250000}, {0.375000, 0.375000}, {0.500000, 0.500000}, {0.625000, 0.625000}, {0.750000, 0.750000}, {0.875000, 0.875000}}, {{0.000000, 0.000000}, {0.125000, 0.125000}, {0.250000, 0.250000}, {0.375000, 0.375000}, {0.500000, 0.500000}, {0.625000, 0.625000}, {0.750000, 0.750000}, {0.875000, 0.875000}}}, {8, 8, 8}, {2, 2, 2}, 1, 0, 0}},
469 {
"Nikon D7200",
"NIKON CORPORATION",
"NIKON D7200", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.000618, 0.003286}, {0.001639, 0.003705}, {0.005227, 0.005101}, {0.013299, 0.011192}, {0.016048, 0.013130}, {0.037941, 0.027014}, {0.058195, 0.041339}, {0.086531, 0.069088}, {0.116679, 0.107283}, {0.155629, 0.159422}, {0.205477, 0.246265}, {0.225923, 0.287343}, {0.348056, 0.509104}, {0.360629, 0.534732}, {0.507562, 0.762089}, {0.606899, 0.865692}, {0.734828, 0.947468}, {0.895488, 0.992021}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.050000, 0.050000}, {0.100000, 0.100000}, {0.150000, 0.150000}, {0.200000, 0.200000}, {0.250000, 0.250000}, {0.300000, 0.300000}, {0.350000, 0.350000}, {0.400000, 0.400000}, {0.450000, 0.450000}, {0.500000, 0.500000}, {0.550000, 0.550000}, {0.600000, 0.600000}, {0.650000, 0.650000}, {0.700000, 0.700000}, {0.750000, 0.750000}, {0.800000, 0.800000}, {0.850000, 0.850000}, {0.900000, 0.900000}, {0.950000, 0.950000}}, {{0.000000, 0.000000}, {0.050000, 0.050000}, {0.100000, 0.100000}, {0.150000, 0.150000}, {0.200000, 0.200000}, {0.250000, 0.250000}, {0.300000, 0.300000}, {0.350000, 0.350000}, {0.400000, 0.400000}, {0.450000, 0.450000}, {0.500000, 0.500000}, {0.550000, 0.550000}, {0.600000, 0.600000}, {0.650000, 0.650000}, {0.700000, 0.700000}, {0.750000, 0.750000}, {0.800000, 0.800000}, {0.850000, 0.850000}, {0.900000, 0.900000}, {0.950000, 0.950000}}}, {20, 20, 20}, {2, 2, 2}, 1, 0, 0}},
471 {
"NIKON D7500",
"NIKON CORPORATION",
"NIKON D7500", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.000421, 0.003412}, {0.003775, 0.004001}, {0.013762, 0.008704}, {0.016698, 0.010230}, {0.034965, 0.018732}, {0.087311, 0.049808}, {0.101389, 0.060789}, {0.166845, 0.145269}, {0.230944, 0.271288}, {0.333399, 0.502609}, {0.353207, 0.542549}, {0.550014, 0.819535}, {0.731749, 0.944033}, {0.783283, 0.960546}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.062500, 0.062500}, {0.125000, 0.125000}, {0.187500, 0.187500}, {0.250000, 0.250000}, {0.312500, 0.312500}, {0.375000, 0.375000}, {0.437500, 0.437500}, {0.500000, 0.500000}, {0.562500, 0.562500}, {0.625000, 0.625000}, {0.687500, 0.687500}, {0.750000, 0.750000}, {0.812500, 0.812500}, {0.875000, 0.875000}, {0.937500, 0.937500}}, {{0.000000, 0.000000}, {0.062500, 0.062500}, {0.125000, 0.125000}, {0.187500, 0.187500}, {0.250000, 0.250000}, {0.312500, 0.312500}, {0.375000, 0.375000}, {0.437500, 0.437500}, {0.500000, 0.500000}, {0.562500, 0.562500}, {0.625000, 0.625000}, {0.687500, 0.687500}, {0.750000, 0.750000}, {0.812500, 0.812500}, {0.875000, 0.875000}, {0.937500, 0.937500}}}, {16, 16, 16}, {2, 2, 2}, 1, 0, 0}},
473 {
"Nikon D90",
"NIKON CORPORATION",
"NIKON D90", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.002915, 0.006453}, {0.023324, 0.021601}, {0.078717, 0.074963}, {0.186589, 0.242230}, {0.364432, 0.544956}, {0.629738, 0.814127}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.125000, 0.125000}, {0.250000, 0.250000}, {0.375000, 0.375000}, {0.500000, 0.500000}, {0.625000, 0.625000}, {0.750000, 0.750000}, {0.875000, 0.875000}}, {{0.000000, 0.000000}, {0.125000, 0.125000}, {0.250000, 0.250000}, {0.375000, 0.375000}, {0.500000, 0.500000}, {0.625000, 0.625000}, {0.750000, 0.750000}, {0.875000, 0.875000}}}, {8, 8, 8}, {2, 2, 2}, 1, 0, 0}},
475 {
"Olympus OM-D E-M10 II",
"OLYMPUS CORPORATION ",
"E-M10MarkII ", 0, FLT_MAX, {{{{0.000000, 0.000000}, {0.004036, 0.000809}, {0.015047, 0.009425}, {0.051948, 0.042053}, {0.071777, 0.066635}, {0.090018, 0.086722}, {0.110197, 0.118773}, {0.145817, 0.171861}, {0.207476, 0.278652}, {0.266832, 0.402823}, {0.428061, 0.696319}, {0.559728, 0.847113}, {0.943576, 0.993482}, {1.000000, 1.000000}}, {{0.000000, 0.000000}, {0.071429, 0.071429}, {0.142857, 0.142857}, {0.214286, 0.214286}, {0.285714, 0.285714}, {0.357143, 0.357143}, {0.428571, 0.428571}, {0.500000, 0.500000}, {0.571429, 0.571429}, {0.642857, 0.642857}, {0.714286, 0.714286}, {0.785714, 0.785714}, {0.857143, 0.857143}, {0.928571, 0.928571}}, {{0.000000, 0.000000}, {0.071429, 0.071429}, {0.142857, 0.142857}, {0.214286, 0.214286}, {0.285714, 0.285714}, {0.357143, 0.357143}, {0.428571, 0.428571}, {0.500000, 0.500000}, {0.571429, 0.571429}, {0.642857, 0.642857}, {0.714286, 0.714286}, {0.785714, 0.785714}, {0.857143, 0.857143}, {0.928571, 0.928571}}}, {14, 14, 14}, {2, 2, 2}, 1, 0, 0}},
482 memset(&
p, 0,
sizeof(
p));
483 p.tonecurve_nodes[
ch_L] = 6;
484 p.tonecurve_nodes[
ch_a] = 7;
485 p.tonecurve_nodes[
ch_b] = 7;
489 p.tonecurve_preset = 0;
491 p.tonecurve_unbound_ab = 1;
493 float linear_ab[7] = { 0.0, 0.08, 0.3, 0.5, 0.7, 0.92, 1.0 };
496 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_a][
k].x = linear_ab[
k];
497 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_a][
k].y = linear_ab[
k];
498 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_b][
k].x = linear_ab[
k];
499 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_b][
k].y = linear_ab[
k];
502 p.tonecurve[
ch_L][0].x = 0.000000;
503 p.tonecurve[
ch_L][1].x = 0.003862;
504 p.tonecurve[
ch_L][2].x = 0.076613;
505 p.tonecurve[
ch_L][3].x = 0.169355;
506 p.tonecurve[
ch_L][4].x = 0.774194;
507 p.tonecurve[
ch_L][5].x = 1.000000;
508 p.tonecurve[
ch_L][0].y = 0.000000;
509 p.tonecurve[
ch_L][1].y = 0.007782;
510 p.tonecurve[
ch_L][2].y = 0.156182;
511 p.tonecurve[
ch_L][3].y = 0.290352;
512 p.tonecurve[
ch_L][4].y = 0.773852;
513 p.tonecurve[
ch_L][5].y = 1.000000;
515 self->version(), &
p,
sizeof(
p), 1);
517 p.tonecurve_nodes[
ch_L] = 7;
518 float linear_L[7] = { 0.0, 0.08, 0.17, 0.50, 0.83, 0.92, 1.0 };
521 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].x = linear_L[
k];
522 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].y = linear_L[
k];
524 self->version(), &
p,
sizeof(
p), 1);
527 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].x = linear_L[
k];
528 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].y = linear_L[
k];
529 p.tonecurve[
ch_L][1].y -= 0.020;
530 p.tonecurve[
ch_L][2].y -= 0.030;
531 p.tonecurve[
ch_L][4].y += 0.030;
532 p.tonecurve[
ch_L][5].y += 0.020;
534 self->version(), &
p,
sizeof(
p), 1);
536 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].x = linear_L[
k];
537 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].y = linear_L[
k];
538 p.tonecurve[
ch_L][1].y -= 0.040;
539 p.tonecurve[
ch_L][2].y -= 0.060;
540 p.tonecurve[
ch_L][4].y += 0.060;
541 p.tonecurve[
ch_L][5].y += 0.040;
543 self->version(), &
p,
sizeof(
p), 1);
546 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].x = linear_L[
k];
547 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].y = linear_L[
k];
548 p.tonecurve[
ch_L][1].y -= 0.020;
549 p.tonecurve[
ch_L][2].y -= 0.030;
550 p.tonecurve[
ch_L][4].y += 0.030;
551 p.tonecurve[
ch_L][5].y += 0.020;
552 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].x = powf(
p.tonecurve[
ch_L][
k].x, 2.2f);
553 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].y = powf(
p.tonecurve[
ch_L][
k].y, 2.2f);
555 self->version(), &
p,
sizeof(
p), 1);
557 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].x = linear_L[
k];
558 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].y = linear_L[
k];
559 p.tonecurve[
ch_L][1].y -= 0.040;
560 p.tonecurve[
ch_L][2].y -= 0.060;
561 p.tonecurve[
ch_L][4].y += 0.060;
562 p.tonecurve[
ch_L][5].y += 0.040;
563 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].x = powf(
p.tonecurve[
ch_L][
k].x, 2.2f);
564 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].y = powf(
p.tonecurve[
ch_L][
k].y, 2.2f);
566 self->version(), &
p,
sizeof(
p), 1);
572 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].x = linear_L[
k];
573 for(
int k = 0;
k < 7;
k++)
p.tonecurve[
ch_L][
k].y = linear_L[
k];
576 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].y = powf(linear_L[
k], 2.0f);
578 self->version(), &
p,
sizeof(
p), 1);
581 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].y = powf(linear_L[
k], 0.5f);
583 self->version(), &
p,
sizeof(
p), 1);
586 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].y = logf(linear_L[
k] + 1.0f) / logf(2.0f);
588 self->version(), &
p,
sizeof(
p), 1);
591 for(
int k = 1;
k < 6;
k++)
p.tonecurve[
ch_L][
k].y = powf(2.0f, linear_L[
k]) - 1.0f;
593 self->version(), &
p,
sizeof(
p), 1);
631 if(
d->curve_type[
ch] !=
p->tonecurve_type[
ch] ||
d->curve_nodes[
ch] !=
p->tonecurve_nodes[
ch])
635 d->curve_nodes[
ch] =
p->tonecurve_nodes[
ch];
636 d->curve_type[
ch] =
p->tonecurve_type[
ch];
637 for(
int k = 0;
k <
p->tonecurve_nodes[
ch];
k++)
642 for(
int k = 0;
k <
p->tonecurve_nodes[
ch];
k++)
647 for(
int k = 0;
k < 0x10000;
k++)
d->table[
ch_L][
k] *= 100.0f;
648 for(
int k = 0;
k < 0x10000;
k++)
d->table[
ch_a][
k] =
d->table[
ch_a][
k] * 256.0f - 128.0f;
649 for(
int k = 0;
k < 0x10000;
k++)
d->table[
ch_b][
k] =
d->table[
ch_b][
k] * 256.0f - 128.0f;
655 for(
int k=0;
k<0x10000;
k++)
660 Lab[0] =
d->table[
ch_L][CLAMP((
int)(
Lab[0]/100.0f * 0x10000), 0, 0xffff)];
668 for(
int k=0;
k<0x10000;
k++)
672 dt_prophotorgb_to_Lab(
rgb,
Lab);
673 Lab[0] =
d->table[
ch_L][CLAMP((
int)(
Lab[0]/100.0f * 0x10000), 0, 0xffff)];
674 dt_Lab_to_prophotorgb(
Lab,
rgb);
679 d->autoscale_ab =
p->tonecurve_autoscale_ab;
680 d->unbound_ab =
p->tonecurve_unbound_ab;
681 d->preserve_colors =
p->preserve_colors;
684 const float xm_L =
p->tonecurve[
ch_L][
p->tonecurve_nodes[
ch_L] - 1].x;
685 const float x_L[4] = { 0.7f * xm_L, 0.8f * xm_L, 0.9f * xm_L, 1.0f * xm_L };
686 const float y_L[4] = {
d->table[
ch_L][CLAMP((
int)(x_L[0] * 0x10000ul), 0, 0xffff)],
687 d->table[
ch_L][CLAMP((
int)(x_L[1] * 0x10000ul), 0, 0xffff)],
688 d->table[
ch_L][CLAMP((
int)(x_L[2] * 0x10000ul), 0, 0xffff)],
689 d->table[
ch_L][CLAMP((
int)(x_L[3] * 0x10000ul), 0, 0xffff)] };
693 const float xm_ar =
p->tonecurve[
ch_a][
p->tonecurve_nodes[
ch_a] - 1].x;
694 const float x_ar[4] = { 0.7f * xm_ar, 0.8f * xm_ar, 0.9f * xm_ar, 1.0f * xm_ar };
695 const float y_ar[4] = {
d->table[
ch_a][CLAMP((
int)(x_ar[0] * 0x10000ul), 0, 0xffff)],
696 d->table[
ch_a][CLAMP((
int)(x_ar[1] * 0x10000ul), 0, 0xffff)],
697 d->table[
ch_a][CLAMP((
int)(x_ar[2] * 0x10000ul), 0, 0xffff)],
698 d->table[
ch_a][CLAMP((
int)(x_ar[3] * 0x10000ul), 0, 0xffff)] };
702 const float xm_al = 1.0f -
p->tonecurve[
ch_a][0].x;
703 const float x_al[4] = { 0.7f * xm_al, 0.8f * xm_al, 0.9f * xm_al, 1.0f * xm_al };
704 const float y_al[4] = {
d->table[
ch_a][CLAMP((
int)((1.0f - x_al[0]) * 0x10000ul), 0, 0xffff)],
705 d->table[
ch_a][CLAMP((
int)((1.0f - x_al[1]) * 0x10000ul), 0, 0xffff)],
706 d->table[
ch_a][CLAMP((
int)((1.0f - x_al[2]) * 0x10000ul), 0, 0xffff)],
707 d->table[
ch_a][CLAMP((
int)((1.0f - x_al[3]) * 0x10000ul), 0, 0xffff)] };
711 const float xm_br =
p->tonecurve[
ch_b][
p->tonecurve_nodes[
ch_b] - 1].x;
712 const float x_br[4] = { 0.7f * xm_br, 0.8f * xm_br, 0.9f * xm_br, 1.0f * xm_br };
713 const float y_br[4] = {
d->table[
ch_b][CLAMP((
int)(x_br[0] * 0x10000ul), 0, 0xffff)],
714 d->table[
ch_b][CLAMP((
int)(x_br[1] * 0x10000ul), 0, 0xffff)],
715 d->table[
ch_b][CLAMP((
int)(x_br[2] * 0x10000ul), 0, 0xffff)],
716 d->table[
ch_b][CLAMP((
int)(x_br[3] * 0x10000ul), 0, 0xffff)] };
720 const float xm_bl = 1.0f -
p->tonecurve[
ch_b][0].x;
721 const float x_bl[4] = { 0.7f * xm_bl, 0.8f * xm_bl, 0.9f * xm_bl, 1.0f * xm_bl };
722 const float y_bl[4] = {
d->table[
ch_b][CLAMP((
int)((1.0f - x_bl[0]) * 0x10000ul), 0, 0xffff)],
723 d->table[
ch_b][CLAMP((
int)((1.0f - x_bl[1]) * 0x10000ul), 0, 0xffff)],
724 d->table[
ch_b][CLAMP((
int)((1.0f - x_bl[2]) * 0x10000ul), 0, 0xffff)],
725 d->table[
ch_b][CLAMP((
int)((1.0f - x_bl[3]) * 0x10000ul), 0, 0xffff)] };
741 piece->
data = (
void *)
d;
760 for(
int k = 0;
k < 0x10000;
k++)
d->table[
ch_L][
k] = 100.0f *
k / 0x10000;
761 for(
int k = 0;
k < 0x10000;
k++)
d->table[
ch_a][
k] = 256.0f *
k / 0x10000 - 128.0f;
762 for(
int k = 0;
k < 0x10000;
k++)
d->table[
ch_b][
k] = 256.0f *
k / 0x10000 - 128.0f;
787 gtk_widget_queue_draw(self->
gui->
widget);
800 gtk_widget_queue_draw(self->
gui->
widget);
807 module->request_histogram |= (DT_REQUEST_ON);
812 d->tonecurve_nodes[1] =
813 d->tonecurve_nodes[2] = 3;
814 d->tonecurve[0][1].x =
d->tonecurve[0][1].y =
815 d->tonecurve[1][2].x =
d->tonecurve[1][2].y =
816 d->tonecurve[2][2].x =
d->tonecurve[2][2].y = 1.0f;
817 d->tonecurve[1][1].x =
d->tonecurve[1][1].y =
818 d->tonecurve[2][1].x =
d->tonecurve[2][1].y = 0.5f;
826 for(
int k=0;
k<3;
k++)
845 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
853 if(w ==
g->autoscale_ab)
856 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
ch_L);
858 gtk_notebook_set_show_tabs(
g->channel_tabs,
p->tonecurve_autoscale_ab ==
DT_S_SCALE_MANUAL);
861 gtk_widget_queue_draw(self->
gui->
widget);
875 gtk_widget_queue_draw(GTK_WIDGET(
g->area));
884 gtk_widget_queue_draw(self->
gui->
widget);
890 GtkAllocation allocation;
891 gtk_widget_get_allocation(widget, &allocation);
892 r.width = allocation.width;
893 r.height = allocation.width;
894 gtk_widget_get_preferred_size(widget, &
r, NULL);
898static float to_log(
const float x,
const float base,
const int ch,
const int semilog,
const int is_ordinate)
901 if(base > 0.0f &&
ch ==
ch_L)
903 if (semilog == 1 && is_ordinate == 1)
908 else if (semilog == -1 && is_ordinate == 0)
915 return logf(
x * base + 1.0f) / logf(base + 1.0f);
924static float to_lin(
const float x,
const float base,
const int ch,
const int semilog,
const int is_ordinate)
927 if(base > 0.0f &&
ch ==
ch_L)
929 if (semilog == 1 && is_ordinate == 1)
934 else if (semilog == -1 && is_ordinate == 0)
941 return (powf(base + 1.0f,
x) - 1.0f) / base;
955 for(
int k=0;
k<3;
k++)
971 int nodes =
p->tonecurve_nodes[
ch];
973 int autoscale_ab =
p->tonecurve_autoscale_ab;
978 if(nodes <= 2)
return;
985 if((c->selected > 0 && (
tonecurve[c->selected - 1].
x >= mx))
986 || (c->selected < nodes - 1 && (
tonecurve[c->selected + 1].
x <= mx)))
988 for(
int k = c->selected;
k < nodes - 1;
k++)
994 p->tonecurve_nodes[
ch]--;
1003 int ch = c->channel;
1011 gtk_widget_queue_draw(widget);
1017#define TONECURVE_DEFAULT_STEP (0.001f)
1025 int ch = c->channel;
1026 int autoscale_ab =
p->tonecurve_autoscale_ab;
1031 if(c->selected < 0)
return TRUE;
1049 int ch = c->channel;
1050 int autoscale_ab =
p->tonecurve_autoscale_ab;
1055 if(c->selected < 0)
return FALSE;
1059 float dx = 0.0f, dy = 0.0f;
1060 if(
key == GDK_KEY_Up)
1065 else if(
key == GDK_KEY_Down)
1070 else if(
key == GDK_KEY_Right)
1075 else if(
key == GDK_KEY_Left)
1081 if(!handled)
return FALSE;
1086#undef TONECURVE_DEFAULT_STEP
1096 c->minmax_curve_nodes[
ch] =
p->tonecurve_nodes[
ch];
1097 c->minmax_curve_type[
ch] =
p->tonecurve_type[
ch];
1098 for(
int k = 0;
k <
p->tonecurve_nodes[
ch];
k++)
1103 c->mouse_x = c->mouse_y = -1.0;
1110 gtk_widget_set_tooltip_text(c->autoscale_ab, _(
"if set to auto, a and b curves have no effect and are "
1111 "not displayed. chroma values (a and b) of each pixel are "
1112 "then adjusted based on L curve data. auto XYZ is similar "
1113 "but applies the saturation changes in XYZ space."));
1120 g_signal_connect(G_OBJECT(c->channel_tabs),
"switch_page", G_CALLBACK(
tab_switch), self);
1122 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(c->channel_tabs),
TRUE,
TRUE, 0);
1123 gtk_box_pack_start(GTK_BOX(hbox), gtk_grid_new(),
TRUE,
TRUE, 0);
1126 gtk_widget_set_tooltip_text(c->colorpicker, _(
"pick GUI color from image\nctrl+click or right-click to select an area"));
1130 c->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
1131 gtk_widget_set_hexpand(GTK_WIDGET(c->area),
TRUE);
1132 g_object_set_data(G_OBJECT(c->area),
"iop-instance", self);
1133 gtk_box_pack_start(GTK_BOX(self->
gui->
widget),
1135 "plugins/darkroom/tonecurve/graphheight", 280, 100),
1142 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1143 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
1144 gtk_widget_set_can_focus(GTK_WIDGET(c->area),
TRUE);
1150 g_signal_connect(G_OBJECT(c->area),
"configure-event", G_CALLBACK(
area_resized), self);
1151 g_signal_connect(G_OBJECT(c->area),
"scroll-event", G_CALLBACK(
_scrolled), self);
1164 gtk_box_pack_start(GTK_BOX(self->
gui->
widget), c->interpolator ,
TRUE,
TRUE, 0);
1165 gtk_widget_set_tooltip_text(c->interpolator, _(
"change this method if you see oscillations or cusps in the curve\n"
1166 "- cubic spline is better to produce smooth curves but oscillates when nodes are too close\n"
1167 "- centripetal is better to avoids cusps and oscillations with close nodes but is less smooth\n"
1168 "- monotonic is better for accuracy of pure analytical functions (log, gamma, exp)\n"));
1169 g_signal_connect(G_OBJECT(c->interpolator),
"value-changed", G_CALLBACK(
interpolator_callback), self);
1172 gtk_widget_set_tooltip_text(c->preserve_colors, _(
"method to preserve colors when applying contrast"));
1177 g_signal_connect(G_OBJECT(c->logbase),
"value-changed", G_CALLBACK(
logbase_callback), self);
1179 c->sizegroup = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL));
1180 gtk_size_group_add_widget(c->sizegroup, GTK_WIDGET(c->area));
1181 gtk_size_group_add_widget(c->sizegroup, GTK_WIDGET(c->channel_tabs));
1188 g_object_unref(c->sizegroup);
1198 gtk_widget_queue_draw(widget);
1204 gtk_widget_queue_draw(widget);
1210 out[0] = CLAMP(in[0] / 100.0f, 0.0f, 1.0f);
1211 out[1] = CLAMP((in[1] + 128.0f) / 256.0f, 0.0f, 1.0f);
1212 out[2] = CLAMP((in[2] + 128.0f) / 256.0f, 0.0f, 1.0f);
1222 int ch = c->channel;
1223 int nodes =
p->tonecurve_nodes[
ch];
1226 if(c->minmax_curve_type[
ch] !=
p->tonecurve_type[
ch] || c->minmax_curve_nodes[
ch] !=
p->tonecurve_nodes[
ch])
1230 c->minmax_curve_nodes[
ch] =
p->tonecurve_nodes[
ch];
1231 c->minmax_curve_type[
ch] =
p->tonecurve_type[
ch];
1232 for(
int k = 0;
k <
p->tonecurve_nodes[
ch];
k++)
1237 for(
int k = 0;
k <
p->tonecurve_nodes[
ch];
k++)
1246 const float x[4] = { 0.7f * xm, 0.8f * xm, 0.9f * xm, 1.0f * xm };
1255 GtkAllocation allocation;
1256 gtk_widget_get_allocation(widget, &allocation);
1257 int width = allocation.width,
height = allocation.height;
1259 cairo_t *cr = cairo_create(cst);
1261 cairo_translate(cr, inset, inset);
1270 cairo_stroke_preserve(cr);
1274 cairo_set_source_rgb(cr, .3, .3, .3);
1284 const float origin[3][3] = { { 0.0f, 0.0f, 0.0f },
1285 { 0.0f, 231.0f/255.0f, 181.0f/255.0f },
1286 { 0.0f, 30.0f/255.0f, 195.0f/255.0f}};
1288 const float destin[3][3] = { { 1.0f, 1.0f, 1.0f },
1289 { 1.0f, 0.0f, 192.0f/255.0f } ,
1290 { 215.0f/255.0f, 182.0f/255.0f, 0.0f}};
1298 const float midgrey =
to_log(0.45f, c->loglogscale,
ch, c->semilog, 0);
1300 const float middle[3][3] = { { midgrey, midgrey, midgrey },
1301 { 0.67f, 0.67f, 0.67f},
1302 { 0.67f, 0.67f, 0.67f}};
1304 const float opacities[3] = { 0.5f, 0.5f, 0.5f};
1306 cairo_pattern_t *pat;
1307 pat = cairo_pattern_create_linear (
height, 0.0, 0.0,
width);
1308 cairo_pattern_add_color_stop_rgba (pat, 1, origin[
ch][0], origin[
ch][1], origin[
ch][2], opacities[
ch]);
1309 cairo_pattern_add_color_stop_rgba (pat, 0.5, middle[
ch][0], middle[
ch][1], middle[
ch][2], opacities[
ch]);
1310 cairo_pattern_add_color_stop_rgba (pat, 0, destin[
ch][0], destin[
ch][1], destin[
ch][2], opacities[
ch]);
1311 cairo_set_source (cr, pat);
1313 cairo_pattern_destroy (pat);
1319 if (c->loglogscale > 0.0f &&
ch ==
ch_L )
1321 if (c->semilog == 0)
1325 else if (c->semilog == 1)
1329 else if (c->semilog == -1)
1340 cairo_move_to(cr, 0,
height);
1341 cairo_line_to(cr,
width, 0);
1343 cairo_translate(cr, 0,
height);
1349 float *raw_mean, *raw_min, *raw_max;
1350 float *raw_mean_output;
1352 const gboolean is_linear =
FALSE;
1365 cairo_move_to(cr, 0,
height);
1368 if (
ch ==
ch_L && c->loglogscale > 0.0f)
1379 cairo_move_to(cr, 0,
height);
1381 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->colorpicker)))
1395 picker_min[
ch] =
to_log(picker_min[
ch], c->loglogscale,
ch, c->semilog, 0);
1396 picker_max[
ch] =
to_log(picker_max[
ch], c->loglogscale,
ch, c->semilog, 0);
1397 picker_mean[
ch] =
to_log(picker_mean[
ch], c->loglogscale,
ch, c->semilog, 0);
1399 cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.35);
1400 cairo_rectangle(cr,
width * picker_min[
ch], 0,
width * fmax(picker_max[
ch] - picker_min[
ch], 0.0f),
1403 cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.5);
1404 cairo_move_to(cr,
width * picker_mean[
ch], 0);
1410 if(raw_max[0] >= 0.0f)
1413 PangoLayout *layout;
1415 PangoFontDescription *desc = pango_font_description_copy_static(
dt_bauhaus_get_global()->pango_font_desc);
1416 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
1417 pango_font_description_set_absolute_size(desc, PANGO_SCALE);
1418 layout = pango_cairo_create_layout(cr);
1419 pango_layout_set_font_description(layout, desc);
1426 snprintf(text,
sizeof(text),
"100.00 / 100.00 ( +100.00)");
1427 pango_layout_set_text(layout, text, -1);
1428 pango_layout_get_pixel_extents(layout, &ink, NULL);
1429 pango_font_description_set_absolute_size(desc,
width*1.0/ink.width * PANGO_SCALE);
1430 pango_layout_set_font_description(layout, desc);
1432 picker_min[
ch] =
to_log(picker_min[
ch], c->loglogscale,
ch, c->semilog, 0);
1433 picker_max[
ch] =
to_log(picker_max[
ch], c->loglogscale,
ch, c->semilog, 0);
1434 picker_mean[
ch] =
to_log(picker_mean[
ch], c->loglogscale,
ch, c->semilog, 0);
1436 cairo_set_source_rgba(cr, 0.7, 0.5, 0.5, 0.35);
1437 cairo_rectangle(cr,
width * picker_min[
ch], 0,
width * fmax(picker_max[
ch] - picker_min[
ch], 0.0f),
1440 cairo_set_source_rgba(cr, 0.9, 0.7, 0.7, 0.5);
1441 cairo_move_to(cr,
width * picker_mean[
ch], 0);
1445 snprintf(text,
sizeof(text),
"%.1f \342\206\222 %.1f", raw_mean[
ch], raw_mean_output[
ch]);
1449 pango_layout_set_text(layout, text, -1);
1450 pango_layout_get_pixel_extents(layout, &ink, NULL);
1451 cairo_move_to(cr, 0.02f *
width, -0.94 *
height - ink.height - ink.y);
1452 pango_cairo_show_layout(cr, layout);
1454 pango_font_description_free(desc);
1455 g_object_unref(layout);
1479 const float x =
to_log(xx, c->loglogscale,
ch, c->semilog, 0),
1480 y =
to_log(yy, c->loglogscale,
ch, c->semilog, 1);
1488 for(
int k = 0;
k < nodes;
k++)
1495 cairo_stroke_preserve(cr);
1501 if(c->selected >= 0)
1504 PangoLayout *layout;
1506 PangoFontDescription *desc = pango_font_description_copy_static(
dt_bauhaus_get_global()->pango_font_desc);
1507 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
1508 pango_font_description_set_absolute_size(desc, PANGO_SCALE);
1509 layout = pango_cairo_create_layout(cr);
1510 pango_layout_set_font_description(layout, desc);
1513 snprintf(text,
sizeof(text),
"100.00 / 100.00 ( +100.00)");
1514 pango_layout_set_text(layout, text, -1);
1515 pango_layout_get_pixel_extents(layout, &ink, NULL);
1516 pango_font_description_set_absolute_size(desc,
width*1.0/ink.width * PANGO_SCALE);
1517 pango_layout_set_font_description(layout, desc);
1519 const float min_scale_value =
ch ==
ch_L ? 0.0f : -128.0f;
1520 const float max_scale_value =
ch ==
ch_L ? 100.0f : 128.0f;
1522 const float x_node_value =
tonecurve[c->selected].
x * (max_scale_value - min_scale_value) + min_scale_value;
1523 const float y_node_value =
tonecurve[c->selected].
y * (max_scale_value - min_scale_value) + min_scale_value;
1524 const float d_node_value = y_node_value - x_node_value;
1525 snprintf(text,
sizeof(text),
"%.1f / %.1f ( %+.1f)", x_node_value, y_node_value, d_node_value);
1528 pango_layout_set_text(layout, text, -1);
1529 pango_layout_get_pixel_extents(layout, &ink, NULL);
1530 cairo_move_to(cr, 0.98f *
width - ink.width - ink.x, -0.02 *
height - ink.height - ink.y);
1531 pango_cairo_show_layout(cr, layout);
1533 pango_font_description_free(desc);
1534 g_object_unref(layout);
1546 cairo_set_source_surface(crf, cst, 0, 0);
1548 cairo_surface_destroy(cst);
1559 for(
int k = 1;
k < *nodes;
k++)
1587 int ch = c->channel;
1588 int nodes =
p->tonecurve_nodes[
ch];
1590 int autoscale_ab =
p->tonecurve_autoscale_ab;
1596 GtkAllocation allocation;
1597 gtk_widget_get_allocation(widget, &allocation);
1598 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
1599 double old_m_x = c->mouse_x;
1600 double old_m_y = c->mouse_y;
1601 c->mouse_x =
event->x - inset;
1602 c->mouse_y =
event->y - inset;
1604 const float mx = CLAMP(c->mouse_x, 0,
width) /
width;
1605 const float my = 1.0f - CLAMP(c->mouse_y, 0,
height) /
height;
1606 const float linx =
to_lin(mx, c->loglogscale,
ch, c->semilog, 0),
1607 liny =
to_lin(my, c->loglogscale,
ch, c->semilog, 1);
1609 if(event->state & GDK_BUTTON1_MASK)
1612 if(c->selected >= 0)
1615 const float translate_mouse_x = old_m_x /
width -
to_log(
tonecurve[c->selected].
x, c->loglogscale,
ch, c->semilog, 0);
1616 const float translate_mouse_y = 1 - old_m_y /
height -
to_log(
tonecurve[c->selected].
y, c->loglogscale,
ch, c->semilog, 1);
1618 const float dx =
to_lin(c->mouse_x /
width - translate_mouse_x, c->loglogscale,
ch, c->semilog, 0)
1619 -
to_lin(old_m_x /
width - translate_mouse_x, c->loglogscale,
ch, c->semilog, 0);
1620 const float dy =
to_lin(1 - c->mouse_y /
height - translate_mouse_y, c->loglogscale,
ch, c->semilog, 1)
1621 -
to_lin(1 - old_m_y /
height - translate_mouse_y, c->loglogscale,
ch, c->semilog, 1);
1624 else if(nodes < DT_IOP_TONECURVE_MAXNODES && c->
selected >= -1)
1637 for(
int k = 0;
k < nodes;
k++)
1648 c->selected = nearest;
1651 if(c->selected >= 0) gtk_widget_grab_focus(widget);
1652 gtk_widget_queue_draw(widget);
1663 int ch = c->channel;
1664 int autoscale_ab =
p->tonecurve_autoscale_ab;
1665 int nodes =
p->tonecurve_nodes[
ch];
1668 if(event->button == 1)
1675 GtkAllocation allocation;
1676 gtk_widget_get_allocation(widget, &allocation);
1677 int width = allocation.width - 2 * inset;
1678 c->mouse_x =
event->x - inset;
1679 c->mouse_y =
event->y - inset;
1681 const float mx = CLAMP(c->mouse_x, 0,
width) / (float)
width;
1682 const float linx =
to_lin(mx, c->loglogscale,
ch, c->semilog, 0);
1690 for(
int k = 1;
k < nodes;
k++)
1708 if(y >= 0.0 && y <= 1.0)
1716 for(
int k = 0;
k < nodes;
k++)
1719 float dist = (y - other_y) * (y - other_y);
1724 gtk_widget_queue_draw(self->
gui->
widget);
1729 else if(event->type == GDK_2BUTTON_PRESS)
1735 p->tonecurve_nodes[
ch] =
d->tonecurve_nodes[
ch];
1736 p->tonecurve_type[
ch] =
d->tonecurve_type[
ch];
1737 for(
int k = 0;
k <
d->tonecurve_nodes[
ch];
k++)
1739 p->tonecurve[
ch][
k].x =
d->tonecurve[
ch][
k].x;
1740 p->tonecurve[
ch][
k].y =
d->tonecurve[
ch][
k].y;
1745 gtk_widget_queue_draw(self->
gui->
widget);
1755 gtk_widget_queue_draw(self->
gui->
widget);
1761 else if(event->button == 3 && c->selected >= 0)
1763 if(c->selected == 0 || c->selected == nodes - 1)
1765 float reset_value = c->selected == 0 ? 0 : 1;
1767 gtk_widget_queue_draw(self->
gui->
widget);
1772 for(
int k = c->selected;
k < nodes - 1;
k++)
1779 p->tonecurve_nodes[
ch]--;
1780 gtk_widget_queue_draw(self->
gui->
widget);
Handle default and user-set shortcuts (accelerators)
static double dist(double x1, double y1, double x2, double y2)
float dt_bauhaus_slider_get(GtkWidget *widget)
int dt_bauhaus_combobox_get(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_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
@ DT_COLOR_PICKER_POINT_AREA
@ DT_LIB_COLORPICKER_STATISTIC_MAX
@ DT_LIB_COLORPICKER_STATISTIC_MIN
@ DT_LIB_COLORPICKER_STATISTIC_MEAN
dt_iop_order_iccprofile_info_t * dt_colorspaces_add_profile(const dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename, const int intent)
Find-or-build the derived matrix/LUT data for a profile identity, memoised.
static dt_aligned_pixel_t float *const const float unbounded_coeffs[3][3]
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static dt_aligned_pixel_t rgb
static const float const float const float min
static dt_aligned_pixel_t XYZ
static dt_aligned_pixel_t Lab
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
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)
GHashTable * selected
set of checked row labels, mirrored to conf on every change
static void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
static void set_color(cairo_t *cr, GdkRGBA color)
static void dt_draw_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
static void dt_draw_semilog_y_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom, const float base)
static float dt_draw_curve_calc_value(dt_draw_curve_t *c, const float x)
static void dt_draw_curve_destroy(dt_draw_curve_t *c)
static void dt_draw_histogram_8_log_base(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const gboolean linear, float base_log)
static void dt_draw_curve_set_point(dt_draw_curve_t *c, const int num, const float x, const float y)
static int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
static void dt_draw_semilog_x_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom, const float base)
static void dt_draw_histogram_8(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const gboolean linear)
static dt_draw_curve_t * dt_draw_curve_new(const float min, const float max, unsigned int type)
static void dt_draw_loglog_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom, const float base)
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
void dt_gui_presets_update_filter(const char *name, dt_dev_operation_t op, const int32_t version, const int filter)
void dt_gui_presets_update_ldr(const char *name, dt_dev_operation_t op, const int32_t version, const int ldrflag)
void dt_gui_presets_update_iso(const char *name, dt_dev_operation_t op, const int32_t version, const float min, const float max)
void dt_gui_presets_update_mml(const char *name, dt_dev_operation_t op, const int32_t version, const char *maker, const char *model, const char *lens)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled)
void dt_iop_default_init(dt_iop_module_t *module)
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)
@ DT_REQUEST_COLORPICK_MODULE
@ IOP_FLAGS_SUPPORTS_BLENDING
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)
static void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
static float dt_iop_eval_exp(const float *const coeff, const float x)
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)
void init(dt_iop_module_t *module)
static float to_lin(const float x, const float base, const int ch, const int semilog, const int is_ordinate)
static gboolean area_resized(GtkWidget *widget, GdkEvent *event, gpointer user_data)
const char ** description(struct dt_iop_module_t *self)
struct dt_iop_tonecurve_params_t dt_iop_tonecurve_params_t
static void interpolator_callback(GtkWidget *widget, dt_iop_module_t *self)
static gboolean dt_iop_tonecurve_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data)
#define DT_IOP_TONECURVE_MAXNODES
static gboolean dt_iop_tonecurve_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
static gboolean dt_iop_tonecurve_leave_notify(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
dt_iop_tonecurve_autoscale_t
@ DT_S_SCALE_AUTOMATIC_RGB
@ DT_S_SCALE_AUTOMATIC_XYZ
#define DT_GUI_CURVE_EDITOR_INSET
static float eval_grey(float x)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
struct dt_iop_tonecurve_params_t preset
void gui_reset(struct dt_iop_module_t *self)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
static int _add_node(dt_iop_tonecurve_node_t *tonecurve, int *nodes, float x, float y)
static gboolean dt_iop_tonecurve_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
void gui_init(struct dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
static void dt_iop_tonecurve_sanity_check(dt_iop_module_t *self, GtkWidget *widget)
static void logbase_callback(GtkWidget *slider, dt_iop_module_t *self)
void cleanup_global(dt_iop_module_so_t *module)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
#define TONECURVE_DEFAULT_STEP
void gui_cleanup(struct dt_iop_module_t *self)
void init_presets(dt_iop_module_so_t *self)
static gboolean dt_iop_tonecurve_enter_notify(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
#define DT_IOP_TONECURVE_RES
__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 i, void *const o)
struct dt_iop_tonecurve_node_t dt_iop_tonecurve_node_t
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void picker_scale(const float *in, float *out)
static gboolean _scrolled(GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
void init_global(dt_iop_module_so_t *module)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void tab_switch(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data)
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 gboolean _move_point_internal(dt_iop_module_t *self, GtkWidget *widget, float dx, float dy, guint state)
static const struct @47 preset_camera_curves[]
static float to_log(const float x, const float base, const int ch, const int semilog, const int is_ordinate)
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_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.
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
GtkNotebook * dt_ui_notebook_new()
void dt_ui_notebook_set_picker_owner(GtkNotebook *notebook, gpointer owner)
Register an opaque owner for a GtkNotebook's page switches, and report every "switch_page" to the hos...
#define __OMP_PARALLEL_FOR__(...)
@ DT_DEV_PIXELPIPE_PREVIEW
@ DT_COLORSPACE_PROPHOTO_RGB
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
const float uint32_t state[4]
lib_colorpicker_sample_statistics lab
dt_dev_request_flags_t request_histogram
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
struct dt_develop_t::@13 color_picker
Authoritative darkroom color-picker state.
dt_iop_global_data_t * data
dt_dev_request_colorpick_flags_t request_color_pick
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
uint32_t histogram_max[4]
dt_iop_global_data_t * global_data
dt_aligned_pixel_t picked_output_color
dt_aligned_pixel_t picked_color_min
dt_aligned_pixel_t picked_color_max
dt_aligned_pixel_t picked_color
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
Region of interest passed through the pixelpipe.
dt_draw_curve_t * curve[3]
float unbounded_coeffs_ab[12]
float unbounded_coeffs_L[3]
float picked_color_max[3]
float picked_color_min[3]
float picked_output_color[3]
dt_draw_curve_t * minmax_curve[3]
GtkNotebook * channel_tabs
GtkWidget * preserve_colors
tonecurve_channel_t channel
int minmax_curve_nodes[3]
int tonecurve_autoscale_ab
dt_iop_tonecurve_node_t tonecurve[3][20]
dt_iop_tonecurve_node_t tonecurve[3][20]
int tonecurve_autoscale_ab
dt_iop_tonecurve_node_t tonecurve[3][20]
dt_iop_tonecurve_autoscale_t tonecurve_autoscale_ab
dt_iop_rgb_norms_t preserve_colors
#define __DT_CLONE_TARGETS__