static int rights_member(lua_State *L) { if(lua_gettop(L) != 3) { const dt_image_t *my_image = checkreadimage(L, 1); GList *res = dt_metadata_get(my_image->id, "Xmp.dc.rights", NULL); if(res) lua_pushstring(L, (char *)res->data); else lua_pushstring(L, ""); releasereadimage(L, my_image); g_list_free_full(res, g_free); return 1; } else { dt_image_t *my_image = checkwriteimage(L, 1); dt_metadata_set(my_image->id, "Xmp.dc.rights", luaL_checkstring(L, 3)); dt_image_synch_xmp(my_image->id); releasewriteimage(L, my_image); return 0; } }
int store (dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality) { dt_imageio_gallery_t *d = (dt_imageio_gallery_t *)sdata; char filename[DT_MAX_PATH_LEN]= {0}; char dirname[DT_MAX_PATH_LEN]= {0}; dt_image_full_path(imgid, dirname, DT_MAX_PATH_LEN); // we're potentially called in parallel. have sequence number synchronized: dt_pthread_mutex_lock(&darktable.plugin_threadsafe); { char tmp_dir[DT_MAX_PATH_LEN]; dt_variables_expand(d->vp, d->filename, TRUE); g_strlcpy(tmp_dir, dt_variables_get_result(d->vp), DT_MAX_PATH_LEN); // if filenamepattern is a directory just let att ${FILE_NAME} as default.. if ( g_file_test(tmp_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) || ((d->filename+strlen(d->filename)-1)[0]=='/' || (d->filename+strlen(d->filename)-1)[0]=='\\') ) snprintf (d->filename+strlen(d->filename), DT_MAX_PATH_LEN-strlen(d->filename), "/$(FILE_NAME)"); // avoid braindead export which is bound to overwrite at random: if(total > 1 && !g_strrstr(d->filename, "$")) { snprintf(d->filename+strlen(d->filename), DT_MAX_PATH_LEN-strlen(d->filename), "_$(SEQUENCE)"); } gchar* fixed_path = dt_util_fix_path(d->filename); g_strlcpy(d->filename, fixed_path, DT_MAX_PATH_LEN); g_free(fixed_path); d->vp->filename = dirname; d->vp->jobcode = "export"; d->vp->imgid = imgid; d->vp->sequence = num; dt_variables_expand(d->vp, d->filename, TRUE); g_strlcpy(filename, dt_variables_get_result(d->vp), DT_MAX_PATH_LEN); g_strlcpy(dirname, filename, DT_MAX_PATH_LEN); const char *ext = format->extension(fdata); char *c = dirname + strlen(dirname); for(; c>dirname && *c != '/'; c--); if(*c == '/') *c = '\0'; if(g_mkdir_with_parents(dirname, 0755)) { fprintf(stderr, "[imageio_storage_gallery] could not create directory: `%s'!\n", dirname); dt_control_log(_("could not create directory `%s'!"), dirname); dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); return 1; } // store away dir. snprintf(d->cached_dirname, DT_MAX_PATH_LEN, "%s", dirname); c = filename + strlen(filename); for(; c>filename && *c != '.' && *c != '/' ; c--); if(c <= filename || *c=='/') c = filename + strlen(filename); sprintf(c,".%s",ext); // save image to list, in order: pair_t *pair = malloc(sizeof(pair_t)); char *title = NULL, *description = NULL, *tags = NULL; GList *res; res = dt_metadata_get(imgid, "Xmp.dc.title", NULL); if(res) { title = res->data; g_list_free(res); } res = dt_metadata_get(imgid, "Xmp.dc.description", NULL); if(res) { description = res->data; g_list_free(res); } unsigned int count = 0; res = dt_metadata_get(imgid, "Xmp.dc.subject", &count); if(res) { // don't show the internal tags (darktable|...) res = g_list_first(res); GList *iter = res; while(iter) { GList *next = g_list_next(iter); if(g_str_has_prefix(iter->data, "darktable|")) { g_free(iter->data); res = g_list_delete_link(res, iter); count--; } iter = next; } tags = dt_util_glist_to_str(", ", res, count); } char relfilename[256], relthumbfilename[256]; c = filename + strlen(filename); for(; c>filename && *c != '/' ; c--); if(*c == '/') c++; if(c <= filename) c = filename; snprintf(relfilename, 256, "%s", c); snprintf(relthumbfilename, 256, "%s", relfilename); c = relthumbfilename + strlen(relthumbfilename); for(; c>relthumbfilename && *c != '.'; c--); if(c <= relthumbfilename) c = relthumbfilename + strlen(relthumbfilename); sprintf(c, "-thumb.%s", ext); char subfilename[DT_MAX_PATH_LEN], relsubfilename[256]; snprintf(subfilename, DT_MAX_PATH_LEN, "%s", d->cached_dirname); char* sc = subfilename + strlen(subfilename); sprintf(sc, "/img_%d.html", num); sprintf(relsubfilename, "img_%d.html", num); snprintf(pair->line, 4096, "\n" " <div><a class=\"dia\" rel=\"lightbox[viewer]\" title=\"%s - %s\" href=\"%s\"><span></span><img src=\"%s\" alt=\"img%d\" class=\"img\"/></a>\n" " <h1>%s</h1>\n" " %s<br/><span class=\"tags\">%s</span></div>\n", title?title:relfilename, description?description:" ", relfilename, relthumbfilename, num, title?title:" ", description?description:" ", tags?tags:" "); char next[256]; sprintf(next, "img_%d.html", (num)%total+1); char prev[256]; sprintf(prev, "img_%d.html", (num==1)?total:num-1); /* Becomes unecessary with the Lightbox image viewer overlay FILE* subfile = fopen(subfilename, "wb"); fprintf(subfile, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" " <head>\n" " <meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n" " <link rel=\"shortcut icon\" href=\"style/favicon.ico\" />\n" " <link rel=\"stylesheet\" href=\"style/style.css\" type=\"text/css\" />\n" " <title>%s</title>\n" " </head>\n" " <body>\n" " <div class=\"title\"><a href=\"index.html\">%s</a></div>\n" " <div class=\"page\">\n" " <div style=\"width: 692px; max-width: 692px; height: 10px;\">\n" " <a style=\"float: left;\" href=\"%s\"><h1>prev</h1></a>\n" " <a style=\"float: right;\"href=\"%s\"><h1>next</h1></a>\n" " </div>\n" " <a href=\"%s\"><img src=\"%s\" width=\"692\" class=\"img\"/></a>\n" " %s<br/><span class=\"tags\">%s</span></div>\n" " <p style=\"clear:both;\"></p>\n" " </div>\n" " <div class=\"footer\">\n" " created with darktable "PACKAGE_VERSION"\n" " </div>\n" " </body>\n" "</html>\n", relfilename, title?title:relfilename, prev, next, relfilename, relfilename, description?description:" ", tags?tags:" "); fclose(subfile); */ pair->pos = num; g_free(title); g_free(description); g_free(tags); d->l = g_list_insert_sorted(d->l, pair, (GCompareFunc)sort_pos); } // end of critical block dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); /* export image to file */ if(dt_imageio_export(imgid, filename, format, fdata, high_quality) != 0) { fprintf(stderr, "[imageio_storage_gallery] could not export to file: `%s'!\n", filename); dt_control_log(_("could not export to file `%s'!"), filename); return 1; } /* also export thumbnail: */ // write with reduced resolution: const int max_width = fdata->max_width; const int max_height = fdata->max_height; fdata->max_width = 200; fdata->max_height = 200; // alter filename with -thumb: char *c = filename + strlen(filename); for(; c>filename && *c != '.' && *c != '/' ; c--); if(c <= filename || *c=='/') c = filename + strlen(filename); const char *ext = format->extension(fdata); sprintf(c,"-thumb.%s",ext); if(dt_imageio_export(imgid, filename, format, fdata, FALSE) != 0) { fprintf(stderr, "[imageio_storage_gallery] could not export to file: `%s'!\n", filename); dt_control_log(_("could not export to file `%s'!"), filename); return 1; } // restore for next image: fdata->max_width = max_width; fdata->max_height = max_height; printf("[export_job] exported to `%s'\n", filename); char *trunc = filename + strlen(filename) - 32; if(trunc < filename) trunc = filename; dt_control_log(_("%d/%d exported to `%s%s'"), num, total, trunc != filename ? ".." : "", trunc); return 0; }
gboolean _variable_get_value(dt_variables_params_t *params, gchar *variable, gchar *value, size_t value_len) { const gchar *file_ext = NULL; gboolean got_value = FALSE; struct tm tim; localtime_r(¶ms->data->time, &tim); const gchar *homedir = dt_loc_get_home_dir(NULL); gchar *pictures_folder = NULL; if(g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) == NULL) pictures_folder = g_build_path(G_DIR_SEPARATOR_S, homedir, "Pictures", (char *)NULL); else pictures_folder = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_PICTURES)); if(params->filename) { file_ext = (g_strrstr(params->filename, ".") + 1); if(file_ext == (gchar *)1) file_ext = params->filename + strlen(params->filename); } /* image exif time */ gboolean have_exif_tm = FALSE; int exif_iso = 100; char camera_maker[64]; char camera_alias[64]; int version = 0; int stars = 0; struct tm exif_tm = { 0 }; if(params->imgid) { const dt_image_t *img = dt_image_cache_get(darktable.image_cache, params->imgid, 'r'); if(sscanf(img->exif_datetime_taken, "%d:%d:%d %d:%d:%d", &exif_tm.tm_year, &exif_tm.tm_mon, &exif_tm.tm_mday, &exif_tm.tm_hour, &exif_tm.tm_min, &exif_tm.tm_sec) == 6) { exif_tm.tm_year -= 1900; exif_tm.tm_mon--; have_exif_tm = TRUE; } exif_iso = img->exif_iso; g_strlcpy(camera_maker, img->camera_maker, sizeof(camera_maker)); g_strlcpy(camera_alias, img->camera_alias, sizeof(camera_alias)); version = img->version; stars = (img->flags & 0x7); if(stars == 6) stars = -1; dt_image_cache_read_release(darktable.image_cache, img); } else if (params->data->exif_time) { localtime_r(¶ms->data->exif_time, &exif_tm); have_exif_tm = TRUE; } if(g_strcmp0(variable, "$(YEAR)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.4d", tim.tm_year + 1900); else if(g_strcmp0(variable, "$(MONTH)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", tim.tm_mon + 1); else if(g_strcmp0(variable, "$(DAY)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", tim.tm_mday); else if(g_strcmp0(variable, "$(HOUR)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", tim.tm_hour); else if(g_strcmp0(variable, "$(MINUTE)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", tim.tm_min); else if(g_strcmp0(variable, "$(SECOND)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", tim.tm_sec); else if(g_strcmp0(variable, "$(EXIF_YEAR)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.4d", (have_exif_tm ? exif_tm.tm_year : tim.tm_year) + 1900); else if(g_strcmp0(variable, "$(EXIF_MONTH)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", (have_exif_tm ? exif_tm.tm_mon : tim.tm_mon) + 1); else if(g_strcmp0(variable, "$(EXIF_DAY)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", (have_exif_tm ? exif_tm.tm_mday : tim.tm_mday)); else if(g_strcmp0(variable, "$(EXIF_HOUR)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", (have_exif_tm ? exif_tm.tm_hour : tim.tm_hour)); else if(g_strcmp0(variable, "$(EXIF_MINUTE)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", (have_exif_tm ? exif_tm.tm_min : tim.tm_min)); else if(g_strcmp0(variable, "$(EXIF_SECOND)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.2d", (have_exif_tm ? exif_tm.tm_sec : tim.tm_sec)); else if(g_strcmp0(variable, "$(EXIF_ISO)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%d", exif_iso); else if(g_strcmp0(variable, "$(MAKER)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", camera_maker); else if(g_strcmp0(variable, "$(MODEL)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", camera_alias); else if(g_strcmp0(variable, "$(ID)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%d", params->imgid); else if(g_strcmp0(variable, "$(VERSION)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%d", version); else if(g_strcmp0(variable, "$(JOBCODE)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", params->jobcode); else if(g_strcmp0(variable, "$(ROLL_NAME)") == 0 && params->filename && (got_value = TRUE)) { gchar *dirname = g_path_get_dirname(params->filename); gchar *basename = g_path_get_basename(dirname); snprintf(value, value_len, "%s", basename); g_free(basename); g_free(dirname); } else if(g_strcmp0(variable, "$(FILE_DIRECTORY)") == 0 && params->filename && (got_value = TRUE)) { gchar *dirname = g_path_get_dirname(params->filename); snprintf(value, value_len, "%s", dirname); g_free(dirname); } // undocumented : backward compatibility else if(g_strcmp0(variable, "$(FILE_FOLDER)") == 0 && params->filename && (got_value = TRUE)) { gchar *dirname = g_path_get_dirname(params->filename); snprintf(value, value_len, "%s", dirname); g_free(dirname); } else if(g_strcmp0(variable, "$(FILE_NAME)") == 0 && params->filename && (got_value = TRUE)) { gchar *basename = g_path_get_basename(params->filename); snprintf(value, value_len, "%s", basename); g_free(basename); if(g_strrstr(value, ".")) *(g_strrstr(value, ".")) = 0; } else if(g_strcmp0(variable, "$(FILE_EXTENSION)") == 0 && params->filename && (got_value = TRUE)) snprintf(value, value_len, "%s", file_ext); else if(g_strcmp0(variable, "$(SEQUENCE)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%.4d", params->sequence >= 0 ? params->sequence : params->data->sequence); else if(g_strcmp0(variable, "$(USERNAME)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", g_get_user_name()); else if(g_strcmp0(variable, "$(HOME_FOLDER)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", homedir); // undocumented : backward compatibility else if(g_strcmp0(variable, "$(HOME)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", homedir); else if(g_strcmp0(variable, "$(PICTURES_FOLDER)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", pictures_folder); else if(g_strcmp0(variable, "$(DESKTOP_FOLDER)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP)); // undocumented : backward compatibility else if(g_strcmp0(variable, "$(DESKTOP)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%s", g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP)); else if(g_strcmp0(variable, "$(STARS)") == 0 && (got_value = TRUE)) snprintf(value, value_len, "%d", stars); else if(g_strcmp0(variable, "$(LABELS)") == 0 && (got_value = TRUE)) { // TODO: currently we concatenate all the color labels with a ',' as a separator. Maybe it's better to // only use the first/last label? GList *res = dt_metadata_get(params->imgid, "Xmp.darktable.colorlabels", NULL); res = g_list_first(res); if(res != NULL) { GList *labels = NULL; do { labels = g_list_append(labels, (char *)(_(dt_colorlabels_to_string(GPOINTER_TO_INT(res->data))))); } while((res = g_list_next(res)) != NULL); char *str = dt_util_glist_to_str(",", labels); g_list_free(labels); snprintf(value, value_len, "%s", str); g_free(str); } else { snprintf(value, value_len, "%s", _("none")); } g_list_free(res); } else if(g_strcmp0(variable, "$(TITLE)") == 0 && params->filename && (got_value = TRUE)) { GList *res = dt_metadata_get(params->imgid, "Xmp.dc.title", NULL); res = g_list_first(res); if(res != NULL) { snprintf(value, value_len, "%s", (char *)res->data); } else { snprintf(value, value_len, "%s", _("none")); } g_list_free_full(res, &g_free); } else if(g_strcmp0(variable, "$(CREATOR)") == 0 && params->filename && (got_value = TRUE)) { GList *res = dt_metadata_get(params->imgid, "Xmp.dc.creator", NULL); res = g_list_first(res); if(res != NULL) { snprintf(value, value_len, "%s", (char *)res->data); } else { snprintf(value, value_len, "%s", _("none")); } g_list_free_full(res, &g_free); } else if(g_strcmp0(variable, "$(PUBLISHER)") == 0 && params->filename && (got_value = TRUE)) { GList *res = dt_metadata_get(params->imgid, "Xmp.dc.publisher", NULL); res = g_list_first(res); if(res != NULL) { snprintf(value, value_len, "%s", (char *)res->data); } else { snprintf(value, value_len, "%s", _("none")); } g_list_free_full(res, &g_free); } else if(g_strcmp0(variable, "$(RIGHTS)") == 0 && params->filename && (got_value = TRUE)) { GList *res = dt_metadata_get(params->imgid, "Xmp.dc.rights", NULL); res = g_list_first(res); if(res != NULL) { snprintf(value, value_len, "%s", (char *)res->data); } else { snprintf(value, value_len, "%s", _("none")); } g_list_free_full(res, &g_free); } g_free(pictures_folder); g_free((gchar *)homedir); return got_value; }
static gchar * _watermark_get_svgdoc( dt_iop_module_t *self, dt_iop_watermark_data_t *data, const dt_image_t *image) { gsize length; gchar *svgdoc=NULL; gchar configdir[DT_MAX_PATH_LEN]; gchar datadir[DT_MAX_PATH_LEN]; gchar *filename; dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN); dt_loc_get_user_config_dir(configdir, DT_MAX_PATH_LEN); g_strlcat(datadir,"/watermarks/", DT_MAX_PATH_LEN); g_strlcat(configdir,"/watermarks/", DT_MAX_PATH_LEN); g_strlcat(datadir,data->filename, DT_MAX_PATH_LEN); g_strlcat(configdir,data->filename, DT_MAX_PATH_LEN); if (g_file_test(configdir,G_FILE_TEST_EXISTS)) filename=configdir; else if (g_file_test(datadir,G_FILE_TEST_EXISTS)) filename=datadir; else return NULL; gchar *svgdata=NULL; char datetime[200]; // EXIF datetime struct tm tt_exif = {0}; if(sscanf(image->exif_datetime_taken,"%d:%d:%d %d:%d:%d", &tt_exif.tm_year, &tt_exif.tm_mon, &tt_exif.tm_mday, &tt_exif.tm_hour, &tt_exif.tm_min, &tt_exif.tm_sec ) == 6 ) { tt_exif.tm_year-=1900; tt_exif.tm_mon--; } // Current datetime struct tm tt_cur = {0}; time_t t = time(NULL); (void)localtime_r(&t, &tt_cur); if( g_file_get_contents( filename, &svgdata, &length, NULL) ) { // File is loaded lets substitute strings if found... // Darktable internal svgdoc = _string_substitute(svgdata,"$(DARKTABLE.NAME)",PACKAGE_NAME); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata,"$(DARKTABLE.VERSION)",PACKAGE_VERSION); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // Current image ID gchar buffer[1024]; g_snprintf(buffer,1024,"%d",image->id); svgdoc = _string_substitute(svgdata,"$(IMAGE.ID)",buffer); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // Current image dt_image_print_exif(image,buffer,1024); svgdoc = _string_substitute(svgdata,"$(IMAGE.EXIF)",buffer); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // Image exif // EXIF date svgdoc = _string_substitute(svgdata,"$(EXIF.DATE)",image->exif_datetime_taken); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.SECOND) -- 00..60 strftime(datetime, sizeof(datetime), "%S", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.SECOND)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.MINUTE) -- 00..59 strftime(datetime, sizeof(datetime), "%M", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.MINUTE)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.HOUR) -- 00..23 strftime(datetime, sizeof(datetime), "%H", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.HOUR)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.HOUR_AMPM) -- 01..12 strftime(datetime, sizeof(datetime), "%I %p", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.HOUR_AMPM)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.DAY) -- 01..31 strftime(datetime, sizeof(datetime), "%d", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.DAY)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.MONTH) -- 01..12 strftime(datetime, sizeof(datetime), "%m", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.MONTH)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized strftime(datetime, sizeof(datetime), "%b", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.SHORT_MONTH)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.LONG_MONTH) -- January, February, .., December, localized strftime(datetime, sizeof(datetime), "%B", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.LONG_MONTH)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.SHORT_YEAR) -- 12 strftime(datetime, sizeof(datetime), "%y", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.SHORT_YEAR)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.LONG_YEAR) -- 2012 strftime(datetime, sizeof(datetime), "%Y", &tt_exif); svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.LONG_YEAR)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // Current date // $(DATE) -- YYYY: dt_gettime_t(datetime, t); svgdoc = _string_substitute(svgdata,"$(DATE)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.SECOND) -- 00..60 strftime(datetime, sizeof(datetime), "%S", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.SECOND)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.MINUTE) -- 00..59 strftime(datetime, sizeof(datetime), "%M", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.MINUTE)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.HOUR) -- 00..23 strftime(datetime, sizeof(datetime), "%H", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.HOUR)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.HOUR_AMPM) -- 01..12 strftime(datetime, sizeof(datetime), "%I %p", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.HOUR_AMPM)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.DAY) -- 01..31 strftime(datetime, sizeof(datetime), "%d", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.DAY)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.MONTH) -- 01..12 strftime(datetime, sizeof(datetime), "%m", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.MONTH)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized strftime(datetime, sizeof(datetime), "%b", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.SHORT_MONTH)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.LONG_MONTH) -- January, February, .., December, localized strftime(datetime, sizeof(datetime), "%B", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.LONG_MONTH)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.SHORT_YEAR) -- 12 strftime(datetime, sizeof(datetime), "%y", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.SHORT_YEAR)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.LONG_YEAR) -- 2012 strftime(datetime, sizeof(datetime), "%Y", &tt_cur); svgdoc = _string_substitute(svgdata,"$(DATE.LONG_YEAR)",datetime); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata,"$(EXIF.MAKER)",image->exif_maker); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata,"$(EXIF.MODEL)",image->exif_model); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata,"$(EXIF.LENS)",image->exif_lens); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata,"$(IMAGE.FILENAME)",image->filename); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } // TODO: auto generate that code? GList * res; res = dt_metadata_get(image->id, "Xmp.dc.creator", NULL); svgdoc = _string_substitute(svgdata,"$(Xmp.dc.creator)",(res?res->data:"")); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } if( res ) { g_free(res->data); g_list_free(res); } res = dt_metadata_get(image->id, "Xmp.dc.publisher", NULL); svgdoc = _string_substitute(svgdata,"$(Xmp.dc.publisher)",(res?res->data:"")); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } if( res ) { g_free(res->data); g_list_free(res); } res = dt_metadata_get(image->id, "Xmp.dc.title", NULL); svgdoc = _string_substitute(svgdata,"$(Xmp.dc.title)",(res?res->data:"")); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } if( res ) { g_free(res->data); g_list_free(res); } res = dt_metadata_get(image->id, "Xmp.dc.description", NULL); svgdoc = _string_substitute(svgdata,"$(Xmp.dc.description)",(res?res->data:"")); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } if( res ) { g_free(res->data); g_list_free(res); } res = dt_metadata_get(image->id, "Xmp.dc.rights", NULL); svgdoc = _string_substitute(svgdata,"$(Xmp.dc.rights)",(res?res->data:"")); if( svgdoc != svgdata ) { g_free(svgdata); svgdata = svgdoc; } if( res ) { g_free(res->data); g_list_free(res); } } return svgdoc; }
static gchar *_watermark_get_svgdoc(dt_iop_module_t *self, dt_iop_watermark_data_t *data, const dt_image_t *image) { gsize length; gchar *svgdoc = NULL; gchar configdir[PATH_MAX] = { 0 }; gchar datadir[PATH_MAX] = { 0 }; gchar *filename; dt_loc_get_datadir(datadir, sizeof(datadir)); dt_loc_get_user_config_dir(configdir, sizeof(configdir)); g_strlcat(datadir, "/watermarks/", sizeof(datadir)); g_strlcat(configdir, "/watermarks/", sizeof(configdir)); g_strlcat(datadir, data->filename, sizeof(datadir)); g_strlcat(configdir, data->filename, sizeof(configdir)); if(g_file_test(configdir, G_FILE_TEST_EXISTS)) filename = configdir; else if(g_file_test(datadir, G_FILE_TEST_EXISTS)) filename = datadir; else return NULL; gchar *svgdata = NULL; char datetime[200]; // EXIF datetime struct tm tt_exif = { 0 }; if(sscanf(image->exif_datetime_taken, "%d:%d:%d %d:%d:%d", &tt_exif.tm_year, &tt_exif.tm_mon, &tt_exif.tm_mday, &tt_exif.tm_hour, &tt_exif.tm_min, &tt_exif.tm_sec) == 6) { tt_exif.tm_year -= 1900; tt_exif.tm_mon--; } // Current datetime struct tm tt_cur = { 0 }; time_t t = time(NULL); (void)localtime_r(&t, &tt_cur); if(g_file_get_contents(filename, &svgdata, &length, NULL)) { // File is loaded lets substitute strings if found... // Darktable internal svgdoc = _string_substitute(svgdata, "$(DARKTABLE.NAME)", PACKAGE_NAME); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata, "$(DARKTABLE.VERSION)", PACKAGE_VERSION); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // Simple text from watermark module gchar buffer[1024]; if (data->font[0] && data->text[0]) { g_snprintf(buffer, sizeof(buffer), "%s", data->text); svgdoc = _string_substitute(svgdata, "$(WATERMARK_TEXT)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } PangoFontDescription *font = pango_font_description_from_string(data->font); const PangoStyle font_style = pango_font_description_get_style(font); const int font_weight = (int)pango_font_description_get_weight(font); g_snprintf(buffer, sizeof(buffer), "%s", pango_font_description_get_family(font)); svgdoc = _string_substitute(svgdata, "$(WATERMARK_FONT_FAMILY)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } switch (font_style) { case PANGO_STYLE_OBLIQUE: g_strlcpy(buffer, "oblique", sizeof(buffer)); break; case PANGO_STYLE_ITALIC: g_strlcpy(buffer, "italic", sizeof(buffer)); break; default: g_strlcpy(buffer, "normal", sizeof(buffer)); break; } svgdoc = _string_substitute(svgdata, "$(WATERMARK_FONT_STYLE)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } g_snprintf(buffer, sizeof(buffer), "%d", font_weight); svgdoc = _string_substitute(svgdata, "$(WATERMARK_FONT_WEIGHT)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } pango_font_description_free(font); } // watermark color GdkRGBA c = { data->color[0], data->color[1], data->color[2], 1.0f }; g_snprintf(buffer, sizeof(buffer), "%s", gdk_rgba_to_string(&c)); svgdoc = _string_substitute(svgdata, "$(WATERMARK_COLOR)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // Current image ID g_snprintf(buffer, sizeof(buffer), "%d", image->id); svgdoc = _string_substitute(svgdata, "$(IMAGE.ID)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // Current image dt_image_print_exif(image, buffer, sizeof(buffer)); svgdoc = _string_substitute(svgdata, "$(IMAGE.EXIF)", buffer); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // Image exif // EXIF date svgdoc = _string_substitute(svgdata, "$(EXIF.DATE)", image->exif_datetime_taken); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.SECOND) -- 00..60 strftime(datetime, sizeof(datetime), "%S", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.SECOND)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.MINUTE) -- 00..59 strftime(datetime, sizeof(datetime), "%M", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.MINUTE)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.HOUR) -- 00..23 strftime(datetime, sizeof(datetime), "%H", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.HOUR)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.HOUR_AMPM) -- 01..12 strftime(datetime, sizeof(datetime), "%I %p", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.HOUR_AMPM)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.DAY) -- 01..31 strftime(datetime, sizeof(datetime), "%d", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.DAY)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.MONTH) -- 01..12 strftime(datetime, sizeof(datetime), "%m", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.MONTH)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized strftime(datetime, sizeof(datetime), "%b", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.SHORT_MONTH)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.LONG_MONTH) -- January, February, .., December, localized strftime(datetime, sizeof(datetime), "%B", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.LONG_MONTH)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.SHORT_YEAR) -- 12 strftime(datetime, sizeof(datetime), "%y", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.SHORT_YEAR)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(EXIF.DATE.LONG_YEAR) -- 2012 strftime(datetime, sizeof(datetime), "%Y", &tt_exif); svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.LONG_YEAR)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // Current date // $(DATE) -- YYYY: dt_gettime_t(datetime, sizeof(datetime), t); svgdoc = _string_substitute(svgdata, "$(DATE)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.SECOND) -- 00..60 strftime(datetime, sizeof(datetime), "%S", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.SECOND)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.MINUTE) -- 00..59 strftime(datetime, sizeof(datetime), "%M", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.MINUTE)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.HOUR) -- 00..23 strftime(datetime, sizeof(datetime), "%H", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.HOUR)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.HOUR_AMPM) -- 01..12 strftime(datetime, sizeof(datetime), "%I %p", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.HOUR_AMPM)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.DAY) -- 01..31 strftime(datetime, sizeof(datetime), "%d", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.DAY)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.MONTH) -- 01..12 strftime(datetime, sizeof(datetime), "%m", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.MONTH)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized strftime(datetime, sizeof(datetime), "%b", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.SHORT_MONTH)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.LONG_MONTH) -- January, February, .., December, localized strftime(datetime, sizeof(datetime), "%B", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.LONG_MONTH)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.SHORT_YEAR) -- 12 strftime(datetime, sizeof(datetime), "%y", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.SHORT_YEAR)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } // $(DATE.LONG_YEAR) -- 2012 strftime(datetime, sizeof(datetime), "%Y", &tt_cur); svgdoc = _string_substitute(svgdata, "$(DATE.LONG_YEAR)", datetime); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata, "$(EXIF.MAKER)", image->camera_maker); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata, "$(EXIF.MODEL)", image->camera_model); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata, "$(EXIF.LENS)", image->exif_lens); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } svgdoc = _string_substitute(svgdata, "$(IMAGE.FILENAME)", image->filename); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } gchar *basename = g_path_get_basename(image->filename); if(g_strrstr(basename, ".")) *(g_strrstr(basename, ".")) = '\0'; svgdoc = _string_substitute(svgdata, "$(IMAGE.BASENAME)", basename); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } g_free(basename); // TODO: auto generate that code? GList *res; res = dt_metadata_get(image->id, "Xmp.dc.creator", NULL); svgdoc = _string_substitute(svgdata, "$(Xmp.dc.creator)", (res ? res->data : "")); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } if(res) { g_list_free_full(res, &g_free); } res = dt_metadata_get(image->id, "Xmp.dc.publisher", NULL); svgdoc = _string_substitute(svgdata, "$(Xmp.dc.publisher)", (res ? res->data : "")); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } if(res) { g_list_free_full(res, &g_free); } res = dt_metadata_get(image->id, "Xmp.dc.title", NULL); svgdoc = _string_substitute(svgdata, "$(Xmp.dc.title)", (res ? res->data : "")); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } if(res) { g_list_free_full(res, &g_free); } res = dt_metadata_get(image->id, "Xmp.dc.description", NULL); svgdoc = _string_substitute(svgdata, "$(Xmp.dc.description)", (res ? res->data : "")); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } if(res) { g_list_free_full(res, &g_free); } res = dt_metadata_get(image->id, "Xmp.dc.rights", NULL); svgdoc = _string_substitute(svgdata, "$(Xmp.dc.rights)", (res ? res->data : "")); if(svgdoc != svgdata) { g_free(svgdata); svgdata = svgdoc; } if(res) { g_list_free_full(res, &g_free); } } return svgdoc; }
int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean upscale) { dt_imageio_gallery_t *d = (dt_imageio_gallery_t *)sdata; char filename[PATH_MAX] = { 0 }; char dirname[PATH_MAX] = { 0 }; gboolean from_cache = FALSE; dt_image_full_path(imgid, dirname, sizeof(dirname), &from_cache); // we're potentially called in parallel. have sequence number synchronized: dt_pthread_mutex_lock(&darktable.plugin_threadsafe); { char tmp_dir[PATH_MAX] = { 0 }; d->vp->filename = dirname; d->vp->jobcode = "export"; d->vp->imgid = imgid; d->vp->sequence = num; dt_variables_expand(d->vp, d->filename, TRUE); gchar *result_tmp_dir = dt_variables_get_result(d->vp); g_strlcpy(tmp_dir, result_tmp_dir, sizeof(tmp_dir)); g_free(result_tmp_dir); // if filenamepattern is a directory just let att ${FILE_NAME} as default.. if(g_file_test(tmp_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) || ((d->filename + strlen(d->filename) - 1)[0] == '/' || (d->filename + strlen(d->filename) - 1)[0] == '\\')) snprintf(d->filename + strlen(d->filename), sizeof(d->filename) - strlen(d->filename), "/$(FILE_NAME)"); // avoid braindead export which is bound to overwrite at random: if(total > 1 && !g_strrstr(d->filename, "$")) { snprintf(d->filename + strlen(d->filename), sizeof(d->filename) - strlen(d->filename), "_$(SEQUENCE)"); } gchar *fixed_path = dt_util_fix_path(d->filename); g_strlcpy(d->filename, fixed_path, sizeof(d->filename)); g_free(fixed_path); dt_variables_expand(d->vp, d->filename, TRUE); gchar *result_filename = dt_variables_get_result(d->vp); g_strlcpy(filename, result_filename, sizeof(filename)); g_free(result_filename); g_strlcpy(dirname, filename, sizeof(dirname)); const char *ext = format->extension(fdata); char *c = dirname + strlen(dirname); for(; c > dirname && *c != '/'; c--) ; if(*c == '/') *c = '\0'; if(g_mkdir_with_parents(dirname, 0755)) { fprintf(stderr, "[imageio_storage_gallery] could not create directory: `%s'!\n", dirname); dt_control_log(_("could not create directory `%s'!"), dirname); dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); return 1; } // store away dir. snprintf(d->cached_dirname, sizeof(d->cached_dirname), "%s", dirname); c = filename + strlen(filename); for(; c > filename && *c != '.' && *c != '/'; c--) ; if(c <= filename || *c == '/') c = filename + strlen(filename); sprintf(c, ".%s", ext); // save image to list, in order: pair_t *pair = malloc(sizeof(pair_t)); char *title = NULL, *description = NULL; GList *res_title, *res_desc; res_title = dt_metadata_get(imgid, "Xmp.dc.title", NULL); if(res_title) { title = res_title->data; } res_desc = dt_metadata_get(imgid, "Xmp.dc.description", NULL); if(res_desc) { description = res_desc->data; } char relfilename[PATH_MAX] = { 0 }, relthumbfilename[PATH_MAX] = { 0 }; c = filename + strlen(filename); for(; c > filename && *c != '/'; c--) ; if(*c == '/') c++; if(c <= filename) c = filename; snprintf(relfilename, sizeof(relfilename), "%s", c); snprintf(relthumbfilename, sizeof(relthumbfilename), "%s", relfilename); c = relthumbfilename + strlen(relthumbfilename); for(; c > relthumbfilename && *c != '.'; c--) ; if(c <= relthumbfilename) c = relthumbfilename + strlen(relthumbfilename); sprintf(c, "-thumb.%s", ext); char subfilename[PATH_MAX] = { 0 }, relsubfilename[PATH_MAX] = { 0 }; snprintf(subfilename, sizeof(subfilename), "%s", d->cached_dirname); char *sc = subfilename + strlen(subfilename); sprintf(sc, "/img_%d.html", num); snprintf(relsubfilename, sizeof(relsubfilename), "img_%d.html", num); snprintf(pair->line, sizeof(pair->line), "\n" " <div><a class=\"dia\" rel=\"lightbox[viewer]\" title=\"%s - %s\" " "href=\"%s\"><span></span><img src=\"%s\" alt=\"img%d\" class=\"img\"/></a>\n" " <h1>%s</h1>\n" " %s</div>\n", title ? title : relfilename, description ? description : " ", relfilename, relthumbfilename, num, title ? title : " ", description ? description : " "); char next[PATH_MAX] = { 0 }; snprintf(next, sizeof(next), "img_%d.html", (num) % total + 1); char prev[PATH_MAX] = { 0 }; snprintf(prev, sizeof(prev), "img_%d.html", (num == 1) ? total : num - 1); pair->pos = num; if(res_title) g_list_free_full(res_title, &g_free); if(res_desc) g_list_free_full(res_desc, &g_free); d->l = g_list_insert_sorted(d->l, pair, (GCompareFunc)sort_pos); } // end of critical block dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); /* export image to file */ if(dt_imageio_export(imgid, filename, format, fdata, high_quality, upscale, FALSE, self, sdata, num, total) != 0) { fprintf(stderr, "[imageio_storage_gallery] could not export to file: `%s'!\n", filename); dt_control_log(_("could not export to file `%s'!"), filename); return 1; } /* also export thumbnail: */ // write with reduced resolution: const int max_width = fdata->max_width; const int max_height = fdata->max_height; fdata->max_width = 200; fdata->max_height = 200; // alter filename with -thumb: char *c = filename + strlen(filename); for(; c > filename && *c != '.' && *c != '/'; c--) ; if(c <= filename || *c == '/') c = filename + strlen(filename); const char *ext = format->extension(fdata); sprintf(c, "-thumb.%s", ext); if(dt_imageio_export(imgid, filename, format, fdata, FALSE, TRUE, FALSE, self, sdata, num, total) != 0) { fprintf(stderr, "[imageio_storage_gallery] could not export to file: `%s'!\n", filename); dt_control_log(_("could not export to file `%s'!"), filename); return 1; } // restore for next image: fdata->max_width = max_width; fdata->max_height = max_height; printf("[export_job] exported to `%s'\n", filename); char *trunc = filename + strlen(filename) - 32; if(trunc < filename) trunc = filename; dt_control_log(ngettext("%d/%d exported to `%s%s'", "%d/%d exported to `%s%s'", num), num, total, trunc != filename ? ".." : "", trunc); return 0; }
int store (dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality) { gint result=1; dt_storage_flickr_params_t *p=(dt_storage_flickr_params_t *)sdata; flickcurl_upload_status *photo_status; gint tags=0; const char *ext = format->extension(fdata); // Let's upload image... /* construct a temporary file name */ char fname[4096]= {0}; dt_loc_get_tmp_dir (fname,4096); g_strlcat (fname,"/darktable.XXXXXX.",4096); g_strlcat(fname,ext,4096); char *caption = NULL; char *description = NULL; gint fd=g_mkstemp(fname); fprintf(stderr,"tempfile: %s\n",fname); if(fd==-1) { dt_control_log("failed to create temporary image for flickr export"); return 1; } close(fd); const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); // If title is not existing, then use the filename without extension. If not, then use title instead GList *title = dt_metadata_get(img->id, "Xmp.dc.title", NULL); if(title != NULL) { caption = g_strdup(title->data); g_list_free_full(title, &g_free); } else { caption = g_path_get_basename(img->filename); (g_strrstr(caption,"."))[0]='\0'; // chop extension... } GList *desc = dt_metadata_get(img->id, "Xmp.dc.description", NULL); if(desc != NULL) { description = desc->data; } dt_image_cache_read_release(darktable.image_cache, img); if(dt_imageio_export(imgid, fname, format, fdata, high_quality) != 0) { fprintf(stderr, "[imageio_storage_flickr] could not export to file: `%s'!\n", fname); dt_control_log(_("could not export to file `%s'!"), fname); result = 0; goto cleanup; } #ifdef _OPENMP #pragma omp critical #endif { //TODO: Check if this could be done in threads, so we enhance export time by using // upload time for one image to export another image to disk. // Upload image // Do we export tags? if( p->export_tags == TRUE ) tags = imgid; photo_status = _flickr_api_upload_photo( p, fname, caption, description, tags ); } if( !photo_status ) { result=0; goto cleanup; } // int fail = 0; // A photoset is only created if we have an album title set if( p->flickr_api->current_album == NULL && p->flickr_api->new_album == TRUE) { char *photoset_id; photoset_id = _flickr_api_create_photoset(p->flickr_api, photo_status->photoid); if( photoset_id == NULL) { dt_control_log("failed to create flickr album"); // fail = 1; } else { // p->flickr_api->new_album = FALSE; p->flickr_api->current_album = flickcurl_photosets_getInfo(p->flickr_api->fc,photoset_id); } } // if(fail) return 1; // TODO: What to do if photoset creation fails? // Add to gallery, if needed if (p->flickr_api->current_album != NULL && p->flickr_api->new_album != TRUE) { flickcurl_photosets_addPhoto (p->flickr_api->fc, p->flickr_api->current_album->id, photo_status->photoid); // TODO: Check for errors adding photo to gallery } else { if (p->flickr_api->current_album != NULL && p->flickr_api->new_album == TRUE) { p->flickr_api->new_album = FALSE; } } cleanup: // And remove from filesystem.. unlink( fname ); g_free( caption ); if(desc) g_list_free_full(desc, &g_free); if (result) { //this makes sense only if the export was successful dt_control_log(_("%d/%d exported to flickr webalbum"), num, total ); } return result; }
/* update all values to reflect mouse over image id or no data at all */ static void _metadata_view_update_values(dt_lib_module_t *self) { dt_lib_metadata_view_t *d = (dt_lib_metadata_view_t *)self->data; int32_t mouse_over_id = dt_control_get_mouse_over_id(); if (mouse_over_id == -1) { const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager); if(cv->view((dt_view_t*)cv) == DT_VIEW_DARKROOM) { mouse_over_id = darktable.develop->image_storage.id; } else { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images limit 1", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) mouse_over_id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } } if(mouse_over_id >= 0) { char value[512]; char pathname[PATH_MAX]; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); if(!img) goto fill_minuses; if(img->film_id == -1) { dt_image_cache_read_release(darktable.image_cache, img); goto fill_minuses; } /* update all metadata */ dt_image_film_roll(img, value, sizeof(value)); _metadata_update_value(d->metadata[md_internal_filmroll], value); const int tp = 512; char tooltip[tp]; snprintf(tooltip, tp, _("double click to jump to film roll\n%s"), value); g_object_set(G_OBJECT(d->metadata[md_internal_filmroll]), "tooltip-text", tooltip, (char *)NULL); snprintf(value,sizeof(value),"%d", img->id); _metadata_update_value(d->metadata[md_internal_imgid], value); snprintf(value,sizeof(value),"%d", img->group_id); _metadata_update_value(d->metadata[md_internal_groupid], value); _metadata_update_value(d->metadata[md_internal_filename], img->filename); snprintf(value,sizeof(value),"%d", img->version); _metadata_update_value(d->metadata[md_internal_version], value); gboolean from_cache = FALSE; dt_image_full_path(img->id, pathname, sizeof(pathname), &from_cache); _metadata_update_value(d->metadata[md_internal_fullpath], pathname); snprintf(value, sizeof(value), "%s", (img->flags & DT_IMAGE_LOCAL_COPY)?_("yes"):_("no")); _metadata_update_value(d->metadata[md_internal_local_copy], value); // TODO: decide if this should be removed for a release. maybe #ifdef'ing to only add it to git compiles? // the bits of the flags { #define EMPTY_FIELD '.' #define FALSE_FIELD '.' #define TRUE_FIELD '!' char *tooltip = NULL; char *flag_descriptions[] = { N_("unused"), N_("unused/deprecated"), N_("ldr"), N_("raw"), N_("hdr"), N_("marked for deletion"), N_("auto-applying presets applied"), N_("legacy flag. set for all new images"), N_("local copy"), N_("has .txt"), N_("has .wav") }; char *tooltip_parts[13] = { 0 }; int next_tooltip_part = 0; memset(value, EMPTY_FIELD, sizeof(value)); int stars = img->flags & 0x7; char *star_string = NULL; if(stars == 6) { value[0] = 'x'; tooltip_parts[next_tooltip_part++] = _("image rejected"); } else { value[0] = '0' + stars; tooltip_parts[next_tooltip_part++] = star_string = g_strdup_printf(ngettext("image has %d star", "image has %d stars", stars), stars); } if(img->flags & 8) { value[1] = TRUE_FIELD; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[0]); } else value[1] = FALSE_FIELD; if(img->flags & DT_IMAGE_THUMBNAIL_DEPRECATED) { value[2] = TRUE_FIELD; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[1]); } else value[2] = FALSE_FIELD; if(img->flags & DT_IMAGE_LDR) { value[3] = 'l'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[2]); } if(img->flags & DT_IMAGE_RAW) { value[4] = 'r'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[3]); } if(img->flags & DT_IMAGE_HDR) { value[5] = 'h'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[4]); } if(img->flags & DT_IMAGE_REMOVE) { value[6] = 'd'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[5]); } if(img->flags & DT_IMAGE_AUTO_PRESETS_APPLIED) { value[7] = 'a'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[6]); } if(img->flags & DT_IMAGE_NO_LEGACY_PRESETS) { value[8] = 'p'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[7]); } if(img->flags & DT_IMAGE_LOCAL_COPY) { value[9] = 'c'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[8]); } if(img->flags & DT_IMAGE_HAS_TXT) { value[10] = 't'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[9]); } if(img->flags & DT_IMAGE_HAS_WAV) { value[11] = 'w'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[10]); } value[12] = '\0'; tooltip = g_strjoinv("\n", tooltip_parts); _metadata_update_value(d->metadata[md_internal_flags], value); g_object_set(G_OBJECT(d->metadata[md_internal_flags]), "tooltip-text", tooltip, (char *)NULL); g_free(star_string); g_free(tooltip); #undef EMPTY_FIELD #undef FALSE_FIELD #undef TRUE_FIELD } /* EXIF */ _metadata_update_value_end(d->metadata[md_exif_model], img->exif_model); _metadata_update_value_end(d->metadata[md_exif_lens], img->exif_lens); _metadata_update_value_end(d->metadata[md_exif_maker], img->exif_maker); snprintf(value, sizeof(value), "F/%.1f", img->exif_aperture); _metadata_update_value(d->metadata[md_exif_aperture], value); if(img->exif_exposure <= 0.5) snprintf(value, sizeof(value), "1/%.0f", 1.0/img->exif_exposure); else snprintf(value, sizeof(value), "%.1f''", img->exif_exposure); _metadata_update_value(d->metadata[md_exif_exposure], value); snprintf(value, sizeof(value), "%.0f mm", img->exif_focal_length); _metadata_update_value(d->metadata[md_exif_focal_length], value); if (isnan(img->exif_focus_distance) || fpclassify(img->exif_focus_distance) == FP_ZERO) { _metadata_update_value(d->metadata[md_exif_focus_distance], NODATA_STRING); } else { snprintf(value, sizeof(value), "%.2f m", img->exif_focus_distance); _metadata_update_value(d->metadata[md_exif_focus_distance], value); } snprintf(value, sizeof(value), "%.0f", img->exif_iso); _metadata_update_value(d->metadata[md_exif_iso], value); _metadata_update_value(d->metadata[md_exif_datetime], img->exif_datetime_taken); snprintf(value, sizeof(value), "%d", img->height); _metadata_update_value(d->metadata[md_exif_height], value); snprintf(value, sizeof(value), "%d", img->width); _metadata_update_value(d->metadata[md_exif_width], value); /* XMP */ GList *res; if((res = dt_metadata_get(img->id, "Xmp.dc.title", NULL))!=NULL) { snprintf(value, sizeof(value), "%s", (char*)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_title], value); if((res = dt_metadata_get(img->id, "Xmp.dc.creator", NULL))!=NULL) { snprintf(value, sizeof(value), "%s", (char*)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_creator], value); if((res = dt_metadata_get(img->id, "Xmp.dc.rights", NULL))!=NULL) { snprintf(value, sizeof(value), "%s", (char*)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_rights], value); /* geotagging */ /* latitude */ if(isnan(img->latitude)) { _metadata_update_value(d->metadata[md_geotagging_lat], NODATA_STRING); } else { #ifdef HAVE_MAP if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *latitude = osd_latitude_str(img->latitude); _metadata_update_value(d->metadata[md_geotagging_lat], latitude); g_free(latitude); } else { #endif gchar NS = img->latitude<0?'S':'N'; snprintf(value, sizeof(value), "%c %09.6f", NS, fabs(img->latitude)); _metadata_update_value(d->metadata[md_geotagging_lat], value); #ifdef HAVE_MAP } #endif } /* longitude */ if(isnan(img->longitude)) { _metadata_update_value(d->metadata[md_geotagging_lon], NODATA_STRING); } else { #ifdef HAVE_MAP if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *longitude = osd_longitude_str(img->longitude); _metadata_update_value(d->metadata[md_geotagging_lon], longitude); g_free(longitude); } else { #endif gchar EW = img->longitude<0?'W':'E'; snprintf(value, sizeof(value), "%c %010.6f", EW, fabs(img->longitude)); _metadata_update_value(d->metadata[md_geotagging_lon], value); #ifdef HAVE_MAP } #endif } /* release img */ dt_image_cache_read_release(darktable.image_cache, img); } return; /* reset */ fill_minuses: for(int k=0; k<md_size; k++) _metadata_update_value(d->metadata[k],NODATA_STRING); }
/* this actually does the work */ int store(dt_imageio_module_storage_t *self, struct dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality) { gint result = 1; dt_storage_facebook_param_t *p = (dt_storage_facebook_param_t*)sdata; const char *ext = format->extension(fdata); char fname[4096]= {0}; dt_loc_get_tmp_dir(fname,4096); g_strlcat (fname,"/darktable.XXXXXX.",4096); g_strlcat(fname,ext,4096); gint fd=g_mkstemp(fname); if(fd==-1) { dt_control_log("failed to create temporary image for facebook export"); return 1; } close(fd); //get metadata const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); char *caption = NULL; GList *title = NULL; GList *desc = NULL; title = dt_metadata_get(img->id, "Xmp.dc.title", NULL); if(title != NULL) { caption = title->data; } if (caption == NULL) { desc = dt_metadata_get(img->id, "Xmp.dc.description", NULL); if(desc != NULL) { caption = desc->data; } } dt_image_cache_read_release(darktable.image_cache, img); //facebook doesn't allow pictures bigger than FB_IMAGE_MAX_SIZExFB_IMAGE_MAX_SIZE px if (fdata->max_height == 0 || fdata->max_height > FB_IMAGE_MAX_SIZE) fdata->max_height = FB_IMAGE_MAX_SIZE; if (fdata->max_width == 0 || fdata->max_width > FB_IMAGE_MAX_SIZE) fdata->max_width = FB_IMAGE_MAX_SIZE; if(dt_imageio_export(imgid, fname, format, fdata, high_quality) != 0) { g_printerr("[facebook] could not export to file: `%s'!\n", fname); dt_control_log(_("could not export to file `%s'!"), fname); result = 0; goto cleanup; } if (p->facebook_ctx->album_id == NULL) { if (p->facebook_ctx->album_title == NULL) { dt_control_log(_("unable to create album, no title provided")); result = 0; goto cleanup; } const gchar *album_id = fb_create_album(p->facebook_ctx, p->facebook_ctx->album_title, p->facebook_ctx->album_summary, p->facebook_ctx->album_permission); if (album_id == NULL) { dt_control_log(_("unable to create album")); result = 0; goto cleanup; } p->facebook_ctx->album_id = g_strdup(album_id); } const char *photoid = fb_upload_photo_to_album(p->facebook_ctx, p->facebook_ctx->album_id, fname, caption); if (photoid == NULL) { dt_control_log(_("unable to export photo to webalbum")); result = 0; goto cleanup; } cleanup: unlink( fname ); g_free( caption ); if(desc) { //no need to free desc->data as caption points to it g_list_free(desc); } if (result) { //this makes sense only if the export was successful dt_control_log(_("%d/%d exported to facebook webalbum"), num, total ); } return 0; }
int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean upscale) { dt_imageio_latex_t *d = (dt_imageio_latex_t *)sdata; char filename[PATH_MAX] = { 0 }; char dirname[PATH_MAX] = { 0 }; gboolean from_cache = FALSE; dt_image_full_path(imgid, dirname, sizeof(dirname), &from_cache); // we're potentially called in parallel. have sequence number synchronized: dt_pthread_mutex_lock(&darktable.plugin_threadsafe); { // if filenamepattern is a directory just add ${FILE_NAME} as default.. if(g_file_test(d->filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) || ((d->filename + strlen(d->filename))[0] == '/' || (d->filename + strlen(d->filename))[0] == '\\')) snprintf(d->filename + strlen(d->filename), sizeof(d->filename) - strlen(d->filename), "$(FILE_NAME)"); // avoid braindead export which is bound to overwrite at random: if(total > 1 && !g_strrstr(d->filename, "$")) { snprintf(d->filename + strlen(d->filename), sizeof(d->filename) - strlen(d->filename), "_$(SEQUENCE)"); } gchar *fixed_path = dt_util_fix_path(d->filename); g_strlcpy(d->filename, fixed_path, sizeof(d->filename)); g_free(fixed_path); d->vp->filename = dirname; d->vp->jobcode = "export"; d->vp->imgid = imgid; d->vp->sequence = num; dt_variables_expand(d->vp, d->filename, TRUE); gchar *result_filename = dt_variables_get_result(d->vp); g_strlcpy(filename, result_filename, sizeof(filename)); g_free(result_filename); g_strlcpy(dirname, filename, sizeof(dirname)); const char *ext = format->extension(fdata); char *c = dirname + strlen(dirname); for(; c > dirname && *c != '/'; c--) ; if(*c == '/') *c = '\0'; if(g_mkdir_with_parents(dirname, 0755)) { fprintf(stderr, "[imageio_storage_latex] could not create directory: `%s'!\n", dirname); dt_control_log(_("could not create directory `%s'!"), dirname); dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); return 1; } // store away dir. snprintf(d->cached_dirname, sizeof(d->cached_dirname), "%s", dirname); c = filename + strlen(filename); // for(; c>filename && *c != '.' && *c != '/' ; c--); // if(c <= filename || *c=='/') c = filename + strlen(filename); sprintf(c, ".%s", ext); // save image to list, in order: pair_t *pair = malloc(sizeof(pair_t)); #if 0 // let's see if we actually want titles and such to be exported: char *title = NULL, *description = NULL, *tags = NULL; GList *res_title, *res_desc, *res_subj; res_title = dt_metadata_get(imgid, "Xmp.dc.title", NULL); if(res_title) { title = res_title->data; } res_desc = dt_metadata_get(imgid, "Xmp.dc.description", NULL); if(res_desc) { description = res_desc->data; } res_subj = dt_metadata_get(imgid, "Xmp.dc.subject", NULL); if(res_subj) { // don't show the internal tags (darktable|...) res_subj = g_list_first(res_subj); GList *iter = res_subj; while(iter) { GList *next = g_list_next(iter); if(g_str_has_prefix(iter->data, "darktable|")) { g_free(iter->data); res_subj = g_list_delete_link(res_subj, iter); } iter = next; } tags = dt_util_glist_to_str(", ", res_subj); g_list_free_full(res_subj, g_free); } #endif char relfilename[PATH_MAX] = { 0 }; c = filename + strlen(filename); for(; c > filename && *c != '/'; c--) ; if(*c == '/') c++; if(c <= filename) c = filename; snprintf(relfilename, sizeof(relfilename), "%s", c); snprintf(pair->line, sizeof(pair->line), "\\begin{minipage}{\\imgwidth}%%\n" "\\drawtrimcorners%%\n" "\\vskip0pt plus 1filll\n" "\\begin{minipage}{\\imgwidth}%%\n" " \\hfil\\includegraphics[width=\\imgwidth,height=\\imgheight,keepaspectratio]{%s}\\hfil\n" " %% put text under image here\n" "\\end{minipage}\n" "\\end{minipage}\n" "\\newpage\n\n", relfilename); pair->pos = num; // g_list_free_full(res_title, &g_free); // g_list_free_full(res_desc, &g_free); // g_list_free_full(res_subj, &g_free); // g_free(tags); d->l = g_list_insert_sorted(d->l, pair, (GCompareFunc)sort_pos); } // end of critical block dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); /* export image to file */ dt_imageio_export(imgid, filename, format, fdata, high_quality, upscale, FALSE, self, sdata, num, total); printf("[export_job] exported to `%s'\n", filename); char *trunc = filename + strlen(filename) - 32; if(trunc < filename) trunc = filename; dt_control_log(ngettext("%d/%d exported to `%s%s'", "%d/%d exported to `%s%s'", num), num, total, trunc != filename ? ".." : "", trunc); return 0; }
/* update all values to reflect mouse over image id or no data at all */ static void _metadata_view_update_values(dt_lib_module_t *self) { dt_lib_metadata_view_t *d = (dt_lib_metadata_view_t *)self->data; int32_t mouse_over_id = -1; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id >= 0) { const int vl = 512; char value[vl]; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); if(!img) goto fill_minuses; if(img->film_id == -1) { dt_image_cache_read_release(darktable.image_cache, img); goto fill_minuses; } /* update all metadata */ dt_image_film_roll(img, value, vl); _metadata_update_value(d->metadata[md_internal_filmroll], value); snprintf(value,vl,"%d", img->id); _metadata_update_value(d->metadata[md_internal_imgid], value); _metadata_update_value(d->metadata[md_internal_filename], img->filename); dt_image_full_path(img->id, value, MAXPATHLEN); _metadata_update_value(d->metadata[md_internal_fullpath], value); /* EXIF */ _metadata_update_value_end(d->metadata[md_exif_model], img->exif_model); _metadata_update_value_end(d->metadata[md_exif_lens], img->exif_lens); _metadata_update_value_end(d->metadata[md_exif_maker], img->exif_maker); snprintf(value, vl, "F/%.1f", img->exif_aperture); _metadata_update_value(d->metadata[md_exif_aperture], value); if(img->exif_exposure <= 0.5) snprintf(value, vl, "1/%.0f", 1.0/img->exif_exposure); else snprintf(value, vl, "%.1f''", img->exif_exposure); _metadata_update_value(d->metadata[md_exif_exposure], value); snprintf(value, vl, "%.0f", img->exif_focal_length); _metadata_update_value(d->metadata[md_exif_focal_length], value); snprintf(value, vl, "%.0f", img->exif_focus_distance); _metadata_update_value(d->metadata[md_exif_focus_distance], value); snprintf(value, vl, "%.0f", img->exif_iso); _metadata_update_value(d->metadata[md_exif_iso], value); _metadata_update_value(d->metadata[md_exif_datetime], img->exif_datetime_taken); snprintf(value, vl, "%d", img->height); _metadata_update_value(d->metadata[md_exif_height], value); snprintf(value, vl, "%d", img->width); _metadata_update_value(d->metadata[md_exif_width], value); /* XMP */ GList *res; if((res = dt_metadata_get(img->id, "Xmp.dc.title", NULL))!=NULL) { snprintf(value, vl, "%s", (char*)res->data); _filter_non_printable(value, vl); g_free(res->data); g_list_free(res); } else snprintf(value, vl, NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_title], value); if((res = dt_metadata_get(img->id, "Xmp.dc.creator", NULL))!=NULL) { snprintf(value, vl, "%s", (char*)res->data); _filter_non_printable(value, vl); g_free(res->data); g_list_free(res); } else snprintf(value, vl, NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_creator], value); if((res = dt_metadata_get(img->id, "Xmp.dc.rights", NULL))!=NULL) { snprintf(value, vl, "%s", (char*)res->data); _filter_non_printable(value, vl); g_free(res->data); g_list_free(res); } else snprintf(value, vl, NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_rights], value); /* geotagging */ /* latitude */ if(isnan(img->latitude)) { _metadata_update_value(d->metadata[md_geotagging_lat], NODATA_STRING); } else { gchar *latitude = osd_latitude_str(img->latitude); _metadata_update_value(d->metadata[md_geotagging_lat], latitude); g_free(latitude); } /* longitude */ if(isnan(img->longitude)) { _metadata_update_value(d->metadata[md_geotagging_lon], NODATA_STRING); } else { gchar *longitude = osd_longitude_str(img->longitude); _metadata_update_value(d->metadata[md_geotagging_lon], longitude); g_free(longitude); } /* release img */ dt_image_cache_read_release(darktable.image_cache, img); } return; /* reset */ fill_minuses: for(int k=0; k<md_size; k++) _metadata_update_value(d->metadata[k],NODATA_STRING); }
/* update all values to reflect mouse over image id or no data at all */ static void _metadata_view_update_values(dt_lib_module_t *self) { dt_lib_metadata_view_t *d = (dt_lib_metadata_view_t *)self->data; int32_t mouse_over_id = dt_control_get_mouse_over_id(); if (mouse_over_id == -1) { const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager); if(cv->view((dt_view_t*)cv) == DT_VIEW_DARKROOM) { mouse_over_id = darktable.develop->image_storage.id; } else { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images limit 1", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) mouse_over_id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } } if(mouse_over_id >= 0) { char value[512]; char pathname[PATH_MAX]; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); if(!img) goto fill_minuses; if(img->film_id == -1) { dt_image_cache_read_release(darktable.image_cache, img); goto fill_minuses; } /* update all metadata */ dt_image_film_roll(img, value, sizeof(value)); _metadata_update_value(d->metadata[md_internal_filmroll], value); const int tp = 512; char tooltip[tp]; snprintf(tooltip, tp, _("double click to jump to film roll\n%s"), value); g_object_set(G_OBJECT(d->metadata[md_internal_filmroll]), "tooltip-text", tooltip, (char *)NULL); snprintf(value,sizeof(value),"%d", img->id); _metadata_update_value(d->metadata[md_internal_imgid], value); _metadata_update_value(d->metadata[md_internal_filename], img->filename); snprintf(value,sizeof(value),"%d", img->version); _metadata_update_value(d->metadata[md_internal_version], value); gboolean from_cache = FALSE; dt_image_full_path(img->id, pathname, sizeof(pathname), &from_cache); _metadata_update_value(d->metadata[md_internal_fullpath], pathname); snprintf(value, sizeof(value), "%s", (img->flags & DT_IMAGE_LOCAL_COPY)?_("yes"):_("no")); _metadata_update_value(d->metadata[md_internal_local_copy], value); /* EXIF */ _metadata_update_value_end(d->metadata[md_exif_model], img->exif_model); _metadata_update_value_end(d->metadata[md_exif_lens], img->exif_lens); _metadata_update_value_end(d->metadata[md_exif_maker], img->exif_maker); snprintf(value, sizeof(value), "F/%.1f", img->exif_aperture); _metadata_update_value(d->metadata[md_exif_aperture], value); if(img->exif_exposure <= 0.5) snprintf(value, sizeof(value), "1/%.0f", 1.0/img->exif_exposure); else snprintf(value, sizeof(value), "%.1f''", img->exif_exposure); _metadata_update_value(d->metadata[md_exif_exposure], value); snprintf(value, sizeof(value), "%.0f mm", img->exif_focal_length); _metadata_update_value(d->metadata[md_exif_focal_length], value); if (isnan(img->exif_focus_distance) || fpclassify(img->exif_focus_distance) == FP_ZERO) { _metadata_update_value(d->metadata[md_exif_focus_distance], NODATA_STRING); } else { snprintf(value, sizeof(value), "%.2f m", img->exif_focus_distance); _metadata_update_value(d->metadata[md_exif_focus_distance], value); } snprintf(value, sizeof(value), "%.0f", img->exif_iso); _metadata_update_value(d->metadata[md_exif_iso], value); _metadata_update_value(d->metadata[md_exif_datetime], img->exif_datetime_taken); snprintf(value, sizeof(value), "%d", img->height); _metadata_update_value(d->metadata[md_exif_height], value); snprintf(value, sizeof(value), "%d", img->width); _metadata_update_value(d->metadata[md_exif_width], value); /* XMP */ GList *res; if((res = dt_metadata_get(img->id, "Xmp.dc.title", NULL))!=NULL) { snprintf(value, sizeof(value), "%s", (char*)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_title], value); if((res = dt_metadata_get(img->id, "Xmp.dc.creator", NULL))!=NULL) { snprintf(value, sizeof(value), "%s", (char*)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_creator], value); if((res = dt_metadata_get(img->id, "Xmp.dc.rights", NULL))!=NULL) { snprintf(value, sizeof(value), "%s", (char*)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_rights], value); /* geotagging */ /* latitude */ if(isnan(img->latitude)) { _metadata_update_value(d->metadata[md_geotagging_lat], NODATA_STRING); } else { #ifdef HAVE_MAP if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *latitude = osd_latitude_str(img->latitude); _metadata_update_value(d->metadata[md_geotagging_lat], latitude); g_free(latitude); } else { #endif gchar NS = img->latitude<0?'S':'N'; snprintf(value, sizeof(value), "%c %09.6f", NS, fabs(img->latitude)); _metadata_update_value(d->metadata[md_geotagging_lat], value); #ifdef HAVE_MAP } #endif } /* longitude */ if(isnan(img->longitude)) { _metadata_update_value(d->metadata[md_geotagging_lon], NODATA_STRING); } else { #ifdef HAVE_MAP if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *longitude = osd_longitude_str(img->longitude); _metadata_update_value(d->metadata[md_geotagging_lon], longitude); g_free(longitude); } else { #endif gchar EW = img->longitude<0?'W':'E'; snprintf(value, sizeof(value), "%c %010.6f", EW, fabs(img->longitude)); _metadata_update_value(d->metadata[md_geotagging_lon], value); #ifdef HAVE_MAP } #endif } /* release img */ dt_image_cache_read_release(darktable.image_cache, img); } return; /* reset */ fill_minuses: for(int k=0; k<md_size; k++) _metadata_update_value(d->metadata[k],NODATA_STRING); }
/* update all values to reflect mouse over image id or no data at all */ static void _metadata_view_update_values(dt_lib_module_t *self) { dt_lib_metadata_view_t *d = (dt_lib_metadata_view_t *)self->data; int32_t mouse_over_id = dt_control_get_mouse_over_id(); if(mouse_over_id == -1) { const dt_view_t *cv = dt_view_manager_get_current_view(darktable.view_manager); if(cv->view((dt_view_t *)cv) == DT_VIEW_DARKROOM) { mouse_over_id = darktable.develop->image_storage.id; } else { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images limit 1", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) mouse_over_id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } } if(mouse_over_id >= 0) { char value[512]; char pathname[PATH_MAX] = { 0 }; const dt_image_t *img = dt_image_cache_get(darktable.image_cache, mouse_over_id, 'r'); if(!img) goto fill_minuses; if(img->film_id == -1) { dt_image_cache_read_release(darktable.image_cache, img); goto fill_minuses; } /* update all metadata */ dt_image_film_roll(img, value, sizeof(value)); _metadata_update_value(d->metadata[md_internal_filmroll], value); const int tp = 512; char tooltip[tp]; snprintf(tooltip, tp, _("double click to jump to film roll\n%s"), value); gtk_widget_set_tooltip_text(GTK_WIDGET(d->metadata[md_internal_filmroll]), tooltip); snprintf(value, sizeof(value), "%d", img->id); _metadata_update_value(d->metadata[md_internal_imgid], value); snprintf(value, sizeof(value), "%d", img->group_id); _metadata_update_value(d->metadata[md_internal_groupid], value); _metadata_update_value(d->metadata[md_internal_filename], img->filename); snprintf(value, sizeof(value), "%d", img->version); _metadata_update_value(d->metadata[md_internal_version], value); gboolean from_cache = FALSE; dt_image_full_path(img->id, pathname, sizeof(pathname), &from_cache); _metadata_update_value(d->metadata[md_internal_fullpath], pathname); snprintf(value, sizeof(value), "%s", (img->flags & DT_IMAGE_LOCAL_COPY) ? _("yes") : _("no")); _metadata_update_value(d->metadata[md_internal_local_copy], value); // TODO: decide if this should be removed for a release. maybe #ifdef'ing to only add it to git compiles? // the bits of the flags #if SHOW_FLAGS { #define EMPTY_FIELD '.' #define FALSE_FIELD '.' #define TRUE_FIELD '!' char *tooltip = NULL; char *flag_descriptions[] = { N_("unused"), N_("unused/deprecated"), N_("ldr"), N_("raw"), N_("hdr"), N_("marked for deletion"), N_("auto-applying presets applied"), N_("legacy flag. set for all new images"), N_("local copy"), N_("has .txt"), N_("has .wav") }; char *tooltip_parts[14] = { 0 }; int next_tooltip_part = 0; memset(value, EMPTY_FIELD, sizeof(value)); int stars = img->flags & 0x7; char *star_string = NULL; if(stars == 6) { value[0] = 'x'; tooltip_parts[next_tooltip_part++] = _("image rejected"); } else { value[0] = '0' + stars; tooltip_parts[next_tooltip_part++] = star_string = g_strdup_printf(ngettext("image has %d star", "image has %d stars", stars), stars); } if(img->flags & 8) { value[1] = TRUE_FIELD; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[0]); } else value[1] = FALSE_FIELD; if(img->flags & DT_IMAGE_THUMBNAIL_DEPRECATED) { value[2] = TRUE_FIELD; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[1]); } else value[2] = FALSE_FIELD; if(img->flags & DT_IMAGE_LDR) { value[3] = 'l'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[2]); } if(img->flags & DT_IMAGE_RAW) { value[4] = 'r'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[3]); } if(img->flags & DT_IMAGE_HDR) { value[5] = 'h'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[4]); } if(img->flags & DT_IMAGE_REMOVE) { value[6] = 'd'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[5]); } if(img->flags & DT_IMAGE_AUTO_PRESETS_APPLIED) { value[7] = 'a'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[6]); } if(img->flags & DT_IMAGE_NO_LEGACY_PRESETS) { value[8] = 'p'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[7]); } if(img->flags & DT_IMAGE_LOCAL_COPY) { value[9] = 'c'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[8]); } if(img->flags & DT_IMAGE_HAS_TXT) { value[10] = 't'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[9]); } if(img->flags & DT_IMAGE_HAS_WAV) { value[11] = 'w'; tooltip_parts[next_tooltip_part++] = _(flag_descriptions[10]); } static const struct { char *tooltip; char flag; } loaders[] = { { N_("unknown"), EMPTY_FIELD}, { N_("tiff"), 't'}, { N_("png"), 'p'}, { N_("j2k"), 'J'}, { N_("jpeg"), 'j'}, { N_("exr"), 'e'}, { N_("rgbe"), 'R'}, { N_("pfm"), 'P'}, { N_("GraphicsMagick"), 'g'}, { N_("rawspeed"), 'r'} }; int loader = (unsigned int)img->loader < sizeof(loaders) / sizeof(*loaders) ? img->loader : 0; value[12] = loaders[loader].flag; char *loader_tooltip = g_strdup_printf(_("loader: %s"), _(loaders[loader].tooltip)); tooltip_parts[next_tooltip_part++] = loader_tooltip; value[13] = '\0'; tooltip = g_strjoinv("\n", tooltip_parts); g_free(loader_tooltip); _metadata_update_value(d->metadata[md_internal_flags], value); gtk_widget_set_tooltip_text(GTK_WIDGET(d->metadata[md_internal_flags]), tooltip); g_free(star_string); g_free(tooltip); #undef EMPTY_FIELD #undef FALSE_FIELD #undef TRUE_FIELD } #endif // SHOW_FLAGS /* EXIF */ _metadata_update_value_end(d->metadata[md_exif_model], img->camera_alias); _metadata_update_value_end(d->metadata[md_exif_lens], img->exif_lens); _metadata_update_value_end(d->metadata[md_exif_maker], img->camera_maker); snprintf(value, sizeof(value), "F/%.1f", img->exif_aperture); _metadata_update_value(d->metadata[md_exif_aperture], value); if(img->exif_exposure <= 0.5) snprintf(value, sizeof(value), "1/%.0f", 1.0 / img->exif_exposure); else snprintf(value, sizeof(value), "%.1f''", img->exif_exposure); _metadata_update_value(d->metadata[md_exif_exposure], value); snprintf(value, sizeof(value), "%.0f mm", img->exif_focal_length); _metadata_update_value(d->metadata[md_exif_focal_length], value); if(isnan(img->exif_focus_distance) || fpclassify(img->exif_focus_distance) == FP_ZERO) { _metadata_update_value(d->metadata[md_exif_focus_distance], NODATA_STRING); } else { snprintf(value, sizeof(value), "%.2f m", img->exif_focus_distance); _metadata_update_value(d->metadata[md_exif_focus_distance], value); } snprintf(value, sizeof(value), "%.0f", img->exif_iso); _metadata_update_value(d->metadata[md_exif_iso], value); struct tm tt_exif = { 0 }; if(sscanf(img->exif_datetime_taken, "%d:%d:%d %d:%d:%d", &tt_exif.tm_year, &tt_exif.tm_mon, &tt_exif.tm_mday, &tt_exif.tm_hour, &tt_exif.tm_min, &tt_exif.tm_sec) == 6) { char datetime[200]; tt_exif.tm_year -= 1900; tt_exif.tm_mon--; tt_exif.tm_isdst = -1; mktime(&tt_exif); // just %c is too long and includes a time zone that we don't know from exif strftime(datetime, sizeof(datetime), "%a %x %X", &tt_exif); _metadata_update_value(d->metadata[md_exif_datetime], datetime); } else _metadata_update_value(d->metadata[md_exif_datetime], img->exif_datetime_taken); snprintf(value, sizeof(value), "%d", img->height); _metadata_update_value(d->metadata[md_exif_height], value); snprintf(value, sizeof(value), "%d", img->width); _metadata_update_value(d->metadata[md_exif_width], value); /* XMP */ GList *res; if((res = dt_metadata_get(img->id, "Xmp.dc.title", NULL)) != NULL) { snprintf(value, sizeof(value), "%s", (char *)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_title], value); if((res = dt_metadata_get(img->id, "Xmp.dc.creator", NULL)) != NULL) { snprintf(value, sizeof(value), "%s", (char *)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_creator], value); if((res = dt_metadata_get(img->id, "Xmp.dc.rights", NULL)) != NULL) { snprintf(value, sizeof(value), "%s", (char *)res->data); _filter_non_printable(value, sizeof(value)); g_list_free_full(res, &g_free); } else snprintf(value, sizeof(value), NODATA_STRING); _metadata_update_value(d->metadata[md_xmp_rights], value); /* geotagging */ /* latitude */ if(isnan(img->latitude)) { _metadata_update_value(d->metadata[md_geotagging_lat], NODATA_STRING); } else { if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *latitude = dt_util_latitude_str(img->latitude); _metadata_update_value(d->metadata[md_geotagging_lat], latitude); g_free(latitude); } else { gchar NS = img->latitude < 0 ? 'S' : 'N'; snprintf(value, sizeof(value), "%c %09.6f", NS, fabs(img->latitude)); _metadata_update_value(d->metadata[md_geotagging_lat], value); } } /* longitude */ if(isnan(img->longitude)) { _metadata_update_value(d->metadata[md_geotagging_lon], NODATA_STRING); } else { if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *longitude = dt_util_longitude_str(img->longitude); _metadata_update_value(d->metadata[md_geotagging_lon], longitude); g_free(longitude); } else { gchar EW = img->longitude < 0 ? 'W' : 'E'; snprintf(value, sizeof(value), "%c %010.6f", EW, fabs(img->longitude)); _metadata_update_value(d->metadata[md_geotagging_lon], value); } } /* elevation */ if(isnan(img->elevation)) { _metadata_update_value(d->metadata[md_geotagging_ele], NODATA_STRING); } else { if(dt_conf_get_bool("plugins/lighttable/metadata_view/pretty_location")) { gchar *elevation = dt_util_elevation_str(img->elevation); _metadata_update_value(d->metadata[md_geotagging_ele], elevation); g_free(elevation); } else { snprintf(value, sizeof(value), "%.2f %s", img->elevation, _("m")); _metadata_update_value(d->metadata[md_geotagging_ele], value); } } /* release img */ dt_image_cache_read_release(darktable.image_cache, img); #ifdef USE_LUA dt_lua_async_call_alien(lua_update_metadata, 0,NULL,NULL, LUA_ASYNC_TYPENAME,"void*",self, LUA_ASYNC_TYPENAME,"int32_t",mouse_over_id,LUA_ASYNC_DONE); #endif } return; /* reset */ fill_minuses: for(int k = 0; k < md_size; k++) _metadata_update_value(d->metadata[k], NODATA_STRING); #ifdef USE_LUA dt_lua_async_call_alien(lua_update_metadata, 0,NULL,NULL, LUA_ASYNC_TYPENAME,"void*",self, LUA_ASYNC_TYPENAME,"int32_t",-1,LUA_ASYNC_DONE); #endif }
/* this actually does the work */ int store(dt_imageio_module_storage_t *self, struct dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean upscale, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent) { dt_storage_gphoto_gui_data_t *ui = self->gui_data; gint result = 1; dt_gphoto_context_t *ctx = (dt_gphoto_context_t *)sdata; const char *ext = format->extension(fdata); char fname[PATH_MAX] = { 0 }; dt_loc_get_tmp_dir(fname, sizeof(fname)); g_strlcat(fname, "/darktable.XXXXXX.", sizeof(fname)); g_strlcat(fname, ext, sizeof(fname)); gint fd = g_mkstemp(fname); if(fd == -1) { dt_control_log("failed to create temporary image for google photos export"); return 1; } close(fd); // get metadata const dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'r'); char *title = NULL; char *summary = NULL; GList *meta_title = NULL; title = g_path_get_basename(img->filename); (g_strrstr(title, "."))[0] = '\0'; // Chop extension... meta_title = dt_metadata_get(img->id, "Xmp.dc.title", NULL); summary = meta_title != NULL ? meta_title->data : ""; dt_image_cache_read_release(darktable.image_cache, img); if(dt_imageio_export(imgid, fname, format, fdata, high_quality, upscale, FALSE, icc_type, icc_filename, icc_intent, self, sdata, num, total) != 0) { g_printerr("[gphoto] could not export to file: `%s'!\n", fname); dt_control_log(_("could not export to file `%s'!"), fname); result = 0; goto cleanup; } if(!*(ctx->album_id)) { if(ctx->album_title == NULL) { dt_control_log(_("unable to create album, no title provided")); result = 0; goto cleanup; } const gchar *album_id = gphoto_create_album(ui, ctx, ctx->album_title); if(album_id == NULL) { dt_control_log(_("unable to create album")); result = 0; goto cleanup; } g_snprintf(ctx->album_id, sizeof(ctx->album_id), "%s", album_id); } const char *photoid = gphoto_upload_photo_to_album(ctx, ctx->album_id, fname, title, summary, imgid); if(photoid == NULL) { dt_control_log(_("unable to export to google photos album")); result = 0; goto cleanup; } cleanup: g_unlink(fname); g_free(title); g_list_free_full(meta_title, &g_free); if(result) { // this makes sense only if the export was successful dt_control_log(ngettext("%d/%d exported to google photos album", "%d/%d exported to google photos album", num), num, total); } return 0; }
int store (dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality) { gint tags = 0; int result=1; dt_storage_picasa_params_t *p=(dt_storage_picasa_params_t *)sdata; int fail = 0; #ifdef _OPENMP // synch parallel store #pragma omp critical #endif if( p->picasa_api->current_album == NULL ) if( _picasa_api_create_album( p->picasa_api ) != 201 ) { dt_control_log("failed to create picasa album"); fail = 1; } if(fail) return 1; const char *ext = format->extension(fdata); // Let's upload image... /* construct a temporary file name */ char fname[4096]= {0}; dt_loc_get_tmp_dir (fname,4096); g_strlcat (fname,"/darktable.XXXXXX.",4096); g_strlcat(fname,ext,4096); char *caption="a image"; char *description=""; char *mime="image/jpeg"; // Ok, maybe a dt_imageio_export_to_buffer would suit here !? gint fd=g_mkstemp(fname); fprintf(stderr,"tempfile: %s\n",fname); if(fd==-1) { dt_control_log("failed to create temporary image for picasa export"); return 1; } close(fd); const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); caption = g_path_get_basename( img->filename ); (g_strrstr(caption,"."))[0]='\0'; // Shop extension... GList *desc = dt_metadata_get(img->id, "Xmp.dc.description", NULL); if(desc != NULL) { description = desc->data; } dt_image_cache_read_release(darktable.image_cache, img); if(dt_imageio_export(imgid, fname, format, fdata, high_quality) != 0) { fprintf(stderr, "[imageio_storage_picasa] could not export to file: `%s'!\n", fname); dt_control_log(_("could not export to file `%s'!"), fname); result = 1; goto cleanup; } // Open the temp file and read image to memory GMappedFile *imgfile = g_mapped_file_new(fname,FALSE,NULL); int size = g_mapped_file_get_length( imgfile ); gchar *data =g_mapped_file_get_contents( imgfile ); #ifdef _OPENMP #pragma omp critical #endif { // Fetch the attached tags of image id if exported.. if( p->export_tags == TRUE ) tags = imgid; // Upload image to picasa if( _picasa_api_upload_photo( p->picasa_api, mime , data, size , caption, description, tags ) == 201 ) result=0; } // Unreference the memorymapped file... g_mapped_file_unref( imgfile ); // And remove from filesystem.. unlink( fname ); cleanup: g_free( caption ); if(desc) { g_free(desc->data); g_list_free(desc); } if(!result) dt_control_log(_("%d/%d exported to picasa webalbum"), num, total ); return result; }
int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean upscale, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent) { dt_storage_piwigo_gui_data_t *ui = self->gui_data; gint result = 0; const char *ext = format->extension(fdata); // Let's upload image... /* construct a temporary file name */ char fname[PATH_MAX] = { 0 }; dt_loc_get_tmp_dir(fname, sizeof(fname)); g_strlcat(fname, "/darktable.XXXXXX.", sizeof(fname)); g_strlcat(fname, ext, sizeof(fname)); char *caption = NULL; char *description = NULL; char *author = NULL; gint fd = g_mkstemp(fname); if(fd == -1) { dt_control_log("failed to create temporary image for piwigo export"); fprintf(stderr, "failed to create tempfile: %s\n", fname); return 1; } close(fd); const dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'r'); // If title is not existing, then use the filename without extension. If not, then use title instead GList *title = dt_metadata_get(img->id, "Xmp.dc.title", NULL); if(title != NULL) { caption = g_strdup(title->data); g_list_free_full(title, &g_free); } else { caption = g_path_get_basename(img->filename); (g_strrstr(caption, "."))[0] = '\0'; // chop extension... } GList *desc = dt_metadata_get(img->id, "Xmp.dc.description", NULL); if(desc != NULL) { description = g_strdup(desc->data); g_list_free_full(desc, &g_free); } dt_image_cache_read_release(darktable.image_cache, img); GList *auth = dt_metadata_get(img->id, "Xmp.dc.creator", NULL); if(auth != NULL) { author = g_strdup(auth->data); g_list_free_full(auth, &g_free); } if(dt_imageio_export(imgid, fname, format, fdata, high_quality, upscale, FALSE, icc_type, icc_filename, icc_intent, self, sdata, num, total) != 0) { fprintf(stderr, "[imageio_storage_piwigo] could not export to file: `%s'!\n", fname); dt_control_log(_("could not export to file `%s'!"), fname); result = 1; goto cleanup; } dt_pthread_mutex_lock(&darktable.plugin_threadsafe); { gboolean status = TRUE; dt_storage_piwigo_params_t *p = (dt_storage_piwigo_params_t *)sdata; if(p->export_tags) { GList *tags_list = dt_tag_get_list(imgid); if(p->tags) g_free(p->tags); p->tags = dt_util_glist_to_str(",", tags_list); g_list_free_full(tags_list, g_free); } if(p->new_album) { status = _piwigo_api_create_new_album(p); if(!status) dt_control_log(_("cannot create a new piwigo album!")); } if(status) { status = _piwigo_api_upload_photo(p, fname, author, caption, description); if(!status) { fprintf(stderr, "[imageio_storage_piwigo] could not upload to piwigo!\n"); dt_control_log(_("could not upload to piwigo!")); result = 1; } else if (p->new_album) { // we do not want to create more albums when multiple upload p->new_album = FALSE; _piwigo_refresh_albums(ui, p->album); } } } dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); cleanup: // And remove from filesystem.. g_unlink(fname); g_free(caption); g_free(description); g_free(author); if(!result) { // this makes sense only if the export was successful dt_control_log(ngettext("%d/%d exported to piwigo webalbum", "%d/%d exported to piwigo webalbum", num), num, total); } return result; }