73#define DT_IOP_LUT3D_MAX_PATHNAME 512
74#define DT_IOP_LUT3D_MAX_LUTNAME 128
75#define DT_IOP_LUT3D_CLUT_LEVEL 48
76#define DT_IOP_LUT3D_MAX_KEYPOINTS 2048
115 gulong lutname_handler_id;
144void lut3d_decompress_clut(
const unsigned char *
const input_keypoints,
const unsigned int nb_input_keypoints,
145 const unsigned int output_resolution,
float *
const output_clut_data,
146 const char *
const filename);
148unsigned int lut3d_get_cached_clut(
float *
const output_clut_data,
const unsigned int output_resolution,
149 const char *
const filename);
151gboolean
lut3d_read_gmz(
int *
const nb_keypoints,
unsigned char *
const keypoints,
const char *
const filename,
152 int *
const nb_lut,
void *
g,
const char *
const lutname,
const gboolean newlutname);
164 _(
"corrective or creative"),
165 _(
"linear, RGB, display-referred"),
166 _(
"defined by profile, RGB"),
167 _(
"linear or non-linear, RGB, display-referred"));
186 const int new_version)
188 if(old_version == 1 && new_version == 3)
190 typedef struct dt_iop_lut3d_params_v1_t
195 } dt_iop_lut3d_params_v1_t;
197 dt_iop_lut3d_params_v1_t *o = (dt_iop_lut3d_params_v1_t *)old_params;
199 g_strlcpy(
n->filepath, o->filepath,
sizeof(
n->filepath));
200 n->colorspace = o->colorspace;
201 n->interpolation = o->interpolation;
203 memset(&
n->c_clut, 0,
sizeof(
n->c_clut));
204 memset(&
n->lutname, 0,
sizeof(
n->lutname));
207 if(old_version == 2 && new_version == 3)
209 typedef struct dt_iop_lut3d_params_v2_t
217 uint32_t gmic_version;
218 } dt_iop_lut3d_params_v2_t;
220 dt_iop_lut3d_params_v2_t *o = (dt_iop_lut3d_params_v2_t *)old_params;
230 char *cache_dir = g_build_filename(g_get_user_cache_dir(),
"gmic", NULL);
231 char *cache_file = g_build_filename(cache_dir, lutname, NULL);
239uint8_t calculate_clut_compressed(
dt_iop_lut3d_params_t *
const p,
const char *
const filepath,
float **clut)
248 buf_size_lut = (size_t)(level * level * level * 3);
252 fprintf(stderr,
"[lut3d] error allocating buffer for gmz lut\n");
261 char *c_clut =
p->c_clut;
264 level, lclut, cache_filename);
278 fprintf(stderr,
"[lut3d] invalid png file %s\n", filepath);
286 fprintf(stderr,
"[lut3d] png bit-depth %d not supported\n", png.
bit_depth);
295 while(level * level * level < png.
width) ++level;
297 if(level * level * level != png.
width)
300 fprintf(stderr,
"[lut3d] invalid level in png file %d %d\n", level, png.
width);
305 fprintf(stderr,
"[lut3d] this Ansel build is not compatible with compressed clut\n");
306 dt_control_log(_(
"this Ansel build is not compatible with compressed clut"));
310 fprintf(stderr,
"[lut3d] invalid level in png file %d %d\n", level, png.
width);
322 fprintf(stderr,
"[lut3d] error - LUT 3D size %d > 256\n", level);
323 dt_control_log(_(
"error - lut 3D size %d exceeds the maximum supported"), level);
329 dt_print(
DT_DEBUG_DEV,
"[lut3d] allocating %" G_GSIZE_FORMAT
" bytes for png file\n", buf_size);
334 fprintf(stderr,
"[lut3d] error allocating buffer for png lut\n");
342 fprintf(stderr,
"[lut3d] error - could not read png image `%s'\n", filepath);
343 dt_control_log(_(
"error - could not read png image %s"), filepath);
347 const size_t buf_size_lut = (size_t)png.
height * png.
height * 3;
348 dt_print(
DT_DEBUG_DEV,
"[lut3d] allocating %" G_GSIZE_FORMAT
" floats for png lut - level %d\n", buf_size_lut, level);
352 fprintf(stderr,
"[lut3d] error - allocating buffer for png lut\n");
358 const float norm = 1.0f / (powf(2.f, png.
bit_depth) - 1.0f);
361 for (
size_t i = 0;
i < buf_size_lut; ++
i)
362 lclut[
i] = (
float)buf[
i] * norm;
366 for (
size_t i = 0;
i < buf_size_lut; ++
i)
367 lclut[
i] = (256.0f * (
float)buf[2*
i] + (float)buf[2*
i+1]) * norm;
377 if (strncmp(str,
"nan", 3) == 0 || strncmp(str,
"NAN", 3) == 0)
379 double integral_result = 0;
380 double fractional_result = 0;
386 }
else if (*str ==
'-')
391 if (strncmp(str,
"inf", 3) == 0 || strncmp(str,
"INF", 3) == 0)
392 return sign * INFINITY;
395 const char * istr_back = str;
396 while (*str >=
'0' && *str <=
'9')
398 const char * istr_2 = str;
399 double imultiplier = 1;
400 while (istr_2 != istr_back)
403 integral_result += (*istr_2 -
'0') * imultiplier;
411 const char * fstr_back = str;
412 while (*str >=
'0' && *str <=
'9')
414 const char * fstr_2 = str;
415 double fmultiplier = 1;
416 while (fstr_2 != fstr_back)
419 fractional_result += (*fstr_2 -
'0') * fmultiplier;
422 fractional_result /= fmultiplier;
424 double result =
sign * (integral_result + fractional_result);
425 if (*str ==
'e' || *str ==
'E')
428 double power_sign = 1;
434 else if (*str ==
'-')
440 while (*str >=
'0' && *str <=
'9')
447 result *= pow(10, power);
449 result /= pow(10, power);
458 const int max_token_len = 50;
461 char *
t = &token[0][0];
464 while (*l != 0 &&
i < max_token_len)
466 if (*l ==
'#' || *l ==
'\n' || *l ==
'\r')
480 if (*l ==
' ' || *l ==
'\t')
487 t = &token[c > 2 ? 2 : c][0];
505 token[0][max_token_len - 1] = 0;
506 token[1][max_token_len - 1] = 0;
507 token[2][max_token_len - 1] = 0;
522 uint32_t out_of_range_nb = 0;
524 if(!(cube_file = g_fopen(filepath,
"r")))
526 fprintf(stderr,
"[lut3d] invalid cube file: %s\n", filepath);
530 while ((read =
getline(&line, &len, cube_file)) != -1)
535 if (token[0][0] ==
'T')
continue;
536 else if (strcmp(
"DOMAIN_MIN", token[0]) == 0)
538 if (strtod(token[1], NULL) != 0.0f)
540 fprintf(stderr,
"[lut3d] DOMAIN MIN <> 0.0 is not supported\n");
547 else if (strcmp(
"DOMAIN_MAX", token[0]) == 0)
549 if (strtod(token[1], NULL) != 1.0f)
551 fprintf(stderr,
"[lut3d] DOMAIN MAX <> 1.0 is not supported\n");
558 else if (strcmp(
"LUT_1D_SIZE", token[0]) == 0)
560 fprintf(stderr,
"[lut3d] 1D cube lut is not supported\n");
566 else if (strcmp(
"LUT_3D_SIZE", token[0]) == 0)
568 level = atoll(token[1]);
571 fprintf(stderr,
"[lut3d] error - LUT 3D size %d > 256\n", level);
572 dt_control_log(_(
"error - lut 3D size %d exceeds the maximum supported"), level);
577 buf_size = level * level * level * 3;
578 dt_print(
DT_DEBUG_DEV,
"[lut3d] allocating %" G_GSIZE_FORMAT
" bytes for cube lut - level %d\n", buf_size, level);
582 fprintf(stderr,
"[lut3d] error - allocating buffer for cube lut\n");
589 else if (nb_token == 3)
593 fprintf(stderr,
"[lut3d] error - cube lut size is not defined\n");
599 for (
int j=0; j < 3; j++)
602 if(isnan(lclut[
i+j]))
604 fprintf(stderr,
"[lut3d] error - invalid number line %d\n", (
int)
i/3);
605 dt_control_log(_(
"error - cube lut invalid number line %d"), (
int)
i/3);
610 else if(lclut[
i+j] < 0.0 || lclut[
i+j] > 1.0)
617 if (
i != buf_size ||
i == 0)
619 fprintf(stderr,
"[lut3d] error - cube lut lines number %d is not correct, should be %d\n",
620 (
int)
i/3, (
int)buf_size/3);
621 dt_control_log(_(
"error - cube lut lines number %d is not correct, should be %d"),
622 (
int)
i/3, (
int)buf_size/3);
630 fprintf(stderr,
"[lut3d] warning - %d out of range values [0,1]\n", out_of_range_nb);
631 dt_control_log(_(
"warning - cube lut %d out of range values [0,1]"), out_of_range_nb);
652 if(!(cube_file = g_fopen(filepath,
"r")))
654 fprintf(stderr,
"[lut3d] invalid 3dl file: %s\n", filepath);
658 while ((read =
getline(&line, &len, cube_file)) != -1)
668 const int min_shaper = atoll(token[0]);
669 const int max_shaper = atoll(token[2]);
670 if (max_shaper > min_shaper)
675 fprintf(stderr,
"[lut3d] error - the maximum shaper lut value %d is too low\n", max_shaper);
676 dt_control_log(_(
"error - the maximum shaper lut value %d is too low"), max_shaper);
681 buf_size = level * level * level * 3;
682 dt_print(
DT_DEBUG_DEV,
"[lut3d] allocating %" G_GSIZE_FORMAT
" bytes for cube lut - level %d\n", buf_size, level);
686 fprintf(stderr,
"[lut3d] error - allocating buffer for cube lut\n");
695 else if (nb_token == 3)
699 fprintf(stderr,
"[lut3d] error - cube lut size is not defined\n");
706 const uint32_t level2 = level * level;
707 const uint32_t red =
i / level2;
708 const uint32_t rr =
i - red * level2;
709 const uint32_t green = rr / level;
710 const uint32_t blue = rr - green * level;
711 const uint32_t
k = red + level * green + level2 * blue;
712 for (
int j=0; j < 3; j++)
714 const uint32_t
value = atoll(token[j]);
715 lclut[
k*3+j] = (float)
value;
716 if (
value > max_value)
720 if (
i * 3 > buf_size)
725 if (
i * 3 != buf_size ||
i == 0)
727 fprintf(stderr,
"[lut3d] error - cube lut lines number is not correct\n");
728 dt_control_log(_(
"error - cube lut lines number is not correct"));
739 while ((inorm < max_value) && (inorm < 65536))
743 fprintf(stderr,
"[lut3d] error - the maximum lut value does not match any valid bit depth\n");
744 dt_control_log(_(
"error - the maximum lut value does not match any valid bit depth"));
748 const float norm = 1.0f / (float)(inorm - 1);
750 for (
i =0;
i < buf_size;
i++)
751 lclut[
i] = CLAMP(lclut[
i] * norm, 0.0f, 1.0f);
762 cl_int err = CL_SUCCESS;
763 const float *
const clut = (
float *)
d->clut;
764 const int level =
d->level;
780 cl_mem clut_cl = NULL;
781 const int devid = pipe->
devid;
791 fprintf(stderr,
"[lut3d process_cl] error allocating memory\n");
792 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
798 work_profile, lut_profile,
"work profile to LUT profile");
814 lut_profile, work_profile,
"LUT profile to work profile");
824 if(err != CL_SUCCESS)
826 fprintf(stderr,
"[lut3d process_cl] error %i enqueue kernel\n", err);
834 return (err == CL_SUCCESS) ?
TRUE :
FALSE;
845 const float *
const clut = (
float *)
d->clut;
846 const uint16_t level =
d->level;
847 const int interpolation =
d->params.interpolation;
865 work_profile, lut_profile,
"work profile to LUT profile");
869 lut_profile, work_profile,
"LUT profile to work profile");
886 const int len = strlen(filepath);
887 for(
int i=0;
i<len; ++
i)
888 if (filepath[
i]==
'\\') filepath[
i] =
'/';
893 const int program = 28;
904 char *cache_dir = g_build_filename(g_get_user_cache_dir(),
"gmic", NULL);
924 const char *filepath =
p->filepath;
926 if (
p->nb_keypoints && filepath[0])
929 level = calculate_clut_compressed(
p, filepath, clut);
935 if (filepath[0] && lutfolder[0])
937 char *fullpath = g_build_filename(lutfolder, filepath, NULL);
938 if (g_str_has_suffix (filepath,
".png") || g_str_has_suffix (filepath,
".PNG"))
942 else if (g_str_has_suffix (filepath,
".cube") || g_str_has_suffix (filepath,
".CUBE"))
946 else if (g_str_has_suffix (filepath,
".3dl") || g_str_has_suffix (filepath,
".3DL"))
966 gchar *haystack = g_utf8_strdown(str, -1);
967 gchar *needle = g_utf8_strdown(gtk_entry_get_text(GTK_ENTRY(
g->lutentry)), -1);
969 visible = (g_strrstr(haystack, needle) != NULL);
980 GtkTreeModel *modelf = gtk_tree_view_get_model((GtkTreeView *)
g->lutname);
981 GtkTreeModel *
model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(modelf));
988 GtkTreeModel *modelf = gtk_tree_view_get_model((GtkTreeView *)
g->lutname);
989 GtkTreeModel *
model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(modelf));
991 gtk_list_store_append((GtkListStore *)
model, &iter);
998 GtkTreeModel *modelf = gtk_tree_view_get_model((GtkTreeView *)
g->lutname);
999 GtkTreeModel *
model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(modelf));
1001 GtkTreeSelection *selection = gtk_tree_view_get_selection((GtkTreeView *)
g->lutname);
1002 g_signal_handler_block(G_OBJECT(selection),
g->lutname_handler_id);
1003 gtk_list_store_clear((GtkListStore *)
model);
1004 g_signal_handler_unblock(G_OBJECT(selection),
g->lutname_handler_id);
1010 GtkTreeSelection *selection = gtk_tree_view_get_selection((GtkTreeView *)
g->lutname);
1011 GtkTreeModel *
model = gtk_tree_view_get_model((GtkTreeView *)
g->lutname);
1014 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
1019 if (!g_strcmp0(lutname,
name))
1021 gtk_tree_selection_select_iter(selection, &iter);
1022 GtkTreePath *
path = gtk_tree_model_get_path (
model, &iter);
1023 gtk_tree_view_scroll_to_cell((GtkTreeView *)
g->lutname, path, NULL,
TRUE, 0.2, 0);
1024 gtk_tree_path_free(path);
1029 valid = gtk_tree_model_iter_next(
model, &iter);
1035 if (gtk_tree_model_iter_nth_child(
model, &iter, NULL, 0))
1037 gtk_tree_selection_select_iter(selection, &iter);
1050 GtkTreeSelection *selection = gtk_tree_view_get_selection((GtkTreeView *)
g->lutname);
1051 GtkTreeModel *
model = gtk_tree_view_get_model((GtkTreeView *)
g->lutname);
1052 if (gtk_tree_selection_get_selected(selection, &
model, &iter))
1059 else lutname[0] = 0;
1062static void get_compressed_clut(
dt_iop_module_t *self, gboolean newlutname)
1068 if (
p->filepath[0] && lutfolder[0])
1070 if (g_str_has_suffix (
p->filepath,
".gmz") || g_str_has_suffix (
p->filepath,
".GMZ"))
1072 char *fullpath = g_build_filename(lutfolder,
p->filepath, NULL);
1073 gboolean lut_found =
lut3d_read_gmz(&
p->nb_keypoints, (
unsigned char *
const)
p->c_clut, fullpath,
1074 &nb_lut, (
void *)
g,
p->lutname, newlutname);
1079 select_lutname_in_list(
g,
p->lutname);
1083 select_lutname_in_list(
g, NULL);
1084 get_selected_lutname(
g,
p->lutname);
1086 else if (
p->lutname[0])
1088 if (!select_lutname_in_list(
g,
p->lutname))
1091 select_lutname_in_list(
g,
p->lutname);
1103 GtkTreeModel *
model = gtk_tree_view_get_model((GtkTreeView *)
g->lutname);
1104 const int nb_luts = gtk_tree_model_iter_n_children(
model, NULL);
1105 if ((nb_luts > 1) || ((nb_luts > 0) &&
1108 int nb_pixels = (20*(nb_luts+1) > 200) ? 200 : 20*(nb_luts);
1110 gtk_widget_set_visible(
g->lutentry,
TRUE);
1112 gtk_widget_set_visible(
g->lutentry,
FALSE);
1113 gtk_widget_set_visible(
g->lutwindow,
TRUE);
1114 gtk_scrolled_window_set_min_content_height((GtkScrolledWindow *)
g->lutwindow,
DT_PIXEL_APPLY_DPI(nb_pixels));
1118 gtk_widget_set_visible(
g->lutentry,
FALSE);
1119 gtk_widget_set_visible(
g->lutwindow,
FALSE);
1130 if (strcmp(
p->filepath,
d->params.filepath) != 0 || strcmp(
p->lutname,
d->params.lutname) != 0 )
1151 d->params.filepath[0] =
'\0';
1170 fprintf(stdout,
"filepath: %s\n", filepath);
1177 if (strcmp(filepath,
p->filepath) != 0 && !(g_str_has_suffix(filepath,
".gmz") || g_str_has_suffix(filepath,
".GMZ")))
1180 p->nb_keypoints = 0;
1184 g_strlcpy(
p->filepath, filepath,
sizeof(
p->filepath));
1185 get_compressed_clut(self,
FALSE);
1186 show_hide_controls(self);
1187 gtk_entry_set_text(GTK_ENTRY(
g->lutentry),
"");
1189 g_strlcpy(
p->filepath, filepath,
sizeof(
p->filepath));
1199 apply_filter_lutname_list(
g);
1202static void lutname_callback(GtkTreeSelection *selection,
dt_iop_module_t *self)
1207 GtkTreeModel *
model;
1210 if (gtk_tree_selection_get_selected(selection, &
model, &iter))
1213 if (lutname[0] && strcmp(lutname,
p->lutname) != 0)
1215 g_strlcpy(
p->lutname, lutname,
sizeof(
p->lutname));
1216 get_compressed_clut(self,
TRUE);
1225 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(
view));
1227 GtkTreeModel *
model = gtk_tree_view_get_model((GtkTreeView *)
view);
1228 if(gtk_tree_selection_get_selected(selection, &
model, &iter))
1230 gboolean next =
FALSE;
1231 if(event->delta_y > 0)
1232 next = gtk_tree_model_iter_next(
model, &iter);
1234 next = gtk_tree_model_iter_previous(
model, &iter);
1237 gtk_tree_selection_select_iter(selection, &iter);
1238 GtkTreePath *
path = gtk_tree_model_get_path(
model, &iter);
1239 gtk_tree_view_set_cursor((GtkTreeView *)
view, path, NULL,
FALSE);
1240 gtk_tree_path_free(path);
1251 const int j = strlen(lutfolder) + 1;
1253 for(
i = 0; filepath[
i+j] !=
'\0';
i++)
1254 filepath[
i] = filepath[
i+j];
1260 gboolean res =
FALSE;
1261 if (!filename || !filename[0])
return res;
1262 char *
p = g_strrstr(filename,
".");
1264 char *fext = g_ascii_strdown(g_strdup(
p), -1);
1266 if (!g_strcmp0(fext,
".png") || !g_strcmp0(fext,
".cube") || !g_strcmp0(fext,
".3dl")
1267 || !g_strcmp0(fext,
".gmz")) res =
TRUE;
1269 if (!g_strcmp0(fext,
".png") || !g_strcmp0(fext,
".cube") || !g_strcmp0(fext,
".3dl") ) res =
TRUE;
1288 char *relativepath = g_path_get_dirname(filepath);
1289 char *folder = g_build_filename(lutfolder, relativepath, NULL);
1291 DIR *
d = opendir(folder);
1295 while ((dir = readdir(
d)) != NULL)
1297 char *file = dir->d_name;
1300 char *ofilepath = (strcmp(relativepath,
".") != 0)
1301 ? g_build_filename(relativepath, file, NULL)
1330 if (strlen(lutfolder) == 0)
1332 fprintf(stderr,
"[lut3d] Lut root folder not defined\n");
1338 GtkFileChooserNative *filechooser = gtk_file_chooser_native_new(
1339 _(
"select lut file"), GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
1340 _(
"_select"), _(
"_cancel"));
1341 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser),
FALSE);
1343 char *composed = g_build_filename(lutfolder,
p->filepath, NULL);
1344 if (strlen(
p->filepath) == 0 || g_access(composed, F_OK) == -1)
1345 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filechooser), lutfolder);
1347 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(filechooser), composed);
1350 GtkFileFilter* filter = GTK_FILE_FILTER(gtk_file_filter_new());
1351 gtk_file_filter_add_pattern(filter,
"*.png");
1352 gtk_file_filter_add_pattern(filter,
"*.PNG");
1353 gtk_file_filter_add_pattern(filter,
"*.cube");
1354 gtk_file_filter_add_pattern(filter,
"*.CUBE");
1355 gtk_file_filter_add_pattern(filter,
"*.3dl");
1356 gtk_file_filter_add_pattern(filter,
"*.3DL");
1358 gtk_file_filter_add_pattern(filter,
"*.gmz");
1359 gtk_file_filter_add_pattern(filter,
"*.GMZ");
1360 gtk_file_filter_set_name(filter, _(
"hald cluts (png), 3D lut (cube or 3dl) or gmic compressed lut (gmz)"));
1362 gtk_file_filter_set_name(filter, _(
"hald cluts (png) or 3D lut (cube or 3dl)"));
1364 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
1365 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(filechooser), filter);
1369 filter = GTK_FILE_FILTER(gtk_file_filter_new());
1370 gtk_file_filter_add_pattern(filter,
"*");
1371 gtk_file_filter_set_name(filter, _(
"all files"));
1372 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
1374 if(gtk_native_dialog_run(GTK_NATIVE_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
1376 gchar *filepath = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
1377 if (strcmp(lutfolder, filepath) < 0)
1383 else if (!filepath[0])
1385 fprintf(stderr,
"[lut3d] select file outside Lut root folder is not allowed\n");
1386 dt_control_log(_(
"select file outside Lut root folder is not allowed"));
1389 gtk_widget_set_sensitive(
g->filepath,
p->filepath[0]);
1394 g_object_unref(filechooser);
1404 if(order_lut3d < order_colorin || order_lut3d > order_colorout)
1406 gtk_widget_hide(
g->colorspace);
1410 gtk_widget_show(
g->colorspace);
1421 gtk_widget_set_sensitive(
g->hbox,
FALSE);
1422 gtk_widget_set_sensitive(
g->filepath,
FALSE);
1427 gtk_widget_set_sensitive(
g->hbox,
TRUE);
1428 gtk_widget_set_sensitive(
g->filepath,
p->filepath[0]);
1438 get_compressed_clut(self,
FALSE);
1440 show_hide_controls(self);
1458 gtk_widget_set_tooltip_text(button, _(
"select a png (haldclut)"
1459 ", a cube, a 3dl or a gmz (compressed lut) file "
1460 "CAUTION: 3D lut folder must be set in preferences/processing before choosing the lut file"));
1462 gtk_widget_set_tooltip_text(button, _(
"select a png (haldclut)"
1463 ", a cube or a 3dl file "
1464 "CAUTION: 3D lut folder must be set in preferences/processing before choosing the lut file"));
1466 gtk_box_pack_start(GTK_BOX(
g->hbox), button,
FALSE,
FALSE, 0);
1467 g_signal_connect(G_OBJECT(button),
"clicked", G_CALLBACK(
button_clicked), self);
1471 gtk_box_pack_start(GTK_BOX(
g->hbox),
g->filepath,
TRUE,
TRUE, 0);
1473 gtk_widget_set_tooltip_text(
g->filepath,
1474 _(
"the file path (relative to lut folder) is saved with image along with the lut data if it's a compressed lut (gmz)"));
1476 gtk_widget_set_tooltip_text(
g->filepath,
1477 _(
"the file path (relative to lut folder) is saved with image (and not the lut data themselves)"));
1479 g_signal_connect(G_OBJECT(
g->filepath),
"value-changed", G_CALLBACK(
filepath_callback), self);
1481 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
g->hbox),
TRUE,
TRUE, 0);
1487 gtk_widget_set_tooltip_text(entry, _(
"enter lut name"));
1489 gtk_widget_add_events(entry, GDK_KEY_RELEASE_MASK);
1490 g_signal_connect(G_OBJECT(entry),
"changed", G_CALLBACK(
entry_callback), self);
1491 g->lutentry = entry;
1493 GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
1495 gtk_scrolled_window_set_policy((GtkScrolledWindow *)sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1497 GtkTreeModel *lutmodel = (GtkTreeModel *)gtk_list_store_new(
DT_LUT3D_NUM_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN);
1498 GtkTreeModel *lutfilter = gtk_tree_model_filter_new(lutmodel, NULL);
1499 gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(lutfilter),
DT_LUT3D_COL_VISIBLE);
1500 g_object_unref(lutmodel);
1502 GtkTreeView *
view = (GtkTreeView *)gtk_tree_view_new();
1505 gtk_tree_view_set_model(
view, lutfilter);
1506 gtk_tree_view_set_hover_selection(
view,
FALSE);
1507 gtk_tree_view_set_headers_visible(
view,
FALSE);
1509 gtk_widget_set_tooltip_text((
GtkWidget *)
view, _(
"select the LUT"));
1510 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1511 GtkTreeViewColumn *col = gtk_tree_view_column_new_with_attributes (
"lutname", renderer,
1513 gtk_tree_view_append_column(
view, col);
1514 GtkTreeSelection *selection = gtk_tree_view_get_selection(
view);
1515 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
1516 g->lutname_handler_id = g_signal_connect(G_OBJECT(selection),
"changed", G_CALLBACK(lutname_callback), self);
1517 g_signal_connect(G_OBJECT(
view),
"scroll-event", G_CALLBACK(mouse_scroll), (gpointer)self);
1522 gtk_widget_set_tooltip_text(
g->colorspace, _(
"select the color space in which the LUT has to be applied"));
1525 gtk_widget_set_tooltip_text(
g->interpolation, _(
"select the interpolation method"));
void cleanup(dt_imageio_module_format_t *self)
void dt_bauhaus_combobox_clear(GtkWidget *widget)
void dt_bauhaus_combobox_set_entries_ellipsis(GtkWidget *widget, PangoEllipsizeMode ellipis)
const char * dt_bauhaus_combobox_get_text(GtkWidget *widget)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
gboolean dt_bauhaus_combobox_set_from_text(GtkWidget *widget, const char *text)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
#define DT_BAUHAUS_WIDGET(obj)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static void transform(float *x, float *o, const float *m, const float t_h, const float t_v)
static gboolean list_match_string(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_ITUR_BT1886
@ DT_COLORSPACE_LIN_REC709
void dt_lut3d_apply(const float *const in, float *const out, const size_t pixel_nb, const float *const clut, const uint16_t level, const float normalization, const dt_lut3d_interpolation_t interpolation)
Apply one interpolation model over a packed RGB CLUT.
gchar * dt_conf_get_string(const char *name)
void dt_control_log(const char *msg,...)
uint32_t view(const dt_view_t *self)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
static const dt_aligned_pixel_simd_t sign
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define dt_pixelpipe_cache_free_align(mem)
static const dt_aligned_pixel_simd_t value
#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_dev_add_history_item(dev, module, enable, redraw)
void dtgtk_cairo_paint_directory(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
gchar * dt_loc_init_generic(const char *absolute_value, const char *application_directory, const char *default_value)
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnects accels when a text or search entry gets the focus, and reconnects them when it looses it....
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
int read_image(dt_imageio_png_t *png, void *out)
int read_header(const char *filename, dt_imageio_png_t *png)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
static float kernel(const float *x, const float *y)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static int calculate_clut(dt_iop_lut3d_params_t *const p, float **clut)
const char ** description(struct dt_iop_module_t *self)
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ibuf, void *const obuf)
uint16_t calculate_clut_3dl(const char *const filepath, float **clut)
const char invalid_filepath_prefix[]
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
gboolean check_extension(char *filename)
dt_iop_lut3d_interpolation_t
#define DT_IOP_LUT3D_MAX_KEYPOINTS
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
double dt_atof(const char *str)
uint8_t parse_cube_line(char *line, char(*token)[50])
void module_moved_callback(gpointer instance, dt_iop_module_t *self)
static void filepath_callback(GtkWidget *widget, dt_iop_module_t *self)
void gui_init(dt_iop_module_t *self)
static void button_clicked(GtkWidget *widget, dt_iop_module_t *self)
#define DT_IOP_LUT3D_CLUT_LEVEL
void filepath_set_unix_separator(char *filepath)
void get_cache_filename(const char *const lutname, char *const cache_filename)
dt_iop_lut3d_colorspace_t
static void update_filepath_combobox(dt_iop_lut3d_gui_data_t *g, char *filepath, char *lutfolder)
#define DT_IOP_LUT3D_MAX_PATHNAME
void gui_cleanup(dt_iop_module_t *self)
static gint array_str_cmp(gconstpointer a, gconstpointer b)
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)
uint16_t calculate_clut_haldclut(dt_iop_lut3d_params_t *const p, const char *const filepath, float **clut)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _show_hide_colorspace(dt_iop_module_t *self)
uint16_t calculate_clut_cube(const char *const filepath, float **clut)
#define DT_IOP_LUT3D_MAX_LUTNAME
void init_global(dt_iop_module_so_t *module)
static void remove_root_from_path(const char *const lutfolder, char *const filepath)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
int dt_ioppr_get_iop_order(GList *iop_order_list, const char *op_name, const int multi_priority)
Return the iop_order for a given operation/instance pair.
dt_iop_order_iccprofile_info_t * dt_ioppr_add_profile_info_to_list(struct dt_develop_t *dev, const dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename, const int intent)
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)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
int dt_ioppr_transform_image_colorspace_rgb_cl(const int devid, cl_mem dev_img_in, cl_mem dev_img_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)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
void lut3d_decompress_clut(const unsigned char *const input_keypoints, const unsigned int nb_input_keypoints, const unsigned int output_resolution, float *const output_clut_data, const char *const filename)
void lut3d_clear_lutname_list(void *g)
void lut3d_add_lutname_to_list(void *g, const char *const lutname)
unsigned int lut3d_get_cached_clut(float *const output_clut_data, const unsigned int output_resolution, const char *const filename)
gboolean lut3d_read_gmz(int *const nb_keypoints, unsigned char *const keypoints, const char *const filename, int *const nb_lut, void *widget, const char *const lutname, const gboolean newlutname)
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
void dt_opencl_release_mem_object(cl_mem mem)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ DT_SIGNAL_DEVELOP_MODULE_MOVED
This signal is raised when order of modules in pipeline is changed.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
static gboolean entry_callback(GtkEntry *entry, gpointer user_data)
struct dt_gui_gtk_t * gui
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_iop_lut3d_params_t params
int kernel_lut3d_tetrahedral
int kernel_lut3d_trilinear
GtkWidget * interpolation
dt_iop_lut3d_colorspace_t colorspace
dt_iop_lut3d_interpolation_t interpolation
dt_iop_global_data_t * data
dt_iop_params_t * default_params
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
GModule *dt_dev_operation_t op
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.
dt_bauhaus_combobox_data_t combobox