82#ifdef GDK_WINDOWING_QUARTZ
86#define HISTOGRAM_BINS 256
87#define GAMMA 1.f / 2.f
88#define DT_LIB_HISTOGRAM_SCOPE_MIN_VALUE (1.f / 256.f)
89#define DT_LIB_HISTOGRAM_SCOPE_ENABLE_SMOOTHING 1
90#define DT_LIB_HISTOGRAM_SCOPE_SMOOTH_SPATIAL_PASSES 1
91#define DT_LIB_HISTOGRAM_SCOPE_SMOOTH_TONE_PASSES 4
92#define DT_LIB_HISTOGRAM_SCOPE_SMOOTH_FORCE (256 * 0.33)
93#define DT_LIB_HISTOGRAM_SCOPE_RESTRICTED_LABEL_OPERATOR CAIRO_OPERATOR_ADD
94#define DT_LIB_HISTOGRAM_SCOPE_DEFAULT_HEIGHT 250
95#define DT_LIB_HISTOGRAM_SCOPE_MIN_HEIGHT 120
96#define DT_LIB_HISTOGRAM_SCOPE_MAX_HEIGHT 500
97#define DT_LIB_HISTOGRAM_SCOPE_HANDLE_HEIGHT 8
98#define DT_LIB_HISTOGRAM_SCOPE_HEIGHT_CONF "plugin/darkroom/histogram/scope_height"
135 = { N_(
"RGB"), N_(
"Lab"), N_(
"LCh"), N_(
"HSL"), N_(
"HSV"), N_(
"none"), NULL };
137 = { N_(
"mean"), N_(
"min"), N_(
"max"), NULL };
237 .crop_x = 0, .crop_y = 0, .crop_width = 0, .crop_height = 0
239 histogram_params.
roi = &histogram_roi;
257 if(!strcmp(op,
"initialscale"))
259 else if(!strcmp(op,
"colorout"))
261 else if(!strcmp(op,
"gamma"))
298 if(!strcmp(op,
"gamma"))
306 roi = &previous_piece->
roi_out;
307 dsc = &previous_piece->
dsc_out;
316 NULL, &entry, NULL, NULL, NULL))
323 if(previous_hash != hash)
364 const float *histogram_input = input;
365 float *transformed_input = NULL;
372 const size_t bytes = pixels * (size_t)piece->
dsc_in.
channels *
sizeof(
float);
382 memcpy(transformed_input, input, bytes);
387 histogram_input = transformed_input;
411 const char *ops[] = {
"initialscale",
"colorout",
"gamma" };
418 for(
size_t i = 0;
i < G_N_ELEMENTS(ops);
i++)
429 if(!strcmp(ops[
i],
"gamma"))
446 if(*pending_hashes[
i] == hash)
continue;
451 *pending_hashes[
i] = hash;
454 GHashTable *seen_modules = g_hash_table_new(g_direct_hash, g_direct_equal);
455 for(GList *node = g_list_first(dev->
preview_pipe->
nodes); node; node = g_list_next(node))
462 g_hash_table_insert(seen_modules, piece->module, piece->module);
469 gboolean found =
FALSE;
473 if(
IS_NULL_PTR(pending) || pending->module != piece->module)
continue;
482 pending->module = piece->module;
492 GList *next = g_list_next(l);
494 if(pending && pending->module == piece->module)
508 GList *next = g_list_next(l);
510 if(
IS_NULL_PTR(pending) || !g_hash_table_contains(seen_modules, pending->module))
518 g_hash_table_destroy(seen_modules);
555 GList *next = g_list_next(l);
557 if(pending->
hash == hash)
574 static const char *
v[] = {
"darkroom", NULL};
604 d->op =
"initialscale";
622 if(!strcmp(
d->op,
"initialscale") || !strcmp(
d->op,
"demosaic"))
return 0;
623 if(!strcmp(
d->op,
"colorout"))
return 1;
624 if(!strcmp(
d->op,
"gamma"))
return 2;
630#pragma omp declare simd \
631 aligned(rgb_in, xyz_out:64) \
632 uniform(rgb_in, xyz_out)
654#pragma omp declare simd \
655 aligned(rgb_in, rgb_out:64) \
656 uniform(rgb_in, rgb_out)
674 "[histogram] sample swatch");
682 d->cache.height = -1;
690 g_array_set_size(
d->pending_hashes, 0);
697 for(guint
i = 0;
i <
d->pending_hashes->len;
i++)
698 if(g_array_index(
d->pending_hashes,
uint64_t,
i) == hash)
return TRUE;
706 g_array_append_val(
d->pending_hashes, hash);
713 for(guint
i = 0;
i <
d->pending_hashes->len;
i++)
715 if(g_array_index(
d->pending_hashes,
uint64_t,
i) == hash)
717 g_array_remove_index(
d->pending_hashes,
i);
733 dt_iop_module_t *
const module = dt_iop_get_module_by_op_priority(dev->iop, op, 0);
739 if(!strcmp(op,
"gamma"))
752 d->refresh_idle_source = 0;
755 return G_SOURCE_REMOVE;
776 if(sample->
locked)
continue;
812 gtk_widget_queue_draw(
d->scope_draw);
817 uint32_t max_hist = 0;
819 for(
size_t k = 0;
k < binning_size;
k++)
if(bins[
k] > max_hist) max_hist = bins[
k];
826 memcpy(box, sample->
box,
sizeof(
float) * 4);
839 const size_t min_x,
const size_t max_x,
840 const size_t min_y,
const size_t max_y,
852 for(
size_t i = min_y;
i < max_y;
i++)
853 for(
size_t j = min_x; j < max_x; j++)
854 for(
size_t c = 0; c < 3; c++)
856 const float value = image[(
i *
width + j) * 4 + c];
858 bins[index * 4 + c]++;
870 float image_box[4] = { 0.0f };
872 const size_t box[4] = {
873 CLAMP((
size_t)roundf(image_box[0] *
width), 0,
width),
874 CLAMP((
size_t)roundf(image_box[1] *
height), 0,
height),
875 CLAMP((
size_t)roundf(image_box[2] *
width), 0,
width),
882 float image_point[2] = { 0.0f };
884 const size_t x = CLAMP((
size_t)roundf(image_point[0] *
width), 0,
width - 1);
885 const size_t y = CLAMP((
size_t)roundf(image_point[1] *
height), 0,
height - 1);
893 const gboolean restrict_active = !
IS_NULL_PTR(
d->restrict_button)
894 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->restrict_button));
895 const gboolean picker_active = !
IS_NULL_PTR(
d->picker_button)
896 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->picker_button));
897 return restrict_active && picker_active;
937 samples = g_slist_next(samples);
954 if(overall_histogram_max > 0)
965 cairo_push_group_with_content(cr, CAIRO_CONTENT_COLOR);
966 cairo_translate(cr, 0,
height);
967 cairo_scale(cr,
width / 255.0, - (
double)
height / (
double)(1. + log(overall_histogram_max)));
968 cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
970 for(
int k = 0;
k < 3;
k++)
976 cairo_pop_group_to_source(cr);
977 cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
978 cairo_paint_with_alpha(cr, 0.5);
987 const size_t min_x,
const size_t max_x,
988 const size_t min_y,
const size_t max_y,
989 const size_t source_width,
const size_t source_height,
990 const size_t tone_bins,
const size_t raster_extent,
991 const gboolean vertical)
999 for(
size_t raster_y = 0; raster_y < raster_extent; raster_y++)
1001 const double source_y0d = (
double)raster_y * (
double)source_height / (
double)raster_extent;
1002 const double source_y1d = (
double)(raster_y + 1) * (
double)source_height / (
double)raster_extent;
1003 const size_t source_y0 =
MAX(min_y, (
size_t)floor(source_y0d));
1004 const size_t source_y1 =
MIN(max_y, (
size_t)ceil(source_y1d));
1005 if(source_y0 >= source_y1)
continue;
1007 for(
size_t i = source_y0;
i < source_y1;
i++)
1009 const double overlap =
MIN((
double)(
i + 1), source_y1d) -
MAX((
double)
i, source_y0d);
1010 const uint32_t
weight =
MAX(1u, (uint32_t)round(overlap * 256.));
1012 for(
size_t j = min_x; j < max_x; j++)
1013 for(
size_t c = 0; c < 3; c++)
1015 const float value = image[(
i * source_width + j) * 4 + c];
1016 const float tone_position =
CLAMPF(
value, 0.f, 1.f) * (float)(tone_bins - 1);
1017 const size_t tone0 = (size_t)floorf(tone_position);
1018 const size_t tone1 =
MIN(tone0 + 1, tone_bins - 1);
1019 const float tone_mix = tone_position - (float)tone0;
1020 const uint32_t weight1 = (uint32_t)roundf((
float)
weight * tone_mix);
1021 const uint32_t weight0 =
weight - weight1;
1022 bins[(raster_y * tone_bins + tone0) * 4 + c] += weight0;
1023 bins[(raster_y * tone_bins + tone1) * 4 + c] += weight1;
1033 for(
size_t raster_x = 0; raster_x < raster_extent; raster_x++)
1035 const double source_x0d = (
double)raster_x * (
double)source_width / (
double)raster_extent;
1036 const double source_x1d = (
double)(raster_x + 1) * (
double)source_width / (
double)raster_extent;
1037 const size_t source_x0 =
MAX(min_x, (
size_t)floor(source_x0d));
1038 const size_t source_x1 =
MIN(max_x, (
size_t)ceil(source_x1d));
1039 if(source_x0 >= source_x1)
continue;
1041 for(
size_t j = source_x0; j < source_x1; j++)
1043 const double overlap =
MIN((
double)(j + 1), source_x1d) -
MAX((
double)j, source_x0d);
1044 const uint32_t
weight =
MAX(1u, (uint32_t)round(overlap * 256.));
1046 for(
size_t i = min_y;
i < max_y;
i++)
1047 for(
size_t c = 0; c < 3; c++)
1049 const float value = image[(
i * source_width + j) * 4 + c];
1050 const float tone_position =
CLAMPF(
value, 0.f, 1.f) * (float)(tone_bins - 1);
1051 const size_t tone0 = (size_t)floorf(tone_position);
1052 const size_t tone1 =
MIN(tone0 + 1, tone_bins - 1);
1053 const float tone_mix = tone_position - (float)tone0;
1054 const uint32_t weight1 = (uint32_t)roundf((
float)
weight * tone_mix);
1055 const uint32_t weight0 =
weight - weight1;
1056 bins[((tone_bins - 1 - tone0) * raster_extent + raster_x) * 4 + c] += weight0;
1057 bins[((tone_bins - 1 - tone1) * raster_extent + raster_x) * 4 + c] += weight1;
1066 const size_t tone_bins,
const size_t raster_extent,
1071 float image_box[4] = { 0.0f };
1073 const size_t box[4] = {
1074 CLAMP((
size_t)roundf(image_box[0] *
width), 0,
width),
1075 CLAMP((
size_t)roundf(image_box[1] *
height), 0,
height),
1076 CLAMP((
size_t)roundf(image_box[2] *
width), 0,
width),
1077 CLAMP((
size_t)roundf(image_box[3] *
height), 0,
height)
1080 width,
height, tone_bins, raster_extent, vertical);
1084 float image_point[2] = { 0.0f };
1086 const size_t x = CLAMP((
size_t)roundf(image_point[0] *
width), 0,
width - 1);
1087 const size_t y = CLAMP((
size_t)roundf(image_point[1] *
height), 0,
height - 1);
1089 width,
height, tone_bins, raster_extent, vertical);
1095 const size_t width,
const size_t height,
const size_t binning_size,
1096 const size_t tone_bins,
const size_t raster_extent,
1097 const gboolean vertical,
const gboolean restricted)
1101 for(
size_t k = 0;
k < binning_size;
k++) bins[
k] = 0;
1111 samples = g_slist_next(samples);
1122 width,
height, tone_bins, raster_extent, vertical);
1127 const uint32_t max_hist,
1136 image[
k + 2] = (uint8_t)CLAMP(roundf(powf((
float)bins[
k + 0] / (float)max_hist,
GAMMA) * 255.f), 0, 255);
1137 image[
k + 1] = (uint8_t)CLAMP(roundf(powf((
float)bins[
k + 1] / (float)max_hist,
GAMMA) * 255.f), 0, 255);
1138 image[
k + 0] = (uint8_t)CLAMP(roundf(powf((
float)bins[
k + 2] / (float)max_hist,
GAMMA) * 255.f), 0, 255);
1143 const size_t img_width,
const size_t img_height,
const size_t tone_bins,
1144 const gboolean vertical)
1146 const size_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, img_width);
1147 cairo_surface_t *background = cairo_image_surface_create_for_data(image, CAIRO_FORMAT_ARGB32, img_width, img_height, stride);
1148 const double scale_w = (vertical) ? (
double)
width / (
double)tone_bins
1150 const double scale_h = (vertical) ? (
double)
height / (
double)img_height
1152 cairo_scale(cr, scale_w, scale_h);
1153 cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
1154 cairo_set_source_surface(cr, background, 0., 0.);
1155 cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BEST);
1157 cairo_surface_destroy(background);
1161static void _process_waveform(
dt_backbuf_t *backbuf,
const char *op, cairo_t *cr,
const int width,
1162 const int height,
const gboolean vertical,
const gboolean parade,
1187 const size_t raster_extent =
MAX(2, (vertical)
1190 const size_t binning_size = 4 * tone_bins * raster_extent;
1191 const size_t img_width = (parade) ?
width : ((vertical) ? tone_bins : raster_extent);
1192 const size_t img_height = (parade) ?
height : ((vertical) ? raster_extent : tone_bins);
1193 const size_t image_size = 4 * img_width * img_height;
1194 const size_t source_axis = (vertical) ? backbuf->
height : backbuf->
width;
1195 float source_min = INFINITY;
1196 float source_max = -INFINITY;
1197 size_t source_clipped = 0;
1198 size_t source_nan = 0;
1199 const size_t source_step =
MAX((
size_t)1, (backbuf->
width * backbuf->
height) / 4096);
1200 for(
size_t pixel = 0; pixel < backbuf->
width * backbuf->
height; pixel += source_step)
1201 for(
size_t c = 0;
c < 3;
c++)
1203 const float value = ((
const float *)
data)[pixel * 4 +
c];
1208 source_min = fminf(source_min,
value);
1209 source_max = fmaxf(source_max,
value);
1210 source_clipped += (
value < 0.f ||
value > 1.f);
1213 uint32_t *smooth_bins = NULL;
1217 "[histogram/scope] waveform setup op=%s parade=%d vertical=%d widget=%dx%d backbuf=%" G_GSIZE_FORMAT
"x%" G_GSIZE_FORMAT
" "
1218 "tone_bins=%" G_GSIZE_FORMAT
" raster_extent=%" G_GSIZE_FORMAT
" source_axis=%" G_GSIZE_FORMAT
1219 " source_per_raster=%.4f binning_size=%" G_GSIZE_FORMAT
" "
1220 "source_value=%0.6f..%0.6f clipped=%" G_GSIZE_FORMAT
" nan=%" G_GSIZE_FORMAT
" sample_step=%" G_GSIZE_FORMAT
"\n",
1222 tone_bins, raster_extent, source_axis, (
double)source_axis / (
double)raster_extent,
1223 binning_size, source_min, source_max, source_clipped, source_nan, source_step);
1225 binning_size *
sizeof(uint32_t),
1228 image_size *
sizeof(uint8_t),
1234 "[histogram/scope] waveform allocation failed bins=%p image=%p binning_size=%" G_GSIZE_FORMAT
1235 " image_size=%" G_GSIZE_FORMAT
"\n",
1236 (
void *)bins, (
void *)image, binning_size, image_size);
1244 const uint32_t *render_bins = bins;
1245 int smoothing_passes = 0;
1246#if DT_LIB_HISTOGRAM_SCOPE_ENABLE_SMOOTHING \
1247 && (DT_LIB_HISTOGRAM_SCOPE_SMOOTH_SPATIAL_PASSES > 0 \
1248 || DT_LIB_HISTOGRAM_SCOPE_SMOOTH_TONE_PASSES > 0)
1251 if(!
IS_NULL_PTR(smooth_bins) && smoothing_force > 0)
1257 const uint32_t original_force = 256u - smoothing_force;
1261 const uint32_t *
const source_bins = render_bins;
1262 uint32_t *
const target_bins = (source_bins == bins) ? smooth_bins : bins;
1266 for(
size_t axis = 0; axis < raster_extent; axis++)
1268 const size_t axis_m2 = (axis > 1) ? axis - 2 : 0;
1269 const size_t axis_m1 = (axis > 0) ? axis - 1 : 0;
1270 const size_t axis_p1 =
MIN(axis + 1, raster_extent - 1);
1271 const size_t axis_p2 =
MIN(axis + 2, raster_extent - 1);
1272 for(
size_t tone = 0; tone < tone_bins; tone++)
1273 for(
size_t c = 0;
c < 4;
c++)
1275 const size_t index = (axis * tone_bins + tone) * 4 + c;
1276 const uint64_t smoothed = source_bins[(axis_m2 * tone_bins + tone) * 4 + c]
1277 + 4u * source_bins[(axis_m1 * tone_bins + tone) * 4 +
c]
1278 + 6u * source_bins[index]
1279 + 4u * source_bins[(axis_p1 * tone_bins + tone) * 4 + c]
1280 + source_bins[(axis_p2 * tone_bins + tone) * 4 +
c];
1281 const uint64_t blended = original_force * source_bins[index]
1282 + smoothing_force * ((smoothed + 8u) / 16u);
1283 target_bins[index] = (uint32_t)((blended + 128u) / 256u);
1289 for(
size_t tone = 0; tone < tone_bins; tone++)
1290 for(
size_t axis = 0; axis < raster_extent; axis++)
1292 const size_t axis_m2 = (axis > 1) ? axis - 2 : 0;
1293 const size_t axis_m1 = (axis > 0) ? axis - 1 : 0;
1294 const size_t axis_p1 =
MIN(axis + 1, raster_extent - 1);
1295 const size_t axis_p2 =
MIN(axis + 2, raster_extent - 1);
1296 for(
size_t c = 0;
c < 4;
c++)
1298 const size_t index = (tone * raster_extent + axis) * 4 + c;
1299 const uint64_t smoothed = source_bins[(tone * raster_extent + axis_m2) * 4 + c]
1300 + 4u * source_bins[(tone * raster_extent + axis_m1) * 4 +
c]
1301 + 6u * source_bins[index]
1302 + 4u * source_bins[(tone * raster_extent + axis_p1) * 4 + c]
1303 + source_bins[(tone * raster_extent + axis_p2) * 4 +
c];
1304 const uint64_t blended = original_force * source_bins[index]
1305 + smoothing_force * ((smoothed + 8u) / 16u);
1306 target_bins[index] = (uint32_t)((blended + 128u) / 256u);
1311 render_bins = target_bins;
1317 const uint32_t *
const source_bins = render_bins;
1318 uint32_t *
const target_bins = (source_bins == bins) ? smooth_bins : bins;
1322 for(
size_t axis = 0; axis < raster_extent; axis++)
1323 for(
size_t tone = 0; tone < tone_bins; tone++)
1325 const size_t tone_m1 = (tone > 0) ? tone - 1 : 0;
1326 const size_t tone_p1 =
MIN(tone + 1, tone_bins - 1);
1327 for(
size_t c = 0;
c < 4;
c++)
1329 const size_t index = (axis * tone_bins + tone) * 4 + c;
1330 const uint64_t smoothed = source_bins[(axis * tone_bins + tone_m1) * 4 + c]
1331 + 2u * source_bins[index]
1332 + source_bins[(axis * tone_bins + tone_p1) * 4 +
c];
1333 const uint64_t blended = original_force * source_bins[index]
1334 + smoothing_force * ((smoothed + 2u) / 4u);
1335 target_bins[index] = (uint32_t)((blended + 128u) / 256u);
1341 for(
size_t tone = 0; tone < tone_bins; tone++)
1343 const size_t tone_m1 = (tone > 0) ? tone - 1 : 0;
1344 const size_t tone_p1 =
MIN(tone + 1, tone_bins - 1);
1345 for(
size_t axis = 0; axis < raster_extent; axis++)
1346 for(
size_t c = 0;
c < 4;
c++)
1348 const size_t index = (tone * raster_extent + axis) * 4 + c;
1349 const uint64_t smoothed = source_bins[(tone_m1 * raster_extent + axis) * 4 + c]
1350 + 2u * source_bins[index]
1351 + source_bins[(tone_p1 * raster_extent + axis) * 4 +
c];
1352 const uint64_t blended = original_force * source_bins[index]
1353 + smoothing_force * ((smoothed + 2u) / 4u);
1354 target_bins[index] = (uint32_t)((blended + 128u) / 256u);
1359 render_bins = target_bins;
1370 size_t empty_axis = 0;
1373 uint32_t min_axis_peak = UINT32_MAX;
1374 uint32_t max_axis_peak = 0;
1375 for(
size_t axis = 0; axis < raster_extent; axis++)
1378 uint32_t axis_peak = 0;
1379 for(
size_t tone = 0; tone < tone_bins; tone++)
1381 const size_t pixel = (vertical) ? axis * tone_bins + tone : tone * raster_extent + axis;
1382 for(
size_t c = 0;
c < 3;
c++)
1384 const uint32_t
value = render_bins[pixel * 4 +
c];
1385 axis_total +=
value;
1390 if(axis_total == 0) empty_axis++;
1391 min_axis =
MIN(min_axis, axis_total);
1392 max_axis =
MAX(max_axis, axis_total);
1393 min_axis_peak =
MIN(min_axis_peak, axis_peak);
1394 max_axis_peak =
MAX(max_axis_peak, axis_peak);
1396 const size_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, img_width);
1398 "[histogram/scope] waveform raster op=%s parade=%d vertical=%d image=%" G_GSIZE_FORMAT
"x%" G_GSIZE_FORMAT
1399 " stride=%" G_GSIZE_FORMAT
" overall_max=%u empty_axis=%" G_GSIZE_FORMAT
" axis_total=%" PRIu64
"..%" PRIu64
1400 " axis_peak=%u..%u smooth=%d scale=%0.4fx%0.4f\n",
1401 op, parade, vertical, img_width, img_height, stride, overall_max_hist,
1402 empty_axis, min_axis, max_axis, min_axis_peak, max_axis_peak, smoothing_passes,
1403 (
double)
width / (
double)img_width, (
double)
height / (
double)img_height);
1406 if(overall_max_hist > 0)
1413 for(
size_t k = 0;
k < image_size;
k++) image[
k] = 0;
1415 for(
size_t c = 0;
c < 3;
c++)
1417 const size_t x0 = vertical ? 0 :
c *
width / 3;
1418 const size_t x1 = vertical ?
width : (
c + 1) *
width / 3;
1419 const size_t y0 = vertical ?
c *
height / 3 : 0;
1421 const size_t channel_width = x1 - x0;
1422 const size_t channel_height = y1 - y0;
1423 if(channel_width == 0 || channel_height == 0)
continue;
1425 for(
size_t y = y0; y < y1; y++)
1426 for(
size_t x = x0;
x < x1;
x++)
1428 const size_t axis = vertical
1429 ? (y - y0) * raster_extent / channel_height
1430 : (
x - x0) * raster_extent / channel_width;
1431 const size_t tone = vertical ?
x : y;
1432 const size_t bin_index = vertical ? (axis * tone_bins + tone) * 4 + c
1433 : (tone * raster_extent + axis) * 4 +
c;
1434 const uint8_t
value = (uint8_t)CLAMP(roundf(powf((
float)render_bins[bin_index] / (
float)overall_max_hist,
GAMMA) * 255.f), 0, 255);
1435 const size_t image_index = (y * img_width +
x) * 4;
1436 image[image_index + 2 -
c] =
value;
1437 image[image_index + 3] = 255;
1447 cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
1463 cairo_set_source_rgb(cr, 0.21, 0.21, 0.21);
1464 const gboolean raw_stage = (!strcmp(op,
"initialscale") || !strcmp(op,
"demosaic"));
1470 for(
int k = 1; !parade &&
k < 4;
k++)
1483 for(
int k = 1;
k < 4;
k++)
1500 for(
int stop = 0; stop <= 8; stop++)
1545 const size_t min_x,
const size_t max_x,
const size_t min_y,
1546 const size_t max_y,
const size_t width,
const float zoom,
1551#pragma omp parallel for default(firstprivate) \
1552 reduction(+: vectorscope[0: HISTOGRAM_BINS * HISTOGRAM_BINS])
1554#pragma omp parallel for default(firstprivate) \
1558 for(
size_t i = min_y;
i < max_y;
i++)
1559 for(
size_t j = min_x; j < max_x; j++)
1578 uint32_t *
const restrict vectorscope,
const size_t width,
1584 float image_box[4] = { 0.0f };
1586 const size_t box[4] = {
1587 CLAMP((
size_t)roundf(image_box[0] *
width), 0,
width),
1588 CLAMP((
size_t)roundf(image_box[1] *
height), 0,
height),
1589 CLAMP((
size_t)roundf(image_box[2] *
width), 0,
width),
1590 CLAMP((
size_t)roundf(image_box[3] *
height), 0,
height)
1596 float image_point[2] = { 0.0f };
1598 const size_t x = CLAMP((
size_t)roundf(image_point[0] *
width), 0,
width - 1);
1599 const size_t y = CLAMP((
size_t)roundf(image_point[1] *
height), 0,
height - 1);
1606 const uint32_t max_hist,
const float zoom)
1614 const float value = sqrtf((
float)vectorscope[index] / (
float)max_hist);
1621 for(
int c = 0; c < 2; c++)
xyY[c] = fmaxf(
xyY[c], 0.f);
1623 for(
int c = 0; c < 3; c++)
XYZ[c] = fmaxf(
XYZ[c], 0.f);
1627 for(
int c = 0; c < 3; c++)
RGB[c] = fmaxf(
RGB[c], 0.f);
1628 const float max_RGB = fmax(
RGB[0], fmaxf(
RGB[1],
RGB[2]));
1629 for(
int c = 0; c < 3; c++)
RGB[c] /= max_RGB;
1631 image[index * 4 + 3] = (uint8_t)roundf(
value * 255.f);
1633 image[index * 4 + 2] = (uint8_t)roundf(powf(
RGB[0] *
value, 1.f / 2.2f) * 255.f);
1634 image[index * 4 + 1] = (uint8_t)roundf(powf(
RGB[1] *
value, 1.f / 2.2f) * 255.f);
1635 image[index * 4 + 0] = (uint8_t)roundf(powf(
RGB[2] *
value, 1.f / 2.2f) * 255.f);
1654 samples = g_slist_next(samples);
1704 const size_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,
HISTOGRAM_BINS);
1707 cairo_translate(cr, (
double)(
width - side) / 2., (
double)(
height - side) / 2.);
1714 cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
1715 cairo_arc(cr, x_center, x_center, radius, 0., 2. *
M_PI);
1719 cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
1720 cairo_arc(cr, x_center, x_center, 2., 0., 2. *
M_PI);
1724 for(
int k = 0;
k < 4;
k++)
1731 dt_aligned_pixel_t colors[6] = { { 1.f, 0.f, 0.f, 0.f }, { 1.f, 1.f, 0.f, 0.f }, { 0.f, 1.f, 0.f, 0.f },
1732 { 0.f, 1.f, 1.f, 0.f }, { 0.f, 0.f, 1.f, 0.f }, { 1.f, 0.f, 1.f, 0.f } };
1735 cairo_arc(cr, x_center, x_center, radius, 0., 2. *
M_PI);
1738 for(
size_t k = 0;
k < 6;
k++)
1756 const double delta_x = radius * cosf(
Lch[2]);
1757 const double delta_y = radius * sinf(
Lch[2]);
1758 const double destination_x = x_center + delta_x;
1759 const double destination_y = (
HISTOGRAM_BINS - 1) - (x_center + delta_y);
1760 cairo_move_to(cr, x_center, x_center);
1761 cairo_line_to(cr, destination_x, destination_y);
1767 cairo_arc(cr,
x, y, half_square, 0, 2. *
M_PI);
1768 cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
1769 cairo_fill_preserve(cr);
1778 cairo_set_source_rgb(cr, 0.33, 0.33, 0.33);
1783 for(
size_t h = 0; h < 180; h++)
1794 const float max_RGB = fmaxf(fmaxf(
RGB[0],
RGB[1]),
RGB[2]);
1795 for(
int c = 0; c < 3; c++)
RGB[c] /= max_RGB;
1798 const double destination_x = x_center + delta_x;
1799 const double destination_y = (
HISTOGRAM_BINS - 1) - (x_center + delta_y);
1800 cairo_set_source_rgba(cr,
RGB[0],
RGB[1],
RGB[2], 0.7);
1806 cairo_arc(cr, x_center, x_center, radius, 0., 2. *
M_PI);
1808 cairo_set_source_surface(cr, background, 0., 0.);
1809 cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BEST);
1811 cairo_surface_destroy(background);
1816 const float max_c = 49.34f;
1817 const float min_c = 9.00f;
1818 const float max_h = 0.99f;
1819 const float min_h = 0.26f;
1821 const float n_w_x = min_c * cosf(max_h);
1822 const float n_w_y = min_c * sinf(max_h);
1823 const float n_e_x = max_c * cosf(max_h);
1824 const float n_e_y = max_c * sinf(max_h);
1825 const float s_e_x = max_c * cosf(min_h);
1826 const float s_e_y = max_c * sinf(min_h);
1827 const float s_w_x = min_c * cosf(min_h);
1828 const float s_w_y = min_c * sinf(min_h);
1839 cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);
1854 gboolean size_match = (
d->cache.width ==
width &&
d->cache.height ==
height);
1855 gboolean zoom_match = (
d->cache.zoom ==
d->zoom);
1856 gboolean view_match = (
d->cache.view ==
view);
1858 return !(hash_match && size_match && zoom_match && view_match && has_surface);
1868 cairo_set_source_surface(crf,
d->cst, 0, 0);
1876 GtkAllocation allocation;
1877 gtk_widget_get_allocation(
d->scope_draw, &allocation);
1878 *
width = allocation.width;
1879 *
height = allocation.height;
1912 PangoLayout *layout = pango_cairo_create_layout(cr);
1914 pango_font_description_set_absolute_size(desc,
DT_PIXEL_APPLY_DPI(12.) * PANGO_SCALE);
1915 pango_layout_set_font_description(layout, desc);
1916 pango_layout_set_text(layout, _(
"Restricted"), -1);
1919 PangoRectangle logical;
1920 pango_layout_get_pixel_extents(layout, &ink, &logical);
1924 const double label_x = padding;
1925 const double label_y =
MAX(padding,
height - logical.height - 2. * text_padding - padding);
1928 cairo_move_to(cr, label_x + text_padding - ink.x, label_y + text_padding);
1929 pango_cairo_show_layout(cr, layout);
1931 pango_font_description_free(desc);
1932 g_object_unref(layout);
1951 d->cache.zoom =
d->zoom;
1952 d->cache.view =
d->scope;
1954 cairo_t *cr = cairo_create(
d->cst);
1957 gtk_render_background(gtk_widget_get_style_context(
d->scope_draw), cr, 0, 0,
width,
height);
1958 cairo_set_line_width(cr, 1.);
2006 if(
d->cst && cairo_surface_get_reference_count(
d->cst) > 0) cairo_surface_destroy(
d->cst);
2007 if(
d->cst && cairo_surface_get_reference_count(
d->cst) == 0)
d->cst = NULL;
2036 dt_iop_module_t *
const module = dt_iop_get_module_by_op_priority(dev->iop, op, 0);
2042 if(!strcmp(op,
"gamma"))
2073 double *
const iop_order,
int *
const direction)
2080 dt_iop_module_t *
const module = dt_iop_get_module_by_op_priority(dev->iop, op, 0);
2089 *iop_order =
module->iop_order;
2092 if(!strcmp(op,
"gamma"))
2098 *roi = previous_piece->
roi_out;
2099 *dsc = previous_piece->
dsc_out;
2124 const float *
const pixel =
data;
2128 .bpp = 4 *
sizeof(float),
2134 .width = (int)backbuf->
width,
2135 .height = (
int)backbuf->
height,
2138 double iop_order = 0.0;
2161 direction, fbox, 2);
2170 box[0] = fminf(fbox[0], fbox[2]);
2171 box[1] = fminf(fbox[1], fbox[3]);
2172 box[2] = fmaxf(fbox[0], fbox[2]);
2173 box[3] = fmaxf(fbox[1], fbox[3]);
2232 samples = g_slist_next(samples);
2253 samples = g_slist_next(samples))
2261 gtk_widget_set_sensitive(GTK_WIDGET(
d->add_sample_button),
2326 if(
d->refresh_idle_source != 0)
2328 g_source_remove(
d->refresh_idle_source);
2329 d->refresh_idle_source = 0;
2379 const float new_value = 4.f * delta_y +
d->zoom;
2381 if(new_value < 512.f && new_value > 32.f)
2383 d->zoom = new_value;
2397 return gtk_widget_get_allocated_height(
d->scope_draw);
2415 window_height * 3 / 4));
2416 d->scope_height = CLAMP(requested_size, min_height, max_height);
2418 gtk_widget_set_size_request(
d->scope_draw, -1,
d->scope_height);
2419 gtk_widget_queue_resize(
d->scope_draw);
2423 return d->scope_height;
2429 if(!strcmp(
d->op,
"demosaic"))
2431 d->op =
"initialscale";
2435 d->zoom = fminf(fmaxf(
dt_conf_get_float(
"plugin/darkroom/histogram/zoom"), 32.f), 252.f);
2448 const guint
width = gtk_widget_get_allocated_width(widget);
2449 const guint
height = gtk_widget_get_allocated_height(widget);
2459 const int icon_width =
width - 2 * border;
2460 const int icon_height =
height - 2 * border;
2461 if(icon_width > 0 && icon_height > 0)
2464 gtk_style_context_get_color(gtk_widget_get_style_context(widget), gtk_widget_get_state_flags(widget), &fg_color);
2466 gdk_cairo_set_source_rgba(cr, &fg_color);
2487 char text[128] = { 0 };
2497 snprintf(text,
sizeof(text),
"%6.02f %6.02f %6.02f",
2498 CLAMP(sample->
lab[statistic][0], .0f, 100.0f), sample->
lab[statistic][1], sample->
lab[statistic][2]);
2502 dt_Lab_2_LCH(sample->
lab[statistic], alt);
2503 snprintf(text,
sizeof(text),
"%6.02f %6.02f %6.02f", CLAMP(alt[0], .0f, 100.0f), alt[1], alt[2] * 360.f);
2507 dt_RGB_2_HSL(sample->
scope[statistic], alt);
2508 snprintf(text,
sizeof(text),
"%6.02f %6.02f %6.02f", alt[0] * 360.f, alt[1] * 100.f, alt[2] * 100.f);
2512 dt_RGB_2_HSV(sample->
scope[statistic], alt);
2513 snprintf(text,
sizeof(text),
"%6.02f %6.02f %6.02f", alt[0] * 360.f, alt[1] * 100.f, alt[2] * 100.f);
2518 snprintf(text,
sizeof(text),
"\342\227\216");
2522 if(g_strcmp0(gtk_label_get_text(GTK_LABEL(sample->
output_label)), text))
2523 gtk_label_set_text(GTK_LABEL(sample->
output_label), text);
2535 const gboolean picker_active = gtk_toggle_button_get_active(button);
2536 gtk_widget_set_sensitive(GTK_WIDGET(
d->add_sample_button), picker_active);
2538 const gboolean restrict_active = !
IS_NULL_PTR(
d->restrict_button)
2539 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->restrict_button));
2574 gchar **sample_parts = g_malloc0_n(14,
sizeof(
char*));
2576 sample_parts[3] = g_strdup_printf(
"%22s(0x%02X%02X%02X)\n<big><b>%14s</b></big>",
" ",
2578 CLAMP(sample->
label_rgb[2], 0, 255), _(
"RGB"));
2579 sample_parts[7] = g_strdup_printf(
"\n<big><b>%14s</b></big>", _(
"Lab"));
2583 sample_parts[
i] = g_strdup_printf(
"<span background='#%02X%02X%02X'>%32s</span>",
2584 (
int)roundf(CLAMP(sample->
display[
i][0], 0.f, 1.f) * 255.f),
2585 (
int)roundf(CLAMP(sample->
display[
i][1], 0.f, 1.f) * 255.f),
2586 (
int)roundf(CLAMP(sample->
display[
i][2], 0.f, 1.f) * 255.f),
" ");
2588 sample_parts[
i + 4] = g_strdup_printf(
"<span foreground='#FF7F7F'>%6d</span> "
2589 "<span foreground='#7FFF7F'>%6d</span> "
2590 "<span foreground='#7F7FFF'>%6d</span> %s",
2591 (
int)roundf(sample->
scope[
i][0] * 255.f),
2592 (
int)roundf(sample->
scope[
i][1] * 255.f),
2593 (
int)roundf(sample->
scope[
i][2] * 255.f),
2596 sample_parts[
i + 8] = g_strdup_printf(
"%6.02f %6.02f %6.02f %s",
2597 sample->
lab[
i][0], sample->
lab[
i][1], sample->
lab[
i][2],
2603 sample_parts[11] = g_strdup_printf(
"\n<big><b>%14s</b></big>", _(
"color"));
2606 gchar *tooltip_text = g_strjoinv(
"\n", sample_parts);
2607 g_strfreev(sample_parts);
2609 gtk_tooltip_set_markup(
tooltip, tooltip_text);
2636 gtk_label_set_attributes(GTK_LABEL(widget), NULL);
2638 PangoStretch stretch = PANGO_STRETCH_NORMAL;
2640 while(gtk_widget_get_preferred_width(widget, NULL, &label_width),
2641 label_width > allocation->width && stretch != PANGO_STRETCH_ULTRA_CONDENSED)
2645 PangoAttrList *attrlist = pango_attr_list_new();
2646 PangoAttribute *attr = pango_attr_stretch_new(stretch);
2647 pango_attr_list_insert(attrlist, attr);
2648 gtk_label_set_attributes(GTK_LABEL(widget), attrlist);
2649 pango_attr_list_unref(attrlist);
2666 if(event->crossing.detail == GDK_NOTIFY_INFERIOR)
return FALSE;
2700 if(event->button == 1)
2703 gtk_widget_queue_draw(widget);
2705 else if(event->button == 3)
2716 float point[2] = { 0.0f };
2748 sample->
container = gtk_event_box_new();
2749 gtk_widget_add_events(sample->
container, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
2757 gtk_widget_add_events(sample->
color_patch, GDK_BUTTON_PRESS_MASK);
2758 gtk_widget_set_tooltip_text(sample->
color_patch, _(
"hover to highlight sample on canvas,\n"
2759 "click to lock sample,\n"
2760 "right-click to load sample area into active color picker"));
2765 gtk_widget_set_name(color_patch_wrapper,
"live-sample");
2771 gtk_label_set_ellipsize(GTK_LABEL(sample->
output_label), PANGO_ELLIPSIZE_START);
2779 g_signal_connect(G_OBJECT(delete_button),
"clicked", G_CALLBACK(
_remove_sample_cb), sample);
2799 dt_conf_set_bool(
"ui_last/colorpicker_display_samples", gtk_toggle_button_get_active(button));
2808 const gboolean restrict_active = gtk_toggle_button_get_active(button);
2809 const gboolean picker_active = !
IS_NULL_PTR(
d->picker_button)
2810 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->picker_button));
2811 dt_conf_set_bool(
"ui_last/colorpicker_restrict_histogram", restrict_active);
2832 for(
int i = 0;
i < 3;
i++)
2836 primary_sample->
display[s][
i] = 0.f;
2837 primary_sample->
scope[s][
i] = 0.f;
2838 primary_sample->
lab[s][
i] = 0.f;
2842 primary_sample->
swatch.red = primary_sample->
swatch.green
2843 = primary_sample->
swatch.blue = 0.0;
2854 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->display_samples_check_box)))
2855 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
d->display_samples_check_box),
FALSE);
2867 if(!gtk_check_menu_item_get_active(item))
return;
2869 _set_stage(self, GPOINTER_TO_INT(user_data));
2874 if(!gtk_check_menu_item_get_active(item))
return;
2884 GtkWidget *mi_stage = gtk_menu_item_new_with_label(_(
"Show data from"));
2885 GtkWidget *submenu_stage = gtk_menu_new();
2886 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_stage), submenu_stage);
2888 const char *stage_labels[] = { N_(
"Raw image"), N_(
"Output color profile"), N_(
"Final display"), NULL };
2890 GSList *stage_group = NULL;
2891 for(
int i = 0; stage_labels[
i];
i++)
2893 GtkWidget *item = gtk_radio_menu_item_new_with_label(stage_group, _(stage_labels[
i]));
2894 stage_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
2895 if(
i == current_stage) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
TRUE);
2896 g_object_set_data(G_OBJECT(item),
"self", self);
2897 g_signal_connect(G_OBJECT(item),
"toggled", G_CALLBACK(
_pref_stage_toggled), GINT_TO_POINTER(
i));
2898 gtk_menu_shell_append(GTK_MENU_SHELL(submenu_stage), item);
2900 gtk_widget_show_all(mi_stage);
2901 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_stage);
2904 GtkWidget *mi_display = gtk_menu_item_new_with_label(_(
"Display"));
2905 GtkWidget *submenu_display = gtk_menu_new();
2906 gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi_display), submenu_display);
2908 const char *display_labels[] = {
2909 N_(
"Histogram"), N_(
"Waveform (horizontal)"), N_(
"Waveform (vertical)"),
2910 N_(
"Parade (horizontal)"), N_(
"Parade (vertical)"), N_(
"Vectorscope"), NULL
2912 const gboolean vectorscope_ok = strcmp(
d->op,
"initialscale");
2913 GSList *display_group = NULL;
2914 for(
int i = 0; display_labels[
i];
i++)
2916 GtkWidget *item = gtk_radio_menu_item_new_with_label(display_group, _(display_labels[
i]));
2917 display_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
2919 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
TRUE);
2921 gtk_widget_set_sensitive(item, vectorscope_ok);
2922 g_object_set_data(G_OBJECT(item),
"self", self);
2924 gtk_menu_shell_append(GTK_MENU_SHELL(submenu_display), item);
2926 gtk_widget_show_all(mi_display);
2927 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_display);
2935 self->
data = (
void *)
d;
2939 d->refresh_idle_source = 0;
2942 d->scope_draw = gtk_drawing_area_new();
2947 d->scope_height = CLAMP(
d->scope_height,
2950 gtk_widget_set_size_request(
d->scope_draw, -1,
d->scope_height);
2951 g_signal_connect(G_OBJECT(
d->scope_draw),
"draw", G_CALLBACK(
_draw_callback),
d);
2953 g_signal_connect(G_OBJECT(
d->scope_draw),
"size-allocate", G_CALLBACK(
_resize_callback),
d);
2957 GtkWidget *scope_overlay = gtk_overlay_new();
2958 gtk_container_add(GTK_CONTAINER(scope_overlay),
d->scope_draw);
2974 _(
"Drag to resize the scope vertically"),
2977 gtk_overlay_add_overlay(GTK_OVERLAY(scope_overlay),
d->scope_resize_handle);
2981 "plugins/darkroom/colorpicker/show",
2983 GTK_BOX(self->
widget), GTK_PACK_END);
2996 if(g_strcmp0(str, *names) == 0)
3002 if(g_strcmp0(str, *names) == 0)
3007 gtk_widget_set_name(GTK_WIDGET(color_patch_wrapper),
"color-picker-area");
3011 gtk_box_pack_start(GTK_BOX(
d->cs.container), picker_row,
TRUE,
TRUE, 0);
3014 darktable.
bauhaus, NULL, NULL, _(
"select which statistic to show"),
d->statistic,
3018 gtk_widget_set_valign(
d->statistic_selector, GTK_ALIGN_CENTER);
3019 gtk_box_pack_start(GTK_BOX(picker_row),
d->statistic_selector,
TRUE,
TRUE, 0);
3026 gtk_widget_set_valign(
d->color_mode_selector, GTK_ALIGN_CENTER);
3027 gtk_box_pack_start(GTK_BOX(picker_row),
d->color_mode_selector,
TRUE,
TRUE, 0);
3030 gtk_widget_set_tooltip_text(
d->picker_button, _(
"turn on color picker\nctrl+click or right-click to select an area"));
3031 gtk_widget_set_name(GTK_WIDGET(
d->picker_button),
"color-picker-button");
3035 GtkWidget *sample_row_events = gtk_event_box_new();
3036 gtk_widget_add_events(sample_row_events, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
3041 gtk_box_pack_start(GTK_BOX(
d->cs.container), sample_row_events,
TRUE,
TRUE, 0);
3044 gtk_container_add(GTK_CONTAINER(sample_row_events), sample_row);
3051 gtk_widget_set_name(color_patch_wrapper,
"live-sample");
3053 gtk_box_pack_start(GTK_BOX(sample_row), color_patch_wrapper,
TRUE,
TRUE, 0);
3056 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
3057 gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_START);
3058 gtk_label_set_selectable(GTK_LABEL(label),
TRUE);
3060 gtk_widget_set_has_tooltip(label,
TRUE);
3065 gtk_box_pack_start(GTK_BOX(sample_row), label,
TRUE,
TRUE, 0);
3068 gtk_widget_set_sensitive(GTK_WIDGET(
d->add_sample_button),
FALSE);
3069 g_signal_connect(G_OBJECT(
d->add_sample_button),
"clicked", G_CALLBACK(
_add_sample), self);
3070 gtk_box_pack_end(GTK_BOX(sample_row),
d->add_sample_button,
FALSE,
FALSE, 0);
3074 gtk_box_pack_start(GTK_BOX(
d->cs.container), label,
TRUE,
TRUE, 0);
3077 gtk_box_pack_start(GTK_BOX(
d->cs.container),
3078 dt_ui_scroll_wrap(
d->samples_container, 1,
"plugins/darkroom/colorpicker/windowheight",
3081 d->display_samples_check_box = gtk_check_button_new_with_label(_(
"Display samples on image"));
3082 gtk_label_set_ellipsize(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
d->display_samples_check_box))),
3083 PANGO_ELLIPSIZE_MIDDLE);
3084 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
d->display_samples_check_box),
3086 g_signal_connect(G_OBJECT(
d->display_samples_check_box),
"toggled",
3088 gtk_box_pack_start(GTK_BOX(
d->cs.container),
d->display_samples_check_box,
TRUE,
TRUE, 0);
3090 d->restrict_button = gtk_check_button_new_with_label(_(
"Restrict scope to selection"));
3091 gtk_label_set_ellipsize(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
d->restrict_button))), PANGO_ELLIPSIZE_MIDDLE);
3092 gboolean restrict_histogram =
dt_conf_get_bool(
"ui_last/colorpicker_restrict_histogram");
3093 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
d->restrict_button), restrict_histogram);
3095 gtk_box_pack_start(GTK_BOX(
d->cs.container),
d->restrict_button,
TRUE,
TRUE, 0);
3110 if(
d->refresh_idle_source != 0)
3112 g_source_remove(
d->refresh_idle_source);
3113 d->refresh_idle_source = 0;
3115 if(
d->pending_hashes) g_array_free(
d->pending_hashes,
TRUE);
static void error(char *msg)
GtkWidget * dt_bauhaus_combobox_new_full(dt_bauhaus_t *bh, dt_gui_module_t *self, const char *label, const char *tip, int pos, GtkCallback callback, gpointer data, const char **texts)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_combobox_set_entries_ellipsis(GtkWidget *widget, PangoEllipsizeMode ellipis)
GtkWidget * dt_bauhaus_resize_handle_new(GtkOrientation orientation, gboolean invert, const char *tooltip, dt_bauhaus_resize_handle_get_size_f get_size, dt_bauhaus_resize_handle_resize_f resize, gpointer user_data)
Create a themed handle widget driving one-dimensional resize gestures.
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
static void set_color(cairo_t *cr, GdkRGBA color)
void dt_color_picker_helper(const dt_iop_buffer_dsc_t *dsc, const float *const pixel, const dt_iop_roi_t *roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t image_cst, const dt_iop_colorspace_type_t picker_cst, const dt_iop_order_iccprofile_info_t *const profile)
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)
@ DT_COLOR_PICKER_POINT_AREA
const char * Lch_to_color_name(dt_aligned_pixel_t color)
dt_lib_colorpicker_statistic_t
@ DT_LIB_COLORPICKER_STATISTIC_MAX
@ DT_LIB_COLORPICKER_STATISTIC_N
@ DT_LIB_COLORPICKER_STATISTIC_MIN
@ DT_LIB_COLORPICKER_STATISTIC_MEAN
@ DT_LIB_COLORPICKER_SIZE_POINT
@ DT_LIB_COLORPICKER_SIZE_BOX
static float4 dt_xyY_to_XYZ(const float4 xyY)
static float4 dt_XYZ_to_xyY(const float4 XYZ)
static dt_aligned_pixel_t xyY
dt_apply_transposed_color_matrix(XYZ, xyz_to_srgb_matrix_transposed, sRGB)
static const float const float const float min
static dt_aligned_pixel_t XYZ
static dt_aligned_pixel_t XYZ_D50
static dt_aligned_pixel_t Luv
static dt_aligned_pixel_t RGB
static dt_aligned_pixel_t Lch
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_histogram_max_helper(const dt_dev_histogram_stats_t *const histogram_stats, const dt_iop_colorspace_type_t cst, const dt_iop_colorspace_type_t cst_to, uint32_t **histogram, uint32_t *histogram_max)
void dt_histogram_helper(dt_dev_histogram_collection_params_t *histogram_params, dt_dev_histogram_stats_t *histogram_stats, const dt_iop_colorspace_type_t cst, const dt_iop_colorspace_type_t cst_to, const void *pixel, uint32_t **histogram, const int compensate_middle_grey, const dt_iop_order_iccprofile_info_t *const profile_info)
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
int dt_conf_key_exists(const char *key)
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
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...
uint32_t view(const dt_view_t *self)
void * dt_alloc_align(size_t size)
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
#define for_each_channel(_var,...)
float dt_boundingbox_t[4]
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define DT_MODULE(MODVER)
static void dt_get_times(dt_times_t *t)
#define dt_pixelpipe_cache_free_align(mem)
#define for_four_channels(_var,...)
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
#define __OMP_FOR_SIMD__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
const dt_dev_pixelpipe_iop_t * dt_dev_pixelpipe_get_module_piece(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module)
void dt_dev_pixelpipe_cache_wait_cleanup(dt_dev_pixelpipe_cache_wait_t *wait, const char *reason)
Cancel one pending GUI cache wait request and clear its runtime state.
const dt_dev_pixelpipe_iop_t * dt_dev_pixelpipe_get_prev_enabled_piece(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void dt_dev_pixelpipe_cache_wait_set_owner(dt_dev_pixelpipe_cache_wait_t *wait, const char *owner_tag, gpointer owner_object)
Attach debug ownership metadata to one cache wait request.
gboolean dt_dev_pixelpipe_cache_peek_gui(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, void **data, dt_pixel_cache_entry_t **cache_entry, dt_dev_pixelpipe_cache_wait_t *wait, dt_dev_pixelpipe_cache_ready_callback_t restart, gpointer restart_data)
#define dt_dev_pixelpipe_update_history_preview(dev)
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
void dt_dev_coordinates_raw_norm_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
void dt_dev_set_backbuf(dt_backbuf_t *backbuf, const int width, const int height, const size_t bpp, const int64_t hash, const int64_t history_hash)
int dt_dev_distort_backtransform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
@ DT_DEV_TRANSFORM_DIR_FORW_INCL
@ DT_DEV_TRANSFORM_DIR_FORW_EXCL
static void dt_draw_line(cairo_t *cr, float left, float top, float right, float bottom)
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_histogram_8(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const gboolean linear)
void dtgtk_cairo_paint_remove(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_lock(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_square_plus(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
const dt_collection_filter_flag_t colors[6]
gboolean dt_gui_get_scroll_unit_deltas(const GdkEventScroll *event, int *delta_x, int *delta_y)
void dt_gui_new_collapsible_section(dt_gui_collapsible_section_t *cs, const char *confname, const char *label, GtkBox *parent, GtkPackType pack)
Create a collapsible section and pack it into the parent box.
GtkWidget * dt_ui_scroll_wrap(GtkWidget *w, gint min_size, char *config_str, dt_ui_resize_mode_t mode)
Wrap a scrollable content widget in a recessed, vertically resizable scrolled window.
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
static GtkWidget * dt_ui_section_label_new(const gchar *str)
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
dt_iop_module_t * dt_iop_get_module_by_op_priority(GList *modules, const char *operation, const int multi_priority)
static gboolean dt_iop_colorspace_is_rgb(const dt_iop_colorspace_type_t cst)
static void dt_iop_gui_enter_critical_section(dt_iop_module_t *const module) ACQUIRE(&module -> gui_lock)
static void dt_iop_gui_leave_critical_section(dt_iop_module_t *const module) RELEASE(&module -> gui_lock)
static void gui_init(dt_lib_import_t *d)
void dt_ioppr_transform_image_colorspace(struct dt_iop_module_t *self, const float *const image_in, float *const image_out, const int width, const int height, const int cst_from, const int cst_to, int *converted_cst, const dt_iop_order_iccprofile_info_t *const profile_info)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
void dt_ioppr_transform_image_colorspace_rgb(const float *const restrict image_in, float *const restrict image_out, const int width, const int height, const dt_iop_order_iccprofile_info_t *const profile_info_from, const dt_iop_order_iccprofile_info_t *const profile_info_to, const char *message)
static dt_aligned_pixel_t rgb_out
void dt_lib_colorpicker_set_box_area(dt_lib_t *lib, const dt_boundingbox_t box)
void dt_lib_colorpicker_set_point(dt_lib_t *lib, const float pos[2])
dt_lib_colorpicker_model_t
@ DT_LIB_COLORPICKER_MODEL_LAB
@ DT_LIB_COLORPICKER_MODEL_LCH
@ DT_LIB_COLORPICKER_MODEL_HSL
@ DT_LIB_COLORPICKER_MODEL_RGB
@ DT_LIB_COLORPICKER_MODEL_NONE
@ DT_LIB_COLORPICKER_MODEL_HSV
static void _create_vectorscope_image(const uint32_t *const restrict vectorscope, uint8_t *const restrict image, const uint32_t max_hist, const float zoom)
#define DT_LIB_HISTOGRAM_SCOPE_RESTRICTED_LABEL_OPERATOR
static void _pixelpipe_pick_samples(dt_lib_histogram_t *d)
static void _set_sample_point(dt_lib_module_t *self, const float pos[2])
static void _add_pending_hash(dt_lib_histogram_t *d, const uint64_t hash)
void gui_reset(dt_lib_module_t *self)
static void _bin_pixels_vectorscope_in_roi(const float *const restrict image, uint32_t *const restrict vectorscope, const size_t min_x, const size_t max_x, const size_t min_y, const size_t max_y, const size_t width, const float zoom, dt_lib_histogram_t *d)
#define DT_LIB_HISTOGRAM_SCOPE_MIN_HEIGHT
void _set_params(dt_lib_histogram_t *d)
static dt_backbuf_t * _get_histogram_backbuf(dt_develop_t *dev, const char *op)
const gchar * dt_lib_colorpicker_model_names[]
static void _update_sample_label(dt_lib_module_t *self, dt_colorpicker_sample_t *sample)
static void _refresh_module_histogram(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const float *pixel, dt_iop_module_t *module)
static void _add_sample(GtkButton *widget, dt_lib_module_t *self)
void set_preferences(void *menu, dt_lib_module_t *self)
static gboolean _sample_tooltip_callback(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, const dt_colorpicker_sample_t *sample)
static int _scope_resize_handle_resize(int requested_size, gboolean finished, gpointer user_data)
Apply one vertical size request from the generic Bauhaus resize handle.
static void _process_restricted_text(dt_lib_histogram_t *d, cairo_t *cr, const int height)
Draw the restricted-scope label over the current Cairo surface.
static gboolean _remove_pending_hash(dt_lib_histogram_t *d, const uint64_t hash)
static void _refresh_preview_histograms(dt_develop_t *dev)
static void _clear_histogram_backbuf(dt_backbuf_t *backbuf)
void _scope_pixel_to_xyz(const dt_aligned_pixel_t rgb_in, dt_aligned_pixel_t xyz_out, dt_lib_histogram_t *d)
static gboolean _is_backbuf_ready(dt_lib_histogram_t *d)
Check that the selected histogram backbuffer belongs to the current preview graph.
void _get_allocation_size(dt_lib_histogram_t *d, int *width, int *height)
static gboolean _refresh_global_picker(dt_lib_module_t *self)
#define DT_LIB_HISTOGRAM_SCOPE_SMOOTH_FORCE
static void _display_samples_changed(GtkToggleButton *button, dt_lib_module_t *self)
static void _bin_pixels_waveform_in_roi(const float *const restrict image, uint32_t *const restrict bins, const size_t min_x, const size_t max_x, const size_t min_y, const size_t max_y, const size_t source_width, const size_t source_height, const size_t tone_bins, const size_t raster_extent, const gboolean vertical)
static const dt_dev_pixelpipe_iop_t * _get_backbuf_source_piece(const dt_backbuf_t *backbuf, const char *op)
static void _resize_callback(GtkWidget *widget, GdkRectangle *allocation, dt_lib_histogram_t *d)
#define DT_LIB_HISTOGRAM_SCOPE_DEFAULT_HEIGHT
static gboolean _histogram_refresh_idle(gpointer user_data)
void _scope_pixel_to_display_rgb(const dt_aligned_pixel_t rgb_in, dt_aligned_pixel_t rgb_out, dt_lib_histogram_t *d)
static void _clear_pending_hashes(dt_lib_histogram_t *d)
static void _redraw_scopes(dt_lib_histogram_t *d)
static int _scope_resize_handle_get_size(gpointer user_data)
static void _color_mode_changed(GtkWidget *widget, dt_lib_module_t *self)
void gui_cleanup(dt_lib_module_t *self)
static void _bin_pickers_waveforms(const float *const restrict image, uint32_t *const restrict bins, const size_t width, const size_t height, const size_t tone_bins, const size_t raster_extent, const gboolean vertical, dt_colorpicker_sample_t *sample)
void _backbuf_int_to_op(const int value, dt_lib_histogram_t *d)
static gboolean _refresh_global_histogram_backbuf_for_hash(dt_develop_t *dev, const char *op, const uint64_t expected_hash)
const gchar * dt_lib_colorpicker_statistic_names[]
static void _paint_waveform(cairo_t *cr, uint8_t *const restrict image, const int width, const int height, const size_t img_width, const size_t img_height, const size_t tone_bins, const gboolean vertical)
static void _sample_raw_point_to_image_norm(const dt_colorpicker_sample_t *const sample, float point[2])
static void _create_waveform_image(const uint32_t *const restrict bins, uint8_t *const restrict image, const uint32_t max_hist, const size_t width, const size_t height)
static uint64_t _get_live_histogram_hash(const char *op)
static void _sample_raw_box_to_image_norm(const dt_colorpicker_sample_t *const sample, float box[4])
static void _sync_pending_histogram_hashes(dt_lib_module_t *self)
static gboolean _is_restricted(dt_lib_histogram_t *d)
int _backbuf_op_to_int(dt_lib_histogram_t *d)
static dt_histogram_preview_refresh_state_t _preview_refresh_state
static gboolean _area_scrolled_callback(GtkWidget *widget, GdkEventScroll *event, dt_lib_histogram_t *d)
#define DT_LIB_HISTOGRAM_SCOPE_MIN_VALUE
static void _lib_histogram_history_resync_callback(gpointer instance, dt_lib_module_t *self)
static void _statistic_changed(GtkWidget *widget, dt_lib_module_t *self)
gboolean _trigger_recompute(dt_lib_histogram_t *d)
static void _preview_cacheline_ready_callback(gpointer instance, const guint64 hash, gpointer user_data)
static void _bin_pickers_vectorscope(const float *const restrict image, uint32_t *const restrict vectorscope, const size_t width, const size_t height, const float zoom, dt_lib_histogram_t *d, const dt_colorpicker_sample_t *const sample)
static void _destroy_surface(dt_lib_histogram_t *d)
static gboolean _sample_enter_callback(GtkWidget *widget, GdkEvent *event, dt_colorpicker_sample_t *sample)
static void _remove_sample_cb(GtkButton *widget, dt_colorpicker_sample_t *sample)
gboolean _needs_recompute(dt_lib_histogram_t *d, const int width, const int height)
static void _pref_stage_toggled(GtkCheckMenuItem *item, gpointer user_data)
static void _update_everything(dt_lib_module_t *self)
static gboolean _has_pending_hash(const dt_lib_histogram_t *d, const uint64_t hash)
static void _pref_display_toggled(GtkCheckMenuItem *item, gpointer user_data)
uint32_t container(dt_lib_module_t *self)
#define DT_LIB_HISTOGRAM_SCOPE_HEIGHT_CONF
static void _label_size_allocate_callback(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data)
static gboolean _sample_draw_callback(GtkWidget *widget, cairo_t *cr, dt_colorpicker_sample_t *sample)
static void _process_vectorscope(dt_backbuf_t *backbuf, const char *op, cairo_t *cr, const int width, const int height, const float zoom, dt_lib_histogram_t *d)
static void _set_scope(dt_lib_module_t *self, dt_lib_histogram_scope_type_t scope)
static void _bin_pixels_histogram_in_roi(const float *const restrict image, uint32_t *const restrict bins, const size_t min_x, const size_t max_x, const size_t min_y, const size_t max_y, const size_t width)
static void _preview_history_resync_callback(gpointer instance, gpointer user_data)
static void _schedule_histogram_refresh(dt_lib_module_t *self)
static void _restrict_histogram_changed(GtkToggleButton *button, dt_lib_module_t *self)
static void _update_picker_output(dt_lib_module_t *self)
void view_leave(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
static void _set_sample_box_area(dt_lib_module_t *self, const dt_boundingbox_t box)
void view_enter(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
static void _histogram_restart_scope_cache_wait(gpointer user_data)
Retry a scope render after its source cacheline has been published.
static float _Luv_to_vectorscope_coord_zoom(const float value, const float zoom)
static void _bin_pickers_histogram(const float *const restrict image, const size_t width, const size_t height, uint32_t *bins, dt_colorpicker_sample_t *sample)
const char ** views(dt_lib_module_t *self)
uint32_t _find_max_histogram(const uint32_t *const restrict bins, const size_t binning_size)
static gboolean _sample_leave_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
int expandable(dt_lib_module_t *self)
static gboolean _draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data)
static void _bin_pixels_waveform(const float *const restrict image, uint32_t *const restrict bins, const size_t width, const size_t height, const size_t binning_size, const size_t tone_bins, const size_t raster_extent, const gboolean vertical, const gboolean restricted)
static gboolean _live_sample_button(GtkWidget *widget, GdkEventButton *event, dt_colorpicker_sample_t *sample)
#define DT_LIB_HISTOGRAM_SCOPE_SMOOTH_SPATIAL_PASSES
#define DT_LIB_HISTOGRAM_SCOPE_SMOOTH_TONE_PASSES
static void _pixelpipe_pick_from_image(const dt_backbuf_t *const backbuf, dt_colorpicker_sample_t *const sample, dt_lib_histogram_t *d, const char *op)
static float _vectorscope_coord_zoom_to_Luv(const float value, const float zoom)
static void _remove_sample(dt_colorpicker_sample_t *sample)
static void _lib_histogram_cacheline_ready_callback(gpointer instance, const guint64 hash, dt_lib_module_t *self)
#define DT_LIB_HISTOGRAM_SCOPE_MAX_HEIGHT
static gboolean _resolve_backbuf_sampling_source(const char *const op, const dt_backbuf_t *const backbuf, dt_iop_roi_t *const roi, dt_iop_buffer_dsc_t *const dsc, double *const iop_order, int *const direction)
Resolve the live preview-stage geometry behind one global histogram backbuffer.
static gboolean _refresh_preview_module_histogram_for_hash(dt_develop_t *dev, dt_iop_module_t *module, const uint64_t expected_hash)
static void _process_histogram(dt_backbuf_t *backbuf, const char *op, cairo_t *cr, const int width, const int height, dt_lib_histogram_t *d)
gboolean _redraw_surface(dt_lib_histogram_t *d)
static void _histogram_restart_cache_wait(gpointer user_data)
static void _set_stage(dt_lib_module_t *self, int value)
dt_lib_histogram_scope_type_t
@ DT_LIB_HISTOGRAM_SCOPE_PARADE_VERTICAL
@ DT_LIB_HISTOGRAM_SCOPE_WAVEFORM_HORIZONTAL
@ DT_LIB_HISTOGRAM_SCOPE_HISTOGRAM
@ DT_LIB_HISTOGRAM_SCOPE_PARADE_HORIZONTAL
@ DT_LIB_HISTOGRAM_SCOPE_WAVEFORM_VERTICAL
@ DT_LIB_HISTOGRAM_SCOPE_VECTORSCOPE
@ DT_LIB_HISTOGRAM_SCOPE_N
static void _clear_pending_preview_histograms(void)
static void _picker_button_toggled(GtkToggleButton *button, dt_lib_histogram_t *d)
static void _reset_cache(dt_lib_histogram_t *d)
static void _bin_vectorscope(const float *const restrict image, uint32_t *const vectorscope, const size_t width, const size_t height, const float zoom, dt_lib_histogram_t *d)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define CLAMPF(a, mn, mx)
float dt_aligned_pixel_t[4]
void dt_dev_pixelpipe_cache_ref_count_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
void dt_dev_pixelpipe_cache_unref_hash(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash)
Find the entry matching hash, and decrease its ref_count if found.
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
Pixelpipe cache for storing intermediate results in the pixelpipe.
#define DT_PIXELPIPE_CACHE_HASH_INVALID
static uint64_t dt_dev_backbuf_get_hash(const dt_backbuf_t *backbuf)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ DT_SIGNAL_HISTORY_RESYNC
This signal is raised once darkroom history has been resynchronized into all live pipelines....
@ DT_SIGNAL_CACHELINE_READY
This signal is raised when one cacheline write lock is released. 1 : uint64_t cacheline hash no retur...
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
unsigned __int64 uint64_t
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
struct dt_gui_gtk_t * gui
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
GdkRGBA graph_scope_restricted
PangoFontDescription * pango_font_desc
lib_colorpicker_sample_statistics display
dt_lib_colorpicker_size_t size
lib_colorpicker_sample_statistics scope
char backbuf_op[32]
Global histogram stage backing this live sample.
lib_colorpicker_sample_statistics lab
const struct dt_histogram_roi_t * roi
dt_iop_buffer_dsc_t dsc_out
dt_dev_request_flags_t request_histogram
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_histogram_collection_params_t histogram_params
struct dt_iop_order_iccprofile_info_t * input_profile_info
struct dt_iop_order_iccprofile_info_t * output_profile_info
gboolean gui_observable_source
struct dt_develop_t::@19 color_picker
Authoritative darkroom color-picker state.
struct dt_colorpicker_sample_t * primary_sample
dt_backbuf_t display_histogram
dt_backbuf_t output_histogram
gboolean(* refresh_global_picker)(struct dt_lib_module_t *self)
gboolean restrict_histogram
struct dt_dev_pixelpipe_t * preview_pipe
struct dt_iop_module_t *struct dt_iop_color_picker_t * picker
dt_backbuf_t raw_histogram
struct dt_colorpicker_sample_t * selected_sample
struct dt_lib_module_t * histogram_module
dt_iop_module_t *uint64_t hash
uint64_t initialscale_hash
GList * module_histograms
dt_iop_buffer_type_t datatype
dt_dev_histogram_stats_t histogram_stats
uint32_t histogram_max[4]
int histogram_middle_grey
dt_iop_colorspace_type_t histogram_cst
dt_colormatrix_t matrix_out_transposed
dt_colormatrix_t matrix_in_transposed
Region of interest passed through the pixelpipe.
dt_lib_histogram_scope_type_t view
GtkWidget * statistic_selector
dt_lib_colorpicker_model_t model
dt_lib_colorpicker_statistic_t statistic
dt_dev_pixelpipe_cache_wait_t scope_wait
dt_lib_histogram_cache_t cache
GtkWidget * samples_container
dt_dev_pixelpipe_cache_wait_t module_wait
GtkWidget * color_mode_selector
GtkWidget * add_sample_button
dt_lib_histogram_scope_type_t scope
GtkWidget * scope_resize_handle
GtkWidget * display_samples_check_box
dt_dev_pixelpipe_cache_wait_t picker_wait
guint refresh_idle_source
GtkWidget * restrict_button
GtkWidget * picker_button
struct dt_lib_module_t *GtkWidget * scope_draw
dt_gui_collapsible_section_t cs
typedef double((*spd)(unsigned long int wavelength, double TempK))
@ DT_UI_CONTAINER_PANEL_LEFT_CENTER