78#ifdef GDK_WINDOWING_QUARTZ
81#include <gdk/gdkkeysyms.h>
92#define EXPORT_MAX_IMAGE_SIZE UINT16_MAX
93#define CONFIG_PREFIX "plugins/lighttable/export/"
131#define INCH_TO_CM (2.54f)
135 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(self->
print_dpi)));
136 return ((
float)pix *
INCH_TO_CM) / (float)dpi;
141 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(self->
print_dpi)));
142 return (
float)pix / (float)dpi;
147 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(self->
print_dpi)));
153 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(self->
print_dpi)));
154 return ceilf(inch * (
float)dpi);
205 static const char *
v[] = {
"special", NULL};
226 gtk_widget_set_sensitive(GTK_WIDGET(
d->export_button), has_act_on && format_index != -1 && storage_index != -1);
248 double num = 1.0, denum = 1.0;
253 gchar *pdiv = strchr(scale_str,
'/');
255 gchar scale_buf[64] =
"";
260 sprintf(_str,
"%d", (
int) num);
261 g_strlcat(scale_buf, _str,
sizeof(scale_buf));
265 g_strlcat(scale_buf, scale_str,
sizeof(scale_buf));
268 else if(pdiv-scale_str == 0)
270 if(
_is_int(denum) && denum > 0.0)
272 sprintf(_str,
"%d", (
int) denum);
273 g_strlcat(scale_buf, _str,
sizeof(scale_buf));
277 g_strlcat(scale_buf,
"1/",
sizeof(scale_buf));
278 g_strlcat(scale_buf, pdiv+1,
sizeof(scale_buf));
285 sprintf(_str,
"%d", (
int) num);
286 g_strlcat(scale_buf, _str,
sizeof(scale_buf));
290 g_strlcat(scale_buf, scale_str,
sizeof(scale_buf));
292 g_strlcat(scale_buf,
"/",
sizeof(scale_buf));
293 if(
_is_int(denum) && denum > 0.0)
295 sprintf(_str,
"%d", (
int) denum);
296 g_strlcat(scale_buf, _str,
sizeof(scale_buf));
300 g_strlcat(scale_buf, pdiv+1,
sizeof(scale_buf));
313 char style[128] = { 0 };
322 if(format_index == -1)
327 if(storage_index == -1)
333 char *confirm_message = NULL;
335 if(mstorage->ask_user_confirmation)
336 confirm_message = mstorage->ask_user_confirmation(mstorage);
340 GtkWidget *dialog = gtk_message_dialog_new(
341 GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
342 "%s", confirm_message);
343#ifdef GDK_WINDOWING_QUARTZ
347 gtk_window_set_title(GTK_WINDOW(dialog), _(
"export to disk"));
348 const gint res = gtk_dialog_run(GTK_DIALOG(dialog));
349 gtk_widget_destroy(dialog);
352 if(res != GTK_RESPONSE_YES)
366 g_strlcpy(style, tmp,
sizeof(style));
375 style, icc_type, icc_filename, icc_intent,
d->metadata_export);
385 const char *validSign =
",.0123456789";
386 const gchar *
value = gtk_entry_get_text(spin);
388 const int len =
sizeof(
value);
389 int i, j = 0, idec = 0, idiv = 0, pdiv = 0;
390 char new_value[30] =
"";
392 for (
i = 0;
i < len;
i++)
394 char *val = strchr(validSign,
value[
i]);
401 new_value[j++] =
'1';
405 if(atof(
value) == 0.0)
411 new_value[j++] =
'/';
416 else if((val[0] ==
'.') || (val[0] ==
','))
420 if((
i == 0) || (
i == pdiv))
422 new_value[j++] =
'0';
427 new_value[j++] =
value[
i];
437 new_value[j++] =
value[
i];
441 gtk_entry_set_text(spin, new_value);
444static void _width_changed(GtkEditable *entry, gpointer user_data);
449 if(event->button == 2)
453 gtk_entry_set_text(GTK_ENTRY(spin),
"1");
465 if(event->button == 2)
469 gtk_entry_set_text(GTK_ENTRY(spin),
"0");
470 g_signal_handlers_unblock_by_func(spin,
_width_changed, user_data);
480 if(event->button == 2)
484 gtk_entry_set_text(GTK_ENTRY(spin),
"0");
499 gtk_widget_hide(
d->size_in_px);
503 gtk_widget_show(
d->size_in_px);
504 gchar size_in_px_txt[120];
505 snprintf(size_in_px_txt,
sizeof(size_in_px_txt) /
sizeof(size_in_px_txt[0]), _(
"which is equal to %s \303\227 %s px"),
506 gtk_entry_get_text(GTK_ENTRY(
d->width)), gtk_entry_get_text(GTK_ENTRY(
d->height)));
507 gtk_label_set_text(GTK_LABEL(
d->size_in_px), size_in_px_txt);
513 gchar *max_width_char = g_strdup_printf(
"%d", max_width);
514 gchar *max_height_char = g_strdup_printf(
"%d", max_height);
517 gtk_entry_set_text(GTK_ENTRY(
d->width), max_width_char);
518 gtk_entry_set_text(GTK_ENTRY(
d->height), max_height_char);
539 gtk_label_set_text(GTK_LABEL(self->
unit_label),
572 && icctype == pp->
type
600 if(mformat) mformat->gui_reset(mformat);
602 if(mstorage) mstorage->gui_reset(mstorage);
616 module = (dt_imageio_module_format_t *)it->data;
623 gtk_widget_hide(
d->format_extra_container);
626 else if(module->widget)
628 gtk_widget_show_all(
d->format_extra_container);
629 gtk_stack_set_visible_child(GTK_STACK(
d->format_extra_container), module->widget);
633 gtk_widget_hide(
d->format_extra_container);
647 const gboolean support_layers = (
module->flags(NULL) & FORMAT_FLAGS_SUPPORT_LAYERS) == FORMAT_FLAGS_SUPPORT_LAYERS;
648 const gboolean is_enabled = gtk_widget_get_sensitive(
d->export_masks);
649 if(support_layers && !is_enabled)
653 gtk_widget_set_sensitive(GTK_WIDGET(
d->export_masks),
TRUE);
656 else if(!support_layers && is_enabled)
662 gtk_widget_set_sensitive(GTK_WIDGET(
d->export_masks),
FALSE);
682 if(storage && format)
684 uint32_t fw, fh, sw, sh;
685 fw = fh = sw = sh = 0;
686 storage->dimension(storage, NULL, &sw, &sh);
687 format->dimension(format, NULL, &fw, &fh);
689 if(sw == 0 || fw == 0)
690 *
width = sw > fw ? sw : fw;
692 *
width = sw < fw ? sw : fw;
694 if(sh == 0 || fh == 0)
695 *
height = sh > fh ? sh : fh;
697 *
height = sh < fh ? sh : fh;
704 uint32_t
width = atoi(gtk_entry_get_text(GTK_ENTRY(
d->width)));
705 uint32_t
height = atoi(gtk_entry_get_text(GTK_ENTRY(
d->height)));
706 if(
width >
d->max_allowed_width ||
height >
d->max_allowed_height)
716 uint32_t max_w = 0, max_h = 0;
741 gtk_widget_hide(
d->storage_extra_container);
744 else if(module->widget)
746 gtk_widget_show_all(
d->storage_extra_container);
747 gtk_stack_set_visible_child(GTK_STACK(
d->storage_extra_container),module->widget);
751 gtk_widget_hide(
d->storage_extra_container);
759 uint32_t w = 0, h = 0;
760 module->recommended_dimension(module, NULL, &w, &h);
766 if(w > cw || w == 0) w = cw;
767 if(h >
ch || h == 0) h =
ch;
856 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(self->
print_dpi)));
862 gchar *pwidth = g_strdup_printf(
"%.2f", p_width);
863 gchar *pheight = g_strdup_printf(
"%.2f", p_height);
864 gchar *pdpi = g_strdup_printf(
"%d", dpi);
865 gtk_entry_set_text(GTK_ENTRY(self->
print_width), pwidth);
866 gtk_entry_set_text(GTK_ENTRY(self->
print_height), pheight);
867 gtk_entry_set_text(GTK_ENTRY(self->
print_dpi), pdpi);
878 const float p_width = atof(gtk_entry_get_text(GTK_ENTRY(self->
print_width)));
879 const float p_height = atof(gtk_entry_get_text(GTK_ENTRY(self->
print_height)));
888 gchar *pwidth = g_strdup_printf(
"%d",
width);
889 gchar *pheight = g_strdup_printf(
"%d",
height);
890 gtk_entry_set_text(GTK_ENTRY(self->
width), pwidth);
891 gtk_entry_set_text(GTK_ENTRY(self->
height), pheight);
902 const uint32_t
width = atoi(gtk_entry_get_text(GTK_ENTRY(
d->width)));
912 const float p_width = atof(gtk_entry_get_text(GTK_ENTRY(
d->print_width)));
917 gchar *pwidth = g_strdup_printf(
"%d",
width);
918 gtk_entry_set_text(GTK_ENTRY(
d->width), pwidth);
929 const uint32_t
height = atoi(gtk_entry_get_text(GTK_ENTRY(
d->height)));
939 const float p_height = atof(gtk_entry_get_text(GTK_ENTRY(
d->print_height)));
944 gchar *pheight = g_strdup_printf(
"%d",
height);
945 gtk_entry_set_text(GTK_ENTRY(
d->height), pheight);
956 const int dpi = atoi(gtk_entry_get_text(GTK_ENTRY(
d->print_dpi)));
967 const char *
key = (
const char *)user_data;
1005 gboolean empty =
TRUE;
1009 if(storage->supported(storage, format))
1016 gtk_widget_set_sensitive(GTK_WIDGET(
d->format), !empty);
1033 gtk_container_add(GTK_CONTAINER(
d->storage_extra_container), module->widget);
1048 for(
const GList *st_iter = styles; st_iter; st_iter = g_list_next(st_iter))
1063 const gboolean ondisk =
name && !g_strcmp0(
name, _(
"file on disk"));
1069 GtkWidget *mi = gtk_menu_item_new_with_label(_(
"preferences..."));
1071 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1078 self->
data = (
void *)
d;
1089 d->storage_extra_container = gtk_stack_new();
1090 gtk_stack_set_homogeneous(GTK_STACK(
d->storage_extra_container),
FALSE);
1091 gtk_box_pack_start(GTK_BOX(self->
widget),
d->storage_extra_container,
FALSE,
TRUE, 0);
1098 gtk_container_add(GTK_CONTAINER(
d->storage_extra_container), module->widget);
1105 g_signal_connect(G_OBJECT(
d->storage),
"value-changed", G_CALLBACK(
_storage_changed), (gpointer)
d);
1113 g_signal_connect(G_OBJECT(
d->format),
"value-changed", G_CALLBACK(
_format_changed), (gpointer)
d);
1116 d->format_extra_container = gtk_stack_new();
1117 gtk_stack_set_homogeneous(GTK_STACK(
d->format_extra_container),
FALSE);
1118 gtk_box_pack_start(GTK_BOX(self->
widget),
d->format_extra_container,
FALSE,
TRUE, 0);
1125 gtk_container_add(GTK_CONTAINER(
d->format_extra_container), module->widget);
1133 _(
"Choose a method for setting the output size.\n"
1134 "The width and height specified define the bounding box\n"
1135 "in which the image will be proportionnaly fitted.\n"),
1138 N_(
"in pixels (for file)"),
1139 N_(
"in cm (for print)"),
1140 N_(
"in inch (for print)"),
1141 N_(
"by scale (for file)"),
1142 N_(
"original resolution"));
1144 d->print_width = gtk_entry_new();
1146 gtk_widget_set_tooltip_text(
d->print_width, _(
"maximum output width limit.\n"
1147 "click middle mouse button to reset to 0."));
1148 gtk_entry_set_width_chars(GTK_ENTRY(
d->print_width), 5);
1149 d->print_height = gtk_entry_new();
1151 gtk_widget_set_tooltip_text(
d->print_height, _(
"maximum output height limit.\n"
1152 "click middle mouse button to reset to 0."));
1153 gtk_entry_set_width_chars(GTK_ENTRY(
d->print_height), 5);
1154 d->print_dpi = gtk_entry_new();
1156 gtk_widget_set_tooltip_text(
d->print_dpi, _(
"resolution in dot per inch"));
1157 gtk_entry_set_width_chars(GTK_ENTRY(
d->print_dpi), 4);
1159 gtk_entry_set_text(GTK_ENTRY(
d->print_dpi), dpi);
1162 d->width = gtk_entry_new();
1164 gtk_widget_set_tooltip_text(
d->width, _(
"maximum output width limit.\n"
1165 "click middle mouse button to reset to 0."));
1166 gtk_entry_set_width_chars(GTK_ENTRY(
d->width), 5);
1167 d->height = gtk_entry_new();
1169 gtk_widget_set_tooltip_text(
d->height, _(
"maximum output height limit.\n"
1170 "click middle mouse button to reset to 0."));
1171 gtk_entry_set_width_chars(GTK_ENTRY(
d->height), 5);
1173 gtk_widget_add_events(
d->width, GDK_BUTTON_PRESS_MASK);
1174 gtk_widget_add_events(
d->height, GDK_BUTTON_PRESS_MASK);
1177 d->print_size = gtk_flow_box_new();
1178 gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(
d->print_size), 5);
1179 gtk_flow_box_set_column_spacing (GTK_FLOW_BOX(
d->print_size), 3);
1180 gtk_container_add(GTK_CONTAINER(
d->print_size),
d->print_width);
1181 gtk_container_add(GTK_CONTAINER(
d->print_size), gtk_label_new(_(
"x")));
1182 gtk_container_add(GTK_CONTAINER(
d->print_size),
d->print_height);
1183 d->unit_label = gtk_label_new(_(
"cm"));
1184 gtk_container_add(GTK_CONTAINER(
d->print_size),
d->unit_label);
1185 GtkBox *dpi_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
1186 gtk_box_pack_start(dpi_box, gtk_label_new(_(
"@")),
FALSE,
FALSE, 0);
1187 gtk_box_pack_start(dpi_box,
d->print_dpi,
TRUE,
TRUE, 0);
1188 gtk_box_pack_start(dpi_box, gtk_label_new(_(
"dpi")),
FALSE,
FALSE, 0);
1189 gtk_container_add(GTK_CONTAINER(
d->print_size), GTK_WIDGET(dpi_box));
1190 gtk_container_foreach(GTK_CONTAINER(
d->print_size), (GtkCallback)gtk_widget_set_can_focus, GINT_TO_POINTER(
FALSE));
1192 d->px_size = gtk_flow_box_new();
1193 gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(
d->px_size), 3);
1194 gtk_flow_box_set_column_spacing (GTK_FLOW_BOX(
d->px_size), 3);
1195 gtk_container_add(GTK_CONTAINER(
d->px_size),
d->width);
1196 gtk_container_add(GTK_CONTAINER(
d->px_size), gtk_label_new(_(
"x")));
1197 GtkBox *px_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
1198 gtk_box_pack_start(px_box,
d->height,
TRUE,
TRUE, 0);
1199 gtk_box_pack_start(px_box, gtk_label_new(_(
"px")),
FALSE,
FALSE, 0);
1200 gtk_container_add(GTK_CONTAINER(
d->px_size), GTK_WIDGET(px_box));
1201 gtk_container_foreach(GTK_CONTAINER(
d->px_size), (GtkCallback)gtk_widget_set_can_focus, GINT_TO_POINTER(
FALSE));
1203 d->scale = gtk_entry_new();
1205 gtk_entry_set_width_chars(GTK_ENTRY(
d->scale), 5);
1207 gtk_widget_set_tooltip_text(
d->scale, _(
"it can be an integer, decimal number or simple fraction.\n"
1208 "zero or empty values are equal to 1.\n"
1209 "click middle mouse button to reset to 1."));
1210 gtk_widget_set_halign(GTK_WIDGET(
d->scale), GTK_ALIGN_END);
1211 gtk_widget_add_events(
d->scale, GDK_BUTTON_PRESS_MASK);
1213 d->size_in_px = gtk_label_new(
"");
1214 gtk_label_set_ellipsize(GTK_LABEL(
d->size_in_px), PANGO_ELLIPSIZE_START);
1215 gtk_widget_set_sensitive(GTK_WIDGET(
d->size_in_px),
FALSE);
1217 gtk_widget_set_halign(GTK_WIDGET(
d->scale), GTK_ALIGN_FILL);
1218 gtk_widget_set_halign(GTK_WIDGET(
d->size_in_px), GTK_ALIGN_END);
1220 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->dimensions_type),
FALSE,
FALSE, 0);
1221 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->px_size),
FALSE,
FALSE, 0);
1222 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->print_size),
FALSE,
FALSE, 0);
1223 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->scale),
FALSE,
FALSE, 0);
1224 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->size_in_px),
FALSE,
FALSE, 0);
1230 gtk_widget_set_tooltip_text(
d->export_masks, _(
"store masks as layers in exported images. only works for some formats."));
1231 gtk_box_pack_start(GTK_BOX(self->
widget),
d->export_masks,
FALSE,
TRUE, 0);
1253 char *system_profile_dir = g_build_filename(datadir,
"color",
"out", NULL);
1254 char *user_profile_dir = g_build_filename(confdir,
"color",
"out", NULL);
1255 char *
tooltip = g_strdup_printf(_(
1256 "RGB color space used to encode the output files.\n"
1257 "\"same as original\" exports to the same space as the original\n"
1258 "picture, which is linear sensor RGB for raw pictures.\n"
1259 "sRGB is recommended in most cases.\n"
1260 "You can use custom color spaces defined\n"
1261 "by ICC profiles stored in:\n- %s\n- %s"), user_profile_dir, system_profile_dir);
1262 gtk_widget_set_tooltip_text(
d->profile,
tooltip);
1278 tooltip = g_strdup_printf(_(
"• perceptual: "
1279 "smoothly moves out-of-gamut colors into gamut,"
1280 "preserving gradations, but distorts in-gamut colors in the process."
1281 " note that perceptual is often a proprietary LUT that depends"
1282 " on the destination space."
1285 "• relative colorimetric: "
1286 "keeps luminance while reducing as little as possible saturation"
1287 " until colors fit in gamut."
1291 "designed to present eye-catching business graphics"
1292 " by preserving the saturation. (not suited for photography)."
1295 "• absolute colorimetric: "
1296 "adapt white point of the image to the white point of the"
1297 " destination medium and do nothing else. mainly used when"
1298 " proofing colors. (not suited for photography)."
1301 gtk_widget_set_tooltip_text(
d->intent,
tooltip);
1310 gtk_widget_set_tooltip_text(
d->style, _(
"temporary style to use while exporting"));
1313 g_signal_connect(G_OBJECT(
d->export_masks),
"value-changed", G_CALLBACK(
_callback_bool),
1315 g_signal_connect(G_OBJECT(
d->intent),
"value-changed", G_CALLBACK(
_intent_changed), (gpointer)
d);
1316 g_signal_connect(G_OBJECT(
d->profile),
"value-changed", G_CALLBACK(
_profile_changed), (gpointer)
d);
1317 g_signal_connect(G_OBJECT(
d->style),
"value-changed", G_CALLBACK(
_style_changed), (gpointer)
d);
1323 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(hbox),
FALSE,
TRUE, 0);
1327 _(
"export with current settings"), GDK_KEY_e, GDK_CONTROL_MASK));
1328 gtk_box_pack_start(hbox, GTK_WIDGET(
d->export_button),
TRUE,
TRUE, 0);
1330 g_signal_connect(G_OBJECT(
d->width),
"changed", G_CALLBACK(
_width_changed), (gpointer)
d);
1331 g_signal_connect(G_OBJECT(
d->height),
"changed", G_CALLBACK(
_height_changed), (gpointer)
d);
1334 g_signal_connect(G_OBJECT(
d->print_dpi),
"changed", G_CALLBACK(
_print_dpi_changed), (gpointer)
d);
1336 g_signal_connect(G_OBJECT(
d->width),
"changed", G_CALLBACK(
_width_changed), (gpointer)
d);
1337 g_signal_connect(G_OBJECT(
d->height),
"changed", G_CALLBACK(
_height_changed), (gpointer)
d);
1339 g_signal_connect(G_OBJECT(
d->width),
"button-press-event", G_CALLBACK(
_widht_mdlclick), (gpointer)
d);
1340 g_signal_connect(G_OBJECT(
d->height),
"button-press-event", G_CALLBACK(
_height_mdlclick), (gpointer)
d);
1341 g_signal_connect(G_OBJECT(
d->print_width),
"button-press-event", G_CALLBACK(
_widht_mdlclick), (gpointer)
d);
1342 g_signal_connect(G_OBJECT(
d->print_height),
"button-press-event", G_CALLBACK(
_height_mdlclick), (gpointer)
d);
1344 g_signal_connect(G_OBJECT(
d->scale),
"button-press-event", G_CALLBACK(
_scale_mdlclick), (gpointer)
d);
1345 g_signal_connect(G_OBJECT(
d->scale),
"changed", G_CALLBACK(
_scale_changed), (gpointer)
d);
1348 gtk_widget_show_all(self->
widget);
1349 gtk_widget_set_no_show_all(self->
widget,
TRUE);
1352 gtk_entry_set_text(GTK_ENTRY(
d->width), setting);
1354 gtk_entry_set_text(GTK_ENTRY(
d->height), setting);
1383 && icctype == pp->
type
1396 gboolean rc =
FALSE;
1431 if(module->widget && GTK_IS_CONTAINER(
d->storage_extra_container)) gtk_container_remove(GTK_CONTAINER(
d->storage_extra_container),
module->widget);
1437 if(module->widget && GTK_IS_CONTAINER(
d->format_extra_container)) gtk_container_remove(GTK_CONTAINER(
d->format_extra_container),
module->widget);
1466 const int version = self->version();
1472 "SELECT rowid, op_version, op_params, name FROM data.presets WHERE operation='export'", -1,
1476 sqlite3_reset(stmt);
1477 sqlite3_clear_bindings(stmt);
1478 while(sqlite3_step(stmt) == SQLITE_ROW)
1480 const int rowid = sqlite3_column_int(stmt, 0);
1481 const int op_version = sqlite3_column_int(stmt, 1);
1482 const void *op_params = (
void *)sqlite3_column_blob(stmt, 2);
1483 const size_t op_params_size = sqlite3_column_bytes(stmt, 2);
1484 const char *
name = (
char *)sqlite3_column_text(stmt, 3);
1486 if(op_version != version)
1489 fprintf(stderr,
"[export_init_presets] found export preset '%s' with version %d, version %d was "
1490 "expected. dropping preset.\n",
1491 name, op_version, version);
1492 sqlite3_stmt *innerstmt;
1494 "DELETE FROM data.presets WHERE rowid=?1", -1,
1497 sqlite3_step(innerstmt);
1498 sqlite3_finalize(innerstmt);
1503 const char *buf = (
const char *)op_params;
1506 buf += 6 *
sizeof(int32_t);
1508 buf += strlen(buf) + 1;
1510 buf += strlen(buf) + 1;
1513 const char *fname = buf;
1514 buf += strlen(fname) + 1;
1515 const char *sname = buf;
1516 buf += strlen(sname) + 1;
1521 if(!fmod || !smod)
continue;
1524 size_t copy_over_part = (
void *)buf - (
void *)op_params;
1526 const int fversion = *(
const int *)buf;
1527 buf +=
sizeof(int32_t);
1528 const int sversion = *(
const int *)buf;
1529 buf +=
sizeof(int32_t);
1530 const int fsize = *(
const int *)buf;
1531 buf +=
sizeof(int32_t);
1532 const int ssize = *(
const int *)buf;
1533 buf +=
sizeof(int32_t);
1535 const void *fdata = buf;
1537 const void *sdata = buf;
1539 void *new_fdata = NULL, *new_sdata = NULL;
1540 size_t new_fsize = fsize, new_ssize = ssize;
1541 const int32_t new_fversion = fmod->version(), new_sversion = smod->version();
1543 if(fversion < new_fversion)
1545 if(!(fmod->legacy_params
1546 && (new_fdata = fmod->legacy_params(fmod, fdata, fsize, fversion, new_fversion, &new_fsize))
1551 if(sversion < new_sversion)
1553 if(!(smod->legacy_params
1554 && (new_sdata = smod->legacy_params(smod, sdata, ssize, sversion, new_sversion, &new_ssize))
1559 if(new_fdata || new_sdata)
1562 const size_t new_params_size = op_params_size - (fsize + ssize) + (new_fsize + new_ssize);
1563 void *new_params = malloc(new_params_size);
1564 memcpy(new_params, op_params, copy_over_part);
1566 size_t pos = copy_over_part;
1567 memcpy((uint8_t *)new_params + pos, &new_fversion,
sizeof(int32_t));
1568 pos +=
sizeof(int32_t);
1569 memcpy((uint8_t *)new_params + pos, &new_sversion,
sizeof(int32_t));
1570 pos +=
sizeof(int32_t);
1571 memcpy((uint8_t *)new_params + pos, &new_fsize,
sizeof(int32_t));
1572 pos +=
sizeof(int32_t);
1573 memcpy((uint8_t *)new_params + pos, &new_ssize,
sizeof(int32_t));
1574 pos +=
sizeof(int32_t);
1576 memcpy((uint8_t *)new_params + pos, new_fdata, new_fsize);
1578 memcpy((uint8_t *)new_params + pos, fdata, fsize);
1581 memcpy((uint8_t *)new_params + pos, new_sdata, new_ssize);
1583 memcpy((uint8_t *)new_params + pos, sdata, ssize);
1587 "[export_init_presets] updating export preset '%s' from versions %d/%d to versions %d/%d\n",
1588 name, fversion, sversion, new_fversion, new_sversion);
1589 sqlite3_stmt *innerstmt;
1591 "UPDATE data.presets SET op_params=?1 WHERE rowid=?2",
1592 -1, &innerstmt, NULL);
1595 sqlite3_step(innerstmt);
1596 sqlite3_finalize(innerstmt);
1608 fprintf(stderr,
"[export_init_presets] export preset '%s' can't be updated from versions %d/%d to "
1609 "versions %d/%d. dropping preset\n",
1610 name, fversion, sversion, new_fversion, new_sversion);
1611 sqlite3_stmt *innerstmt;
1613 "DELETE FROM data.presets WHERE rowid=?1", -1,
1616 sqlite3_step(innerstmt);
1617 sqlite3_finalize(innerstmt);
1620 sqlite3_reset(stmt);
1621 sqlite3_clear_bindings(stmt);
1625 const int old_version,
int *new_version,
size_t *new_size)
1627 if(old_version == 1)
1630 const size_t new_params_size = old_params_size + 2 *
sizeof(int32_t);
1631 void *new_params = malloc(new_params_size);
1633 const char *buf = (
const char *)old_params;
1636 buf += 3 *
sizeof(int32_t);
1638 buf += strlen(buf) + 1;
1641 const char *fname = buf;
1642 buf += strlen(fname) + 1;
1643 const char *sname = buf;
1644 buf += strlen(sname) + 1;
1658 size_t first_half = (
void *)buf - (
void *)old_params;
1659 memcpy(new_params, old_params, first_half);
1662 int32_t fversion = 1;
1663 int32_t sversion = (strcmp(sname,
"picasa") == 0 ? 2 : 1);
1664 memcpy((uint8_t *)new_params + first_half, &fversion,
sizeof(int32_t));
1665 memcpy((uint8_t *)new_params + first_half +
sizeof(int32_t), &sversion,
sizeof(int32_t));
1667 memcpy((uint8_t *)new_params + first_half +
sizeof(int32_t) * 2, buf, old_params_size - first_half);
1669 *new_size = new_params_size;
1673 else if(old_version == 2)
1676 const size_t new_params_size = old_params_size +
sizeof(int32_t);
1677 void *new_params = calloc(1, new_params_size);
1679 memcpy(new_params, old_params,
sizeof(int32_t) * 2);
1680 memcpy((uint8_t *)new_params +
sizeof(int32_t) * 3, (uint8_t *)old_params +
sizeof(int32_t) * 2, old_params_size -
sizeof(int32_t) * 2);
1682 *new_size = new_params_size;
1686 else if(old_version == 3)
1698 const char *buf = (
const char *)old_params;
1701 const char *iccprofile = buf + 4 *
sizeof(int32_t);
1703 size_t new_params_size = old_params_size - strlen(iccprofile) +
sizeof(int32_t);
1705 const char *iccfilename =
"";
1707 if(!strcmp(iccprofile,
"image"))
1709 else if(!strcmp(iccprofile,
"sRGB"))
1711 else if(!strcmp(iccprofile,
"linear_rec709_rgb") || !strcmp(iccprofile,
"linear_rgb"))
1713 else if(!strcmp(iccprofile,
"linear_rec2020_rgb"))
1715 else if(!strcmp(iccprofile,
"adobergb"))
1720 iccfilename = iccprofile;
1721 new_params_size += strlen(iccfilename);
1724 void *new_params = calloc(1, new_params_size);
1726 memcpy(new_params, old_params,
sizeof(int32_t) * 4);
1727 pos += 4 *
sizeof(int32_t);
1728 memcpy((uint8_t *)new_params + pos, &icctype,
sizeof(int32_t));
1729 pos +=
sizeof(int32_t);
1730 memcpy((uint8_t *)new_params + pos, iccfilename, strlen(iccfilename) + 1);
1731 pos += strlen(iccfilename) + 1;
1732 size_t old_pos = 4 *
sizeof(int32_t) + strlen(iccprofile) + 1;
1733 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + old_pos, old_params_size - old_pos);
1735 *new_size = new_params_size;
1739 else if(old_version == 4)
1752 const size_t new_params_size = old_params_size +
sizeof(int32_t);
1753 void *new_params = calloc(1, new_params_size);
1756 memcpy(new_params, old_params,
sizeof(int32_t) * 3);
1757 pos += 4 *
sizeof(int32_t);
1758 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + pos -
sizeof(int32_t), old_params_size -
sizeof(int32_t) * 3);
1760 *new_size = new_params_size;
1764 else if(old_version == 5)
1780 const int flags_size = strlen(
flags) + 1;
1781 const size_t new_params_size = old_params_size + flags_size;
1782 void *new_params = calloc(1, new_params_size);
1784 memcpy(new_params, old_params,
sizeof(int32_t) * 6);
1785 pos += 6 *
sizeof(int32_t);
1786 memcpy((uint8_t *)new_params + pos,
flags, flags_size);
1788 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + pos - flags_size, old_params_size -
sizeof(int32_t) * 6);
1791 *new_size = new_params_size;
1795 else if(old_version == 6)
1806 const size_t new_params_size = old_params_size +
sizeof(int32_t);
1807 void *new_params = calloc(1, new_params_size);
1810 memcpy(new_params, old_params,
sizeof(int32_t) * 4);
1811 pos += 5 *
sizeof(int32_t);
1812 memcpy((uint8_t *)new_params + pos, (uint8_t *)old_params + pos -
sizeof(int32_t), old_params_size -
sizeof(int32_t) * 4);
1814 *new_size = new_params_size;
1831 size_t fsize = mformat->params_size(mformat);
1833 size_t ssize = mstorage->params_size(mstorage);
1834 void *sdata = mstorage->get_params(mstorage);
1835 const int32_t fversion = mformat->version();
1836 const int32_t sversion = mstorage->version();
1857 const int32_t upscale =
FALSE;
1858 const int32_t high_quality =
TRUE;
1862 const char *metadata_export =
d->metadata_export;
1866 g_strlcpy(fdata->
style, style,
sizeof(fdata->
style));
1874 if(!iccfilename) iccfilename = g_strdup(
"");
1875 if(
IS_NULL_PTR(metadata_export)) metadata_export = g_strdup(
"");
1879 const int32_t fname_len = strlen(fname);
1880 const int32_t sname_len = strlen(sname);
1882 *
size = fname_len + sname_len + 2 + 4 *
sizeof(int32_t) + fsize + ssize + 7 *
sizeof(int32_t)
1883 + strlen(iccfilename) + 1 + strlen(metadata_export) + 1;
1885 char *params = (
char *)calloc(1, *
size);
1887 memcpy(params + pos, &max_width,
sizeof(int32_t));
1888 pos +=
sizeof(int32_t);
1889 memcpy(params + pos, &max_height,
sizeof(int32_t));
1890 pos +=
sizeof(int32_t);
1891 memcpy(params + pos, &upscale,
sizeof(int32_t));
1892 pos +=
sizeof(int32_t);
1893 memcpy(params + pos, &high_quality,
sizeof(int32_t));
1894 pos +=
sizeof(int32_t);
1895 memcpy(params + pos, &export_masks,
sizeof(int32_t));
1896 pos +=
sizeof(int32_t);
1897 memcpy(params + pos, &iccintent,
sizeof(int32_t));
1898 pos +=
sizeof(int32_t);
1899 memcpy(params + pos, &icctype,
sizeof(int32_t));
1900 pos +=
sizeof(int32_t);
1901 memcpy(params + pos, metadata_export, strlen(metadata_export) + 1);
1902 pos += strlen(metadata_export) + 1;
1903 memcpy(params + pos, iccfilename, strlen(iccfilename) + 1);
1904 pos += strlen(iccfilename) + 1;
1905 memcpy(params + pos, fname, fname_len + 1);
1906 pos += fname_len + 1;
1907 memcpy(params + pos, sname, sname_len + 1);
1908 pos += sname_len + 1;
1909 memcpy(params + pos, &fversion,
sizeof(int32_t));
1910 pos +=
sizeof(int32_t);
1911 memcpy(params + pos, &sversion,
sizeof(int32_t));
1912 pos +=
sizeof(int32_t);
1913 memcpy(params + pos, &fsize,
sizeof(int32_t));
1914 pos +=
sizeof(int32_t);
1915 memcpy(params + pos, &ssize,
sizeof(int32_t));
1916 pos +=
sizeof(int32_t);
1919 memcpy(params + pos, fdata, fsize);
1924 memcpy(params + pos, sdata, ssize);
1927 g_assert(pos == *
size);
1932 if(fdata) mformat->free_params(mformat, fdata);
1933 if(sdata) mstorage->free_params(mstorage, sdata);
1941 const char *buf = (
const char *)params;
1943 const int max_width = *(
const int *)buf;
1944 buf +=
sizeof(int32_t);
1945 const int max_height = *(
const int *)buf;
1946 buf +=
sizeof(int32_t);
1948 buf +=
sizeof(int32_t);
1950 buf +=
sizeof(int32_t);
1951 const int export_masks = *(
const int *)buf;
1952 buf +=
sizeof(int32_t);
1953 const int iccintent = *(
const int *)buf;
1954 buf +=
sizeof(int32_t);
1955 const int icctype = *(
const int *)buf;
1956 buf +=
sizeof(int32_t);
1957 const char *metadata_export = buf;
1958 buf += strlen(metadata_export) + 1;
1960 d->metadata_export = g_strdup(metadata_export);
1962 const char *iccfilename = buf;
1963 buf += strlen(iccfilename) + 1;
1975 && icctype == pp->
type
1985 const char *fname = buf;
1986 buf += strlen(fname) + 1;
1987 const char *sname = buf;
1988 buf += strlen(sname) + 1;
1993 if(!fmod || !smod)
return 1;
1995 const int32_t fversion = *(
const int32_t *)buf;
1996 buf +=
sizeof(int32_t);
1997 const int32_t sversion = *(
const int32_t *)buf;
1998 buf +=
sizeof(int32_t);
2000 const int fsize = *(
const int *)buf;
2001 buf +=
sizeof(int32_t);
2002 const int ssize = *(
const int *)buf;
2003 buf +=
sizeof(int32_t);
2006 != strlen(fname) + strlen(sname) + 2 + 4 *
sizeof(int32_t) + fsize + ssize + 7 *
sizeof(int32_t)
2007 + strlen(iccfilename) + 1 + strlen(metadata_export) + 1)
2009 if(fversion != fmod->version() || sversion != smod->version())
return 1;
2013 if(fdata->
style[0] ==
'\0')
2019 const void *sdata = buf;
2031 if(ssize) res += smod->set_params(smod, sdata, ssize);
2032 if(fsize) res += fmod->set_params(fmod, fdata, fsize);
int dt_act_on_get_images_nb(const gboolean only_visible, const gboolean force)
GList * dt_act_on_get_images()
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
static dt_colorspaces_color_profile_type_t sanitize_colorspaces(dt_colorspaces_color_profile_type_t colorspace)
dt_colorspaces_color_profile_type_t
@ DT_COLORSPACE_LIN_REC2020
@ DT_COLORSPACE_LIN_REC709
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
gchar * dt_conf_get_string(const char *name)
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)
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)
const char * dt_confgen_get(const char *name, dt_confgen_value_kind_t kind)
void dt_control_log(const char *msg,...)
void dt_control_export(GList *imgid_list, int max_width, int max_height, int format_index, int storage_index, gboolean high_quality, gboolean export_masks, char *style, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, const gchar *metadata_export)
#define DT_MODULE(MODVER)
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...
sqlite3 * dt_database_get(const dt_database_t *db)
#define DT_DEBUG_SQLITE3_BIND_BLOB(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
static float pixels2cm(dt_lib_export_t *self, const uint32_t pix)
static void _format_changed(GtkWidget *widget, dt_lib_export_t *d)
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 float pixels2inch(dt_lib_export_t *self, const uint32_t pix)
static void _print_height_changed(GtkEditable *entry, gpointer user_data)
void * get_params(dt_lib_module_t *self, int *size)
static float pixels2print(dt_lib_export_t *self, const uint32_t pix)
void set_preferences(void *menu, dt_lib_module_t *self)
static void _intent_changed(GtkWidget *widget, dt_lib_export_t *d)
static uint32_t inch2pixels(dt_lib_export_t *self, const float inch)
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 void _print_width_changed(GtkEditable *entry, gpointer user_data)
static gboolean _scale_mdlclick(GtkEntry *spin, GdkEventButton *event, dt_lib_export_t *d)
static sqlite3_stmt * _export_presets_stmt
void gui_cleanup(dt_lib_module_t *self)
static uint32_t print2pixels(dt_lib_export_t *self, const float value)
static void _print_dpi_changed(GtkWidget *widget, gpointer user_data)
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 void _validate_dimensions(dt_lib_export_t *d)
void _size_update_display(dt_lib_export_t *self)
#define EXPORT_MAX_IMAGE_SIZE
static void _update_formats_combobox(dt_lib_export_t *d)
void init_presets(dt_lib_module_t *self)
static void _update_dimensions(dt_lib_export_t *d)
static void _resync_print_dimensions(dt_lib_export_t *self)
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)
static void _widht_mdlclick(GtkEntry *spin, GdkEventButton *event, gpointer user_data)
uint32_t container(dt_lib_module_t *self)
static void _height_mdlclick(GtkEntry *spin, GdkEventButton *event, gpointer user_data)
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)
gboolean _is_int(double value)
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 uint32_t cm2pixels(dt_lib_export_t *self, const float cm)
static void set_storage_by_name(dt_lib_export_t *d, const char *name)
static void _width_changed(GtkEditable *entry, gpointer user_data)
static void _get_max_output_dimension(dt_lib_export_t *d, uint32_t *width, uint32_t *height)
static void _resync_pixel_dimensions(dt_lib_export_t *self)
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)
void dt_gui_container_remove_children(GtkContainer *container)
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....
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
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)
gchar * dt_imageio_resizing_factor_get_and_parsing(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)
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
dt_mipmap_buffer_dsc_flags flags
void dt_osx_disallow_fullscreen(GtkWidget *widget)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ 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)
struct _GtkWidget GtkWidget
void dt_style_free(gpointer data)
GList * dt_styles_get_list(const char *filter)
struct dt_imageio_t * imageio
struct dt_gui_gtk_t * gui
struct dt_colorspaces_t * color_profiles
const struct dt_database_t * db
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
dt_colorspaces_color_profile_type_t type
GtkButton * export_button
GtkWidget * storage_extra_container
uint32_t max_allowed_width
GtkWidget * dimensions_type
GtkWidget * format_extra_container
uint32_t max_allowed_height