81#ifdef GDK_WINDOWING_QUARTZ
84#include <gdk/gdkkeysyms.h>
97#define EXPORT_MAX_IMAGE_SIZE UINT16_MAX
98#define CONFIG_PREFIX "plugins/lighttable/export/"
135#define INCH_TO_CM (2.54f)
142#define CONF_PRINT_WIDTH CONFIG_PREFIX "print_width"
143#define CONF_PRINT_HEIGHT CONFIG_PREFIX "print_height"
153 return dpi > 0 ? dpi : 300;
164 return cm > 0.f ? (uint32_t)ceilf(cm * (
float)dpi /
INCH_TO_CM) : 0;
208 *scale_factor = num / denum;
224 static const char *
v[] = {
"special", NULL};
245 gtk_widget_set_sensitive(GTK_WIDGET(
d->export_button), has_act_on && format_index != -1 && storage_index != -1);
273 const gchar *pdiv = strchr(scale_str,
'/');
275 gchar scale_buf[64] =
"";
276 gchar num_str[16] =
"";
277 gchar denum_str[16] =
"";
278 if(
_is_int(num)) snprintf(num_str,
sizeof(num_str),
"%d", (
int)num);
279 if(
_is_int(denum)) snprintf(denum_str,
sizeof(denum_str),
"%d", (
int)denum);
283 g_strlcat(scale_buf, num_str[0] ? num_str : scale_str,
sizeof(scale_buf));
285 else if(pdiv == scale_str)
288 g_strlcat(scale_buf, denum_str,
sizeof(scale_buf));
291 g_strlcat(scale_buf,
"1/",
sizeof(scale_buf));
292 g_strlcat(scale_buf, pdiv + 1,
sizeof(scale_buf));
298 g_strlcat(scale_buf, num_str,
sizeof(scale_buf));
302 gchar *num_part = g_strndup(scale_str, pdiv - scale_str);
303 g_strlcat(scale_buf, num_part,
sizeof(scale_buf));
306 g_strlcat(scale_buf,
"/",
sizeof(scale_buf));
307 g_strlcat(scale_buf, denum_str[0] ? denum_str : pdiv + 1,
sizeof(scale_buf));
319 char style[128] = { 0 };
328 if(format_index == -1)
333 if(storage_index == -1)
339 char *confirm_message = NULL;
341 if(mstorage->ask_user_confirmation)
342 confirm_message = mstorage->ask_user_confirmation(mstorage);
346 GtkWidget *dialog = gtk_message_dialog_new(
347 GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
348 "%s", confirm_message);
349#ifdef GDK_WINDOWING_QUARTZ
353 gtk_window_set_title(GTK_WINDOW(dialog), _(
"export to disk"));
354 const gint
res = gtk_dialog_run(GTK_DIALOG(dialog));
355 GtkWindow *dialog_parent = gtk_window_get_transient_for(GTK_WINDOW(dialog));
356 gtk_widget_destroy(dialog);
360 if(
res != GTK_RESPONSE_YES)
374 g_strlcpy(style, tmp,
sizeof(style));
376 request.
style = style;
395 const char *validSign =
",.0123456789";
396 const gchar *
value = gtk_entry_get_text(spin);
398 char new_value[30] =
"";
400 const int len =
MIN((
int)strlen(
value), (
int)
sizeof(new_value) - 1);
401 int i, j = 0, idec = 0, idiv = 0, pdiv = 0;
403 for (
i = 0;
i < len;
i++)
405 char *val = strchr(validSign,
value[
i]);
412 new_value[j++] =
'1';
416 if(atof(
value) == 0.0)
422 new_value[j++] =
'/';
427 else if((val[0] ==
'.') || (val[0] ==
','))
431 if((
i == 0) || (
i == pdiv))
433 new_value[j++] =
'0';
438 new_value[j++] =
value[
i];
448 new_value[j++] =
value[
i];
452 gtk_entry_set_text(spin, new_value);
460 if(event->button != 2)
return FALSE;
461 gtk_entry_set_text(entry, (
const char *)reset_text);
471 gtk_widget_hide(
d->size_in_px);
475 gtk_widget_show(
d->size_in_px);
478 double scale_factor = 0.0;
481 gchar height_txt[16];
482 snprintf(width_txt,
sizeof(width_txt),
"%d", max_width);
483 snprintf(height_txt,
sizeof(height_txt),
"%d", max_height);
484 gchar size_in_px_txt[120];
485 snprintf(size_in_px_txt,
sizeof(size_in_px_txt), _(
"which is equal to %s \303\227 %s px"), width_txt, height_txt);
486 gtk_label_set_text(GTK_LABEL(
d->size_in_px), size_in_px_txt);
492 gchar *max_width_char = g_strdup_printf(
"%d", max_width);
493 gchar *max_height_char = g_strdup_printf(
"%d", max_height);
496 gtk_entry_set_text(GTK_ENTRY(
d->width), max_width_char);
497 gtk_entry_set_text(GTK_ENTRY(
d->height), max_height_char);
517 gtk_label_set_text(GTK_LABEL(self->
unit_label),
574 if(mformat) mformat->gui_reset(mformat);
576 if(mstorage) mstorage->gui_reset(mstorage);
590 module = (dt_imageio_module_format_t *)it->data;
597 gtk_widget_hide(
d->format_extra_container);
600 else if(module->widget)
602 gtk_widget_show_all(
d->format_extra_container);
603 gtk_stack_set_visible_child(GTK_STACK(
d->format_extra_container), module->widget);
607 gtk_widget_hide(
d->format_extra_container);
621 const gboolean support_layers = (
module->flags(NULL) & FORMAT_FLAGS_SUPPORT_LAYERS) == FORMAT_FLAGS_SUPPORT_LAYERS;
622 const gboolean is_enabled = gtk_widget_get_sensitive(
d->export_masks);
623 if(support_layers && !is_enabled)
627 gtk_widget_set_sensitive(GTK_WIDGET(
d->export_masks),
TRUE);
630 else if(!support_layers && is_enabled)
636 gtk_widget_set_sensitive(GTK_WIDGET(
d->export_masks),
FALSE);
656 if(storage && format)
658 uint32_t fw, fh, sw, sh;
659 fw = fh = sw = sh = 0;
660 storage->dimension(storage, NULL, &sw, &sh);
661 format->dimension(format, NULL, &fw, &fh);
663 if(sw == 0 || fw == 0)
664 *
width = sw > fw ? sw : fw;
666 *
width = sw < fw ? sw : fw;
668 if(sh == 0 || fh == 0)
669 *
height = sh > fh ? sh : fh;
671 *
height = sh < fh ? sh : fh;
678 uint32_t
width = atoi(gtk_entry_get_text(GTK_ENTRY(
d->width)));
679 uint32_t
height = atoi(gtk_entry_get_text(GTK_ENTRY(
d->height)));
680 if(
width >
d->max_allowed_width ||
height >
d->max_allowed_height)
690 uint32_t max_w = 0, max_h = 0;
715 gtk_widget_hide(
d->storage_extra_container);
718 else if(module->widget)
720 gtk_widget_show_all(
d->storage_extra_container);
721 gtk_stack_set_visible_child(GTK_STACK(
d->storage_extra_container),module->widget);
725 gtk_widget_hide(
d->storage_extra_container);
733 uint32_t w = 0, h = 0;
734 module->recommended_dimension(module, NULL, &w, &h);
740 if(w > cw || w == 0) w = cw;
741 if(h >
ch || h == 0) h =
ch;
814 gchar *pdpi = g_strdup_printf(
"%d",
_print_dpi());
817 gtk_entry_set_text(GTK_ENTRY(
d->print_width), pwidth);
818 gtk_entry_set_text(GTK_ENTRY(
d->print_height), pheight);
819 gtk_entry_set_text(GTK_ENTRY(
d->print_dpi), pdpi);
832 const uint32_t
width = atoi(gtk_entry_get_text(GTK_ENTRY(
d->width)));
839 const float value = atof(gtk_entry_get_text(entry));
855 const uint32_t
height = atoi(gtk_entry_get_text(GTK_ENTRY(
d->height)));
870 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(
d->print_dpi)));
881 const char *
key = (
const char *)user_data;
919 gboolean empty =
TRUE;
923 if(storage->supported(storage, format))
930 gtk_widget_set_sensitive(GTK_WIDGET(
d->format), !empty);
947 gtk_container_add(GTK_CONTAINER(
d->storage_extra_container), module->widget);
962 for(
const GList *st_iter = styles; st_iter; st_iter = g_list_next(st_iter))
977 const gboolean ondisk =
name && !g_strcmp0(
name, _(
"file on disk"));
983 GtkWidget *mi = gtk_menu_item_new_with_label(_(
"preferences..."));
985 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
992 self->
data = (
void *)
d;
1003 d->storage_extra_container = gtk_stack_new();
1004 gtk_stack_set_homogeneous(GTK_STACK(
d->storage_extra_container),
FALSE);
1005 gtk_box_pack_start(GTK_BOX(self->
widget),
d->storage_extra_container,
FALSE,
TRUE, 0);
1012 gtk_container_add(GTK_CONTAINER(
d->storage_extra_container), module->widget);
1019 g_signal_connect(G_OBJECT(
d->storage),
"value-changed", G_CALLBACK(
_storage_changed), (gpointer)
d);
1027 g_signal_connect(G_OBJECT(
d->format),
"value-changed", G_CALLBACK(
_format_changed), (gpointer)
d);
1030 d->format_extra_container = gtk_stack_new();
1031 gtk_stack_set_homogeneous(GTK_STACK(
d->format_extra_container),
FALSE);
1032 gtk_box_pack_start(GTK_BOX(self->
widget),
d->format_extra_container,
FALSE,
TRUE, 0);
1039 gtk_container_add(GTK_CONTAINER(
d->format_extra_container), module->widget);
1047 _(
"Choose a method for setting the output size.\n"
1048 "The width and height specified define the bounding box\n"
1049 "in which the image will be proportionnaly fitted.\n"),
1052 N_(
"in pixels (for file)"),
1053 N_(
"in cm (for print)"),
1054 N_(
"in inch (for print)"),
1055 N_(
"by scale (for file)"),
1056 N_(
"original resolution"));
1058 d->print_width = gtk_entry_new();
1060 gtk_widget_set_tooltip_text(
d->print_width, _(
"maximum output width limit.\n"
1061 "click middle mouse button to reset to 0."));
1062 gtk_entry_set_width_chars(GTK_ENTRY(
d->print_width), 5);
1063 d->print_height = gtk_entry_new();
1065 gtk_widget_set_tooltip_text(
d->print_height, _(
"maximum output height limit.\n"
1066 "click middle mouse button to reset to 0."));
1067 gtk_entry_set_width_chars(GTK_ENTRY(
d->print_height), 5);
1068 d->print_dpi = gtk_entry_new();
1070 gtk_widget_set_tooltip_text(
d->print_dpi, _(
"resolution in dot per inch"));
1071 gtk_entry_set_width_chars(GTK_ENTRY(
d->print_dpi), 4);
1073 gtk_entry_set_text(GTK_ENTRY(
d->print_dpi), dpi);
1076 d->width = gtk_entry_new();
1078 gtk_widget_set_tooltip_text(
d->width, _(
"maximum output width limit.\n"
1079 "click middle mouse button to reset to 0."));
1080 gtk_entry_set_width_chars(GTK_ENTRY(
d->width), 5);
1081 d->height = gtk_entry_new();
1083 gtk_widget_set_tooltip_text(
d->height, _(
"maximum output height limit.\n"
1084 "click middle mouse button to reset to 0."));
1085 gtk_entry_set_width_chars(GTK_ENTRY(
d->height), 5);
1087 gtk_widget_add_events(
d->width, GDK_BUTTON_PRESS_MASK);
1088 gtk_widget_add_events(
d->height, GDK_BUTTON_PRESS_MASK);
1091 d->print_size = gtk_flow_box_new();
1092 gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(
d->print_size), 5);
1093 gtk_flow_box_set_column_spacing (GTK_FLOW_BOX(
d->print_size), 3);
1094 gtk_container_add(GTK_CONTAINER(
d->print_size),
d->print_width);
1095 gtk_container_add(GTK_CONTAINER(
d->print_size), gtk_label_new(_(
"x")));
1096 gtk_container_add(GTK_CONTAINER(
d->print_size),
d->print_height);
1097 d->unit_label = gtk_label_new(_(
"cm"));
1098 gtk_container_add(GTK_CONTAINER(
d->print_size),
d->unit_label);
1099 GtkBox *dpi_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
1100 gtk_box_pack_start(dpi_box, gtk_label_new(_(
"@")),
FALSE,
FALSE, 0);
1101 gtk_box_pack_start(dpi_box,
d->print_dpi,
TRUE,
TRUE, 0);
1102 gtk_box_pack_start(dpi_box, gtk_label_new(_(
"dpi")),
FALSE,
FALSE, 0);
1103 gtk_container_add(GTK_CONTAINER(
d->print_size), GTK_WIDGET(dpi_box));
1106 d->px_size = gtk_flow_box_new();
1107 gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(
d->px_size), 3);
1108 gtk_flow_box_set_column_spacing (GTK_FLOW_BOX(
d->px_size), 3);
1109 gtk_container_add(GTK_CONTAINER(
d->px_size),
d->width);
1110 gtk_container_add(GTK_CONTAINER(
d->px_size), gtk_label_new(_(
"x")));
1111 GtkBox *px_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
1112 gtk_box_pack_start(px_box,
d->height,
TRUE,
TRUE, 0);
1113 gtk_box_pack_start(px_box, gtk_label_new(_(
"px")),
FALSE,
FALSE, 0);
1114 gtk_container_add(GTK_CONTAINER(
d->px_size), GTK_WIDGET(px_box));
1117 d->scale = gtk_entry_new();
1119 gtk_entry_set_width_chars(GTK_ENTRY(
d->scale), 5);
1121 gtk_widget_set_tooltip_text(
d->scale, _(
"it can be an integer, decimal number or simple fraction.\n"
1122 "zero or empty values are equal to 1.\n"
1123 "click middle mouse button to reset to 1."));
1124 gtk_widget_set_halign(GTK_WIDGET(
d->scale), GTK_ALIGN_END);
1125 gtk_widget_add_events(
d->scale, GDK_BUTTON_PRESS_MASK);
1127 d->size_in_px = gtk_label_new(
"");
1128 gtk_label_set_ellipsize(GTK_LABEL(
d->size_in_px), PANGO_ELLIPSIZE_START);
1129 gtk_widget_set_sensitive(GTK_WIDGET(
d->size_in_px),
FALSE);
1131 gtk_widget_set_halign(GTK_WIDGET(
d->scale), GTK_ALIGN_FILL);
1132 gtk_widget_set_halign(GTK_WIDGET(
d->size_in_px), GTK_ALIGN_END);
1134 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->dimensions_type),
FALSE,
FALSE, 0);
1135 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->px_size),
FALSE,
FALSE, 0);
1136 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->print_size),
FALSE,
FALSE, 0);
1137 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->scale),
FALSE,
FALSE, 0);
1138 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->size_in_px),
FALSE,
FALSE, 0);
1144 gtk_widget_set_tooltip_text(
d->export_masks, _(
"store masks as layers in exported images. only works for some formats."));
1145 gtk_box_pack_start(GTK_BOX(self->
widget),
d->export_masks,
FALSE,
TRUE, 0);
1160 for(
size_t k = 0;
k < n_out_profiles;
k++)
1166 char *system_profile_dir = g_build_filename(datadir,
"color",
"out", NULL);
1167 char *user_profile_dir = g_build_filename(confdir,
"color",
"out", NULL);
1168 char *
tooltip = g_strdup_printf(_(
1169 "RGB color space used to encode the output files.\n"
1170 "\"same as original\" exports to the same space as the original\n"
1171 "picture, which is linear sensor RGB for raw pictures.\n"
1172 "sRGB is recommended in most cases.\n"
1173 "You can use custom color spaces defined\n"
1174 "by ICC profiles stored in:\n- %s\n- %s"), user_profile_dir, system_profile_dir);
1175 gtk_widget_set_tooltip_text(
d->profile,
tooltip);
1191 tooltip = g_strdup_printf(_(
"• perceptual: "
1192 "smoothly moves out-of-gamut colors into gamut,"
1193 "preserving gradations, but distorts in-gamut colors in the process."
1194 " note that perceptual is often a proprietary LUT that depends"
1195 " on the destination space."
1198 "• relative colorimetric: "
1199 "keeps luminance while reducing as little as possible saturation"
1200 " until colors fit in gamut."
1204 "designed to present eye-catching business graphics"
1205 " by preserving the saturation. (not suited for photography)."
1208 "• absolute colorimetric: "
1209 "adapt white point of the image to the white point of the"
1210 " destination medium and do nothing else. mainly used when"
1211 " proofing colors. (not suited for photography)."
1214 gtk_widget_set_tooltip_text(
d->intent,
tooltip);
1223 gtk_widget_set_tooltip_text(
d->style, _(
"temporary style to use while exporting"));
1226 g_signal_connect(G_OBJECT(
d->export_masks),
"value-changed", G_CALLBACK(
_callback_bool),
1228 g_signal_connect(G_OBJECT(
d->intent),
"value-changed", G_CALLBACK(
_intent_changed), (gpointer)
d);
1229 g_signal_connect(G_OBJECT(
d->profile),
"value-changed", G_CALLBACK(
_profile_changed), (gpointer)
d);
1230 g_signal_connect(G_OBJECT(
d->style),
"value-changed", G_CALLBACK(
_style_changed), (gpointer)
d);
1236 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(hbox),
FALSE,
TRUE, 0);
1241 gtk_box_pack_start(hbox, GTK_WIDGET(
d->export_button),
TRUE,
TRUE, 0);
1243 g_signal_connect(G_OBJECT(
d->width),
"changed", G_CALLBACK(
_width_changed), (gpointer)
d);
1244 g_signal_connect(G_OBJECT(
d->height),
"changed", G_CALLBACK(
_height_changed), (gpointer)
d);
1247 g_signal_connect(G_OBJECT(
d->print_dpi),
"changed", G_CALLBACK(
_print_dpi_changed), (gpointer)
d);
1251 g_signal_connect(G_OBJECT(
d->print_width),
"button-press-event", G_CALLBACK(
_size_entry_reset_click), (gpointer)
"0");
1252 g_signal_connect(G_OBJECT(
d->print_height),
"button-press-event", G_CALLBACK(
_size_entry_reset_click), (gpointer)
"0");
1255 g_signal_connect(G_OBJECT(
d->scale),
"changed", G_CALLBACK(
_scale_changed), (gpointer)
d);
1258 gtk_widget_show_all(self->
widget);
1259 gtk_widget_set_no_show_all(self->
widget,
TRUE);
1262 gtk_entry_set_text(GTK_ENTRY(
d->width), setting);
1264 gtk_entry_set_text(GTK_ENTRY(
d->height), setting);
1299 gboolean rc =
FALSE;
1334 if(module->widget && GTK_IS_CONTAINER(
d->storage_extra_container)) gtk_container_remove(GTK_CONTAINER(
d->storage_extra_container),
module->widget);
1340 if(module->widget && GTK_IS_CONTAINER(
d->format_extra_container)) gtk_container_remove(GTK_CONTAINER(
d->format_extra_container),
module->widget);
1364 const int version = self->version();
1369 for(GList *l = presets; l; l = g_list_next(l))
1372 const int rowid =
p->rowid;
1373 const int op_version =
p->op_version;
1374 const void *op_params =
p->op_params;
1375 const size_t op_params_size =
p->op_params_size;
1376 const char *
name =
p->name;
1378 if(op_version != version)
1381 fprintf(stderr,
"[export_init_presets] found export preset '%s' with version %d, version %d was "
1382 "expected. dropping preset.\n",
1383 name, op_version, version);
1389 const char *buf = (
const char *)op_params;
1392 buf += 6 *
sizeof(int32_t);
1394 buf += strlen(buf) + 1;
1396 buf += strlen(buf) + 1;
1399 const char *fname = buf;
1400 buf += strlen(fname) + 1;
1401 const char *sname = buf;
1402 buf += strlen(sname) + 1;
1407 if(!fmod || !smod)
continue;
1410 size_t copy_over_part = (
void *)buf - (
void *)op_params;
1412 const int fversion = *(
const int *)buf;
1413 buf +=
sizeof(int32_t);
1414 const int sversion = *(
const int *)buf;
1415 buf +=
sizeof(int32_t);
1416 const int fsize = *(
const int *)buf;
1417 buf +=
sizeof(int32_t);
1418 const int ssize = *(
const int *)buf;
1419 buf +=
sizeof(int32_t);
1421 const void *fdata = buf;
1423 const void *sdata = buf;
1425 void *new_fdata = NULL, *new_sdata = NULL;
1426 size_t new_fsize = fsize, new_ssize = ssize;
1427 const int32_t new_fversion = fmod->version(), new_sversion = smod->version();
1429 if(fversion < new_fversion)
1431 if(!(fmod->legacy_params
1432 && (new_fdata = fmod->legacy_params(fmod, fdata, fsize, fversion, new_fversion, &new_fsize))
1437 if(sversion < new_sversion)
1439 if(!(smod->legacy_params
1440 && (new_sdata = smod->legacy_params(smod, sdata, ssize, sversion, new_sversion, &new_ssize))
1445 if(new_fdata || new_sdata)
1448 const size_t new_params_size = op_params_size - (fsize + ssize) + (new_fsize + new_ssize);
1449 void *new_params = malloc(new_params_size);
1450 memcpy(new_params, op_params, copy_over_part);
1452 size_t pos = copy_over_part;
1453 memcpy((uint8_t *)new_params + pos, &new_fversion,
sizeof(int32_t));
1454 pos +=
sizeof(int32_t);
1455 memcpy((uint8_t *)new_params + pos, &new_sversion,
sizeof(int32_t));
1456 pos +=
sizeof(int32_t);
1457 memcpy((uint8_t *)new_params + pos, &new_fsize,
sizeof(int32_t));
1458 pos +=
sizeof(int32_t);
1459 memcpy((uint8_t *)new_params + pos, &new_ssize,
sizeof(int32_t));
1460 pos +=
sizeof(int32_t);
1462 memcpy((uint8_t *)new_params + pos, new_fdata, new_fsize);
1464 memcpy((uint8_t *)new_params + pos, fdata, fsize);
1467 memcpy((uint8_t *)new_params + pos, new_sdata, new_ssize);
1469 memcpy((uint8_t *)new_params + pos, sdata, ssize);
1473 "[export_init_presets] updating export preset '%s' from versions %d/%d to versions %d/%d\n",
1474 name, fversion, sversion, new_fversion, new_sversion);
1489 fprintf(stderr,
"[export_init_presets] export preset '%s' can't be updated from versions %d/%d to "
1490 "versions %d/%d. dropping preset\n",
1491 name, fversion, sversion, new_fversion, new_sversion);
1499 const int old_version,
int *new_version,
size_t *new_size)
1501 if(old_version == 1)
1504 const size_t new_params_size = old_params_size + 2 *
sizeof(int32_t);
1505 void *new_params = malloc(new_params_size);
1507 const char *buf = (
const char *)old_params;
1510 buf += 3 *
sizeof(int32_t);
1512 buf += strlen(buf) + 1;
1515 const char *fname = buf;
1516 buf += strlen(fname) + 1;
1517 const char *sname = buf;
1518 buf += strlen(sname) + 1;
1532 size_t first_half = (
void *)buf - (
void *)old_params;
1533 memcpy(new_params, old_params, first_half);
1536 int32_t fversion = 1;
1537 int32_t sversion = (strcmp(sname,
"picasa") == 0 ? 2 : 1);
1538 memcpy((uint8_t *)new_params + first_half, &fversion,
sizeof(int32_t));
1539 memcpy((uint8_t *)new_params + first_half +
sizeof(int32_t), &sversion,
sizeof(int32_t));
1541 memcpy((uint8_t *)new_params + first_half +
sizeof(int32_t) * 2, buf, old_params_size - first_half);
1543 *new_size = new_params_size;
1547 else if(old_version == 2)
1550 const size_t new_params_size = old_params_size +
sizeof(int32_t);
1551 void *new_params = calloc(1, new_params_size);
1553 memcpy(new_params, old_params,
sizeof(int32_t) * 2);
1554 memcpy((uint8_t *)new_params +
sizeof(int32_t) * 3, (uint8_t *)old_params +
sizeof(int32_t) * 2, old_params_size -
sizeof(int32_t) * 2);
1556 *new_size = new_params_size;
1560 else if(old_version == 3)
1572 const char *buf = (
const char *)old_params;
1575 const char *iccprofile = buf + 4 *
sizeof(int32_t);
1577 size_t new_params_size = old_params_size - strlen(iccprofile) +
sizeof(int32_t);
1579 const char *iccfilename =
"";
1581 if(!strcmp(iccprofile,
"image"))
1583 else if(!strcmp(iccprofile,
"sRGB"))
1585 else if(!strcmp(iccprofile,
"linear_rec709_rgb") || !strcmp(iccprofile,
"linear_rgb"))
1587 else if(!strcmp(iccprofile,
"linear_rec2020_rgb"))
1589 else if(!strcmp(iccprofile,
"adobergb"))
1594 iccfilename = iccprofile;
1595 new_params_size += strlen(iccfilename);
1598 void *new_params = calloc(1, new_params_size);
1600 memcpy(new_params, old_params,
sizeof(int32_t) * 4);
1601 pos += 4 *
sizeof(int32_t);
1602 memcpy((uint8_t *)new_params + pos, &icctype,
sizeof(int32_t));
1603 pos +=
sizeof(int32_t);
1604 memcpy((uint8_t *)new_params + pos, iccfilename, strlen(iccfilename) + 1);
1605 pos += strlen(iccfilename) + 1;
1606 size_t old_pos = 4 *
sizeof(int32_t) + strlen(iccprofile) + 1;
1607 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + old_pos, old_params_size - old_pos);
1609 *new_size = new_params_size;
1613 else if(old_version == 4)
1626 const size_t new_params_size = old_params_size +
sizeof(int32_t);
1627 void *new_params = calloc(1, new_params_size);
1630 memcpy(new_params, old_params,
sizeof(int32_t) * 3);
1631 pos += 4 *
sizeof(int32_t);
1632 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + pos -
sizeof(int32_t), old_params_size -
sizeof(int32_t) * 3);
1634 *new_size = new_params_size;
1638 else if(old_version == 5)
1654 const int flags_size = strlen(
flags) + 1;
1655 const size_t new_params_size = old_params_size + flags_size;
1656 void *new_params = calloc(1, new_params_size);
1658 memcpy(new_params, old_params,
sizeof(int32_t) * 6);
1659 pos += 6 *
sizeof(int32_t);
1660 memcpy((uint8_t *)new_params + pos,
flags, flags_size);
1662 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + pos - flags_size, old_params_size -
sizeof(int32_t) * 6);
1665 *new_size = new_params_size;
1669 else if(old_version == 6)
1680 const size_t new_params_size = old_params_size +
sizeof(int32_t);
1681 void *new_params = calloc(1, new_params_size);
1684 memcpy(new_params, old_params,
sizeof(int32_t) * 4);
1685 pos += 5 *
sizeof(int32_t);
1686 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + pos -
sizeof(int32_t), old_params_size -
sizeof(int32_t) * 4);
1688 *new_size = new_params_size;
1705 size_t fsize = mformat->params_size(mformat);
1707 size_t ssize = mstorage->params_size(mstorage);
1708 void *sdata = mstorage->get_params(mstorage);
1709 const int32_t fversion = mformat->version();
1710 const int32_t sversion = mstorage->version();
1731 int32_t max_width = 0;
1732 int32_t max_height = 0;
1733 double scale_factor = 0.0;
1735 if(scale_factor > 0.0)
1740 const int32_t upscale =
FALSE;
1741 const int32_t high_quality =
TRUE;
1745 const char *metadata_export =
IS_NULL_PTR(
d->metadata_export) ?
"" :
d->metadata_export;
1749 g_strlcpy(fdata->
style, style,
sizeof(fdata->
style));
1757 if(!iccfilename) iccfilename = g_strdup(
"");
1761 const int32_t fname_len = strlen(fname);
1762 const int32_t sname_len = strlen(sname);
1764 *
size = fname_len + sname_len + 2 + 4 *
sizeof(int32_t) + fsize + ssize + 7 *
sizeof(int32_t)
1765 + strlen(iccfilename) + 1 + strlen(metadata_export) + 1;
1769 memcpy(
params + pos, &max_width,
sizeof(int32_t));
1770 pos +=
sizeof(int32_t);
1771 memcpy(
params + pos, &max_height,
sizeof(int32_t));
1772 pos +=
sizeof(int32_t);
1773 memcpy(
params + pos, &upscale,
sizeof(int32_t));
1774 pos +=
sizeof(int32_t);
1775 memcpy(
params + pos, &high_quality,
sizeof(int32_t));
1776 pos +=
sizeof(int32_t);
1777 memcpy(
params + pos, &export_masks,
sizeof(int32_t));
1778 pos +=
sizeof(int32_t);
1779 memcpy(
params + pos, &iccintent,
sizeof(int32_t));
1780 pos +=
sizeof(int32_t);
1781 memcpy(
params + pos, &icctype,
sizeof(int32_t));
1782 pos +=
sizeof(int32_t);
1783 memcpy(
params + pos, metadata_export, strlen(metadata_export) + 1);
1784 pos += strlen(metadata_export) + 1;
1785 memcpy(
params + pos, iccfilename, strlen(iccfilename) + 1);
1786 pos += strlen(iccfilename) + 1;
1787 memcpy(
params + pos, fname, fname_len + 1);
1788 pos += fname_len + 1;
1789 memcpy(
params + pos, sname, sname_len + 1);
1790 pos += sname_len + 1;
1791 memcpy(
params + pos, &fversion,
sizeof(int32_t));
1792 pos +=
sizeof(int32_t);
1793 memcpy(
params + pos, &sversion,
sizeof(int32_t));
1794 pos +=
sizeof(int32_t);
1795 memcpy(
params + pos, &fsize,
sizeof(int32_t));
1796 pos +=
sizeof(int32_t);
1797 memcpy(
params + pos, &ssize,
sizeof(int32_t));
1798 pos +=
sizeof(int32_t);
1801 memcpy(
params + pos, fdata, fsize);
1806 memcpy(
params + pos, sdata, ssize);
1809 g_assert(pos == *
size);
1814 if(fdata) mformat->free_params(mformat, fdata);
1815 if(sdata) mstorage->free_params(mstorage, sdata);
1822 const char *str = *buf;
1823 const char *nul = memchr(str,
'\0', end - str);
1835 const char *buf = (
const char *)
params;
1836 const char *
const end = buf +
size;
1840 if((
size_t)(end - buf) <
sizeof(header))
return 1;
1841 memcpy(header, buf,
sizeof(header));
1842 buf +=
sizeof(header);
1843 const int max_width = header[0];
1844 const int max_height = header[1];
1845 const int export_masks = header[4];
1846 const int iccintent = header[5];
1847 const int icctype = header[6];
1850 const char *iccfilename = metadata_export ?
_blob_string(&buf, end) : NULL;
1851 const char *fname = iccfilename ?
_blob_string(&buf, end) : NULL;
1852 const char *sname = fname ?
_blob_string(&buf, end) : NULL;
1857 if((
size_t)(end - buf) <
sizeof(modules))
return 1;
1858 memcpy(modules, buf,
sizeof(modules));
1859 buf +=
sizeof(modules);
1860 const int32_t fversion = modules[0];
1861 const int32_t sversion = modules[1];
1862 const int32_t fsize = modules[2];
1863 const int32_t ssize = modules[3];
1864 if(fsize < 0 || ssize < 0 || (
size_t)(end - buf) != (
size_t)fsize + (size_t)ssize)
return 1;
1869 if(!fmod || !smod)
return 1;
1870 if(fversion != fmod->version() || sversion != smod->version())
return 1;
1873 const void *sdata = buf + fsize;
1876 d->metadata_export = g_strdup(metadata_export);
1894 char style[
sizeof(fdata->
style)];
1895 memcpy(style, fdata->
style,
sizeof(style));
1896 style[
sizeof(style) - 1] =
'\0';
1897 if(style[0] ==
'\0')
1917 if(ssize)
res += smod->set_params(smod, sdata, ssize);
1918 if(fsize)
res += fmod->set_params(fmod, fdata, fsize);
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnect accels while a text or search entry has the focus, and reconnect them when it loses it....
Handle default and user-set shortcuts (accelerators)
int dt_act_on_get_images_nb(const gboolean only_visible, const gboolean force)
GList * dt_act_on_get_images()
GtkWidget * dt_gui_main_window(void)
void dt_bauhaus_combobox_clear(GtkWidget *widget)
int dt_bauhaus_combobox_get(GtkWidget *widget)
const char * dt_bauhaus_combobox_get_text(GtkWidget *widget)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
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_COMBOBOX_NEW_FULL(bauhaus, widget, action, label, tip, pos, callback, data,...)
dt_collection_properties_t
size_t dt_colorspaces_enumerate_profiles(const dt_colorspaces_profile_role_t role, dt_colorprofile_desc_t **out)
Ordered snapshot of every profile registered for one role.
int dt_colorspaces_profile_index(const dt_colorspaces_profile_role_t role, const dt_colorspaces_color_profile_type_t type, const char *const filename)
Combo position of (type, filename) within direction.
gboolean dt_colorspaces_profile_at(const dt_colorspaces_profile_role_t role, const int index, dt_colorprofile_desc_t *const out)
Identity of the profile at index within direction.
The colour-profile module's API: which profiles exist, and how to apply one.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
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)
Does key have a value?
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
Float for name, clamped to its declared bounds.
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
void dt_conf_set_int(const char *name, int val)
gboolean dt_confgen_get_bool(const char *name, dt_confgen_value_kind_t kind)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
int dt_confgen_get_int(const char *name, dt_confgen_value_kind_t kind)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
const char * dt_confgen_get(const char *name, dt_confgen_value_kind_t kind)
One declared attribute of name from the generated XML, as text.
void dt_gui_container_remove_children(GtkContainer *container)
void dt_gui_flow_box_as_layout(GtkFlowBox *box)
void dt_control_log(const char *msg,...)
void dt_control_export(GList *imgid_list, const dt_control_export_request_t *request)
struct dt_imageio_t * dt_imageio_get_global(void)
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
void dt_gui_refocus_parent(GtkWindow *parent)
static void _format_changed(GtkWidget *widget, dt_lib_export_t *d)
static float _print_unit_in_cm(const dt_dimensions_type_t d_type)
void gui_reset(dt_lib_module_t *self)
static void _callback_bool(GtkWidget *widget, gpointer user_data)
void _menuitem_preferences(GtkMenuItem *menuitem, dt_lib_module_t *self)
int set_params(dt_lib_module_t *self, const void *params, int size)
static void _update(dt_lib_module_t *self)
static void _height_changed(GtkEditable *entry, gpointer user_data)
char * dt_lib_export_metadata_configuration_dialog(char *list, const gboolean ondisk)
static void _print_height_changed(GtkEditable *entry, gpointer user_data)
void * get_params(dt_lib_module_t *self, int *size)
static int _print_dpi(void)
static gboolean _is_int(const double value)
void set_preferences(void *menu, dt_lib_module_t *self)
static void _intent_changed(GtkWidget *widget, dt_lib_export_t *d)
static void _scale_changed(GtkEntry *spin, dt_lib_export_t *d)
static void _profile_changed(GtkWidget *widget, dt_lib_export_t *d)
static void _scale_optim()
static gboolean _size_entry_reset_click(GtkEntry *entry, const GdkEventButton *event, gpointer reset_text)
static void _print_width_changed(GtkEditable *entry, gpointer user_data)
void gui_cleanup(dt_lib_module_t *self)
static void _print_dpi_changed(GtkWidget *widget, gpointer user_data)
static void _resolve_export_size(int *max_width, int *max_height, double *scale_factor)
static void _on_storage_list_changed(gpointer instance, dt_lib_module_t *self)
static void _dimensions_type_changed(GtkWidget *widget, dt_lib_export_t *d)
static void _style_changed(GtkWidget *widget, dt_lib_export_t *d)
static void set_format_by_name(dt_lib_export_t *d, const char *name)
static dt_dimensions_type_t _dimensions_type(void)
static void _validate_dimensions(dt_lib_export_t *d)
static void _print_size_from_pixels(const uint32_t width, const uint32_t height)
void _size_update_display(dt_lib_export_t *self)
#define EXPORT_MAX_IMAGE_SIZE
static void _print_size_display(dt_lib_export_t *d)
static void _update_formats_combobox(dt_lib_export_t *d)
static uint32_t _cm_to_pixels(const float cm, const int dpi)
void init_presets(dt_lib_module_t *self)
static void _update_dimensions(dt_lib_export_t *d)
static void _collection_updated_callback(gpointer instance, dt_collection_change_t query_change, dt_collection_properties_t changed_property, gpointer imgs, int next, dt_lib_module_t *self)
#define CONF_PRINT_HEIGHT
uint32_t container(dt_lib_module_t *self)
static void _size_in_px_update(dt_lib_export_t *d)
static void _storage_changed(GtkWidget *widget, dt_lib_export_t *d)
void _set_dimensions(dt_lib_export_t *d, uint32_t max_width, uint32_t max_height)
static void _export_button_clicked(GtkWidget *widget, dt_lib_export_t *d)
void gui_init(dt_lib_module_t *self)
const char ** views(dt_lib_module_t *self)
static void _image_selection_changed_callback(gpointer instance, dt_lib_module_t *self)
void * legacy_params(dt_lib_module_t *self, const void *const old_params, const size_t old_params_size, const int old_version, int *new_version, size_t *new_size)
static void _ensure_print_size_conf(void)
static void _print_size_changed(GtkEntry *entry, const char *key, dt_lib_export_t *d)
static void set_storage_by_name(dt_lib_export_t *d, const char *name)
static void _width_changed(GtkEditable *entry, gpointer user_data)
static const char * _blob_string(const char **buf, const char *const end)
static void _get_max_output_dimension(dt_lib_export_t *d, uint32_t *width, uint32_t *height)
static void _lib_export_styles_changed_callback(gpointer instance, gpointer user_data)
void dt_loc_get_datadir(char *datadir, size_t bufsize)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
dt_imageio_module_storage_t * dt_imageio_get_storage()
int dt_imageio_get_index_of_format(dt_imageio_module_format_t *format)
int dt_imageio_get_index_of_storage(dt_imageio_module_storage_t *storage)
void dt_imageio_resizing_factor_parse(const char *str, double *num, double *denum)
dt_imageio_module_format_t * dt_imageio_get_format()
dt_imageio_module_format_t * dt_imageio_get_format_by_name(const char *name)
dt_imageio_module_storage_t * dt_imageio_get_storage_by_name(const char *name)
GtkWidget * dt_ui_section_label_new(const gchar *str)
static const dt_iop_drawlayer_params_t * params
void dt_lib_cancel_postponed_update(dt_lib_module_t *mod)
GtkWidget * dt_action_button_new(dt_lib_module_t *self, const gchar *label, gpointer callback, gpointer data, const gchar *tooltip, guint accel_key, GdkModifierType mods)
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.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
dt_mipmap_buffer_dsc_flags flags
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
void dt_osx_disallow_fullscreen(GtkWidget *widget)
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
void dt_module_preset_free(gpointer data)
Release one dt_module_preset_t. Suits g_list_free_full().
GList * dt_preset_repository_list_all_versions(const char *operation)
Every preset of operation at ANY version, with rowid and op_version filled in, SHIPPED FIRST then by ...
void dt_preset_repository_update_params_by_rowid(const int rowid, const int op_version, const void *params, const int params_size)
Replace the parameters of one row, by rowid.
void dt_preset_repository_delete_by_rowid(const int rowid)
Delete one row by rowid.
data.presets: a module's saved parameters, with the conditions under which it auto-applies.
static dt_colorspaces_color_profile_type_t sanitize_colorspaces(dt_colorspaces_color_profile_type_t colorspace)
Coerce an integer read back from storage into a colour space this build still has.
@ DT_COLORSPACE_FILE
A user ICC file on disk; the only type whose filename is meaningful.
@ DT_COLORSPACE_SRGB
sRGB – registered TWICE, and the two entries are not interchangeable.
@ DT_COLORSPACE_NONE
No profile / "take it from the image settings". Never matches a list entry.
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_LIN_REC709
@ DT_PROFILE_ROLE_OUTPUT
Listed in the output/export-profile combo (colorout, export).
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_STYLE_CHANGED
This signal is raised when a style is added/deleted/changed
@ DT_SIGNAL_IMAGEIO_STORAGE_CHANGE
This signal is raised when a new storage module is loaded noparameters no return.
@ DT_SIGNAL_SELECTION_CHANGED
This signal is raised when the selection is changed no param, no returned value.
@ DT_SIGNAL_COLLECTION_CHANGED
This signal is raised when collection changed. To avoid leaking the list, dt_collection_t is connecte...
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
static const dt_aligned_pixel_simd_t value
void dt_style_free(gpointer data)
GList * dt_styles_get_list(const char *filter)
A profile's public identity: what the GUI displays and stores, and nothing else.
dt_colorspaces_color_profile_type_t type
what to store in params / conf
char name[512]
translated, display-ready
char filename[DT_IOP_COLOR_ICC_LEN]
"" unless type == DT_COLORSPACE_FILE
const gchar * icc_filename
const gchar * metadata_export
dt_colorspaces_color_profile_type_t icc_type
dt_iop_color_intent_t icc_intent
GtkButton * export_button
GtkWidget * storage_extra_container
uint32_t max_allowed_width
GtkWidget * dimensions_type
GtkWidget * format_extra_container
uint32_t max_allowed_height
typedef double((*spd)(unsigned long int wavelength, double TempK))