int dt_history_load_and_apply_on_selection (gchar *filename) { int res=0; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select * from selected_images", -1, &stmt, NULL); while(sqlite3_step(stmt) == SQLITE_ROW) { int imgid = sqlite3_column_int(stmt, 0); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, (int32_t)imgid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); if(img) { if (dt_exif_xmp_read(img, filename, 1)) { res=1; break; } /* if current image in develop reload history */ if (dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_reload_history_items (darktable.develop); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); } } sqlite3_finalize(stmt); return res; }
int dt_history_load_and_apply(int imgid, gchar *filename, int history_only) { int res = 0; dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'w'); if(img) { if(dt_exif_xmp_read(img, filename, history_only)) return 1; /* if current image in develop reload history */ if(dt_dev_is_current_image(darktable.develop, imgid)) dt_dev_reload_history_items(darktable.develop); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); } return res; }
uint32_t dt_image_import(const int32_t film_id, const char *filename, gboolean override_ignore_jpegs) { if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) return 0; const char *cc = filename + strlen(filename); for(; *cc!='.'&&cc>filename; cc--); if(!strcmp(cc, ".dt")) return 0; if(!strcmp(cc, ".dttags")) return 0; if(!strcmp(cc, ".xmp")) return 0; char *ext = g_ascii_strdown(cc+1, -1); if(override_ignore_jpegs == FALSE && (!strcmp(ext, "jpg") || !strcmp(ext, "jpeg")) && dt_conf_get_bool("ui_last/import_ignore_jpegs")) return 0; int supported = 0; char **extensions = g_strsplit(dt_supported_extensions, ",", 100); for(char **i=extensions; *i!=NULL; i++) if(!strcmp(ext, *i)) { supported = 1; break; } g_strfreev(extensions); if(!supported) { g_free(ext); return 0; } int rc; uint32_t id = 0; // select from images; if found => return gchar *imgfname; imgfname = g_path_get_basename((const gchar*)filename); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where film_id = ?1 and filename = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) { id = sqlite3_column_int(stmt, 0); g_free(imgfname); sqlite3_finalize(stmt); g_free(ext); return id; } sqlite3_finalize(stmt); // also need to set the no-legacy bit, to make sure we get the right presets (new ones) uint32_t flags = dt_conf_get_int("ui_last/import_initial_rating"); if(flags > 5) { flags = 1; dt_conf_set_int("ui_last/import_initial_rating", 1); } flags |= DT_IMAGE_NO_LEGACY_PRESETS; // insert dummy image entry in database DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into images (id, film_id, filename, caption, description, " "license, sha1sum, flags) values (null, ?1, ?2, '', '', '', '', ?3)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, flags); rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) fprintf(stderr, "sqlite3 error %d\n", rc); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where film_id = ?1 and filename = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_STATIC); if(sqlite3_step(stmt) == SQLITE_ROW) id = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); // Try to find out if this should be grouped already. gchar *basename = g_strdup(imgfname); gchar *cc2 = basename + strlen(basename); for(; *cc2!='.'&&cc2>basename; cc2--); *cc2='\0'; gchar *sql_pattern = g_strconcat(basename, ".%", NULL); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select group_id from images where film_id = ?1 and filename like ?2 and id != ?3", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, sql_pattern, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id); int group_id; if(sqlite3_step(stmt) == SQLITE_ROW) group_id = sqlite3_column_int(stmt, 0); else group_id = id; sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update images set group_id = ?1 where id = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, group_id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, id); sqlite3_step(stmt); sqlite3_finalize(stmt); // printf("[image_import] importing `%s' to img id %d\n", imgfname, id); // lock as shortly as possible: const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); img->group_id = group_id; // read dttags and exif for database queries! (void) dt_exif_read(img, filename); char dtfilename[DT_MAX_PATH_LEN]; g_strlcpy(dtfilename, filename, DT_MAX_PATH_LEN); dt_image_path_append_version(id, dtfilename, DT_MAX_PATH_LEN); char *c = dtfilename + strlen(dtfilename); sprintf(c, ".xmp"); (void)dt_exif_xmp_read(img, dtfilename, 0); // write through to db, but not to xmp. dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); // add a tag with the file extension guint tagid = 0; char tagname[512]; snprintf(tagname, 512, "darktable|format|%s", ext); g_free(ext); dt_tag_new(tagname, &tagid); dt_tag_attach(tagid,id); // Search for sidecar files and import them if found. glob_t *globbuf = g_malloc(sizeof(glob_t)); // Add version wildcard gchar *fname = g_strdup(filename); gchar pattern[DT_MAX_PATH_LEN]; g_snprintf(pattern, DT_MAX_PATH_LEN, "%s", filename); char *c1 = pattern + strlen(pattern); while(*c1 != '.' && c1 > pattern) c1--; snprintf(c1, pattern + DT_MAX_PATH_LEN - c1, "_*"); char *c2 = fname + strlen(fname); while(*c2 != '.' && c2 > fname) c2--; snprintf(c1+2, pattern + DT_MAX_PATH_LEN - c1 - 2, "%s.xmp", c2); if (!glob(pattern, 0, NULL, globbuf)) { for (int i=0; i < globbuf->gl_pathc; i++) { int newid = -1; newid = dt_image_duplicate(id); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, newid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); (void)dt_exif_xmp_read(img, globbuf->gl_pathv[i], 0); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, img); } globfree(globbuf); } g_free(imgfname); g_free(fname); g_free(basename); g_free(sql_pattern); g_free(globbuf); dt_control_signal_raise(darktable.signals,DT_SIGNAL_IMAGE_IMPORT,id); return id; }
int main(int argc, char *arg[]) { bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); gtk_init (&argc, &arg); // parse command line arguments char *image_filename = NULL; char *xmp_filename = NULL; char *output_filename = NULL; int file_counter = 0; int width = 0, height = 0, bpp = 0; gboolean verbose = FALSE, high_quality = TRUE; for(int k=1; k<argc; k++) { if(arg[k][0] == '-') { if(!strcmp(arg[k], "--help")) { usage(arg[0]); exit(1); } else if(!strcmp(arg[k], "--version")) { printf("this is darktable-cli\ncopyright (c) 2012-2013 johannes hanika, tobias ellinghaus\n"); exit(1); } else if(!strcmp(arg[k], "--width")) { k++; width = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--height")) { k++; height = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--bpp")) { k++; bpp = MAX(atoi(arg[k]), 0); fprintf(stderr, "%s %d\n", _("TODO: sorry, due to api restrictions we currently cannot set the bpp to"), bpp); } else if(!strcmp(arg[k], "--hq")) { k++; gchar *str = g_ascii_strup(arg[k], -1); if(!g_strcmp0(str, "0") || !g_strcmp0(str, "FALSE")) high_quality = FALSE; else if(!g_strcmp0(str, "1") || !g_strcmp0(str, "TRUE")) high_quality = TRUE; else { fprintf(stderr, "%s: %s\n", _("Unknown option for --hq"), arg[k]); usage(arg[0]); exit(1); } g_free(str); } else if(!strcmp(arg[k], "-v") || !strcmp(arg[k], "--verbose")) { verbose = TRUE; } } else { if(file_counter == 0) image_filename = arg[k]; else if(file_counter == 1) xmp_filename = arg[k]; else if(file_counter == 2) output_filename = arg[k]; file_counter++; } } if(file_counter < 2 || file_counter > 3) { usage(arg[0]); exit(1); } else if(file_counter == 2) { // no xmp file given output_filename = xmp_filename; xmp_filename = NULL; } // the output file already exists, so there will be a sequence number added if(g_file_test(output_filename, G_FILE_TEST_EXISTS)) { fprintf(stderr, "%s\n", _("output file already exists, it will get renamed")); } char *m_arg[] = {"darktable-cli", "--library", ":memory:", NULL}; // init dt without gui: if(dt_init(3, m_arg, 0)) exit(1); dt_film_t film; int id = 0; int filmid = 0; gchar *directory = g_path_get_dirname(image_filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, image_filename, TRUE); if(!id) { fprintf(stderr, _("error: can't open file %s"), image_filename); fprintf(stderr, "\n"); exit(1); } g_free(directory); // attach xmp, if requested: if(xmp_filename) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); dt_exif_xmp_read(image, xmp_filename, 1); // don't write new xmp: dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, image); } // print the history stack if(verbose) { gchar *history = dt_history_get_items_as_string(id); if(history) printf("%s\n", history); else printf("[%s]\n", _("empty history stack")); } // try to find out the export format from the output_filename char *ext = output_filename + strlen(output_filename); while(ext > output_filename && *ext != '.') ext--; *ext = '\0'; ext++; if(!strcmp(ext, "jpg")) ext = "jpeg"; // init the export data structures int size = 0, dat_size = 0; dt_imageio_module_format_t *format; dt_imageio_module_storage_t *storage; dt_imageio_module_data_t *sdata, *fdata; storage = dt_imageio_get_storage_by_name("disk"); // only exporting to disk makes sense if(storage == NULL) { fprintf(stderr, "%s\n", _("cannot find disk storage module. please check your installation, something seems to be broken.")); exit(1); } sdata = storage->get_params(storage, &size); if(sdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from storage module, aborting export ...")); exit(1); } // and now for the really ugly hacks. don't tell your children about this one or they won't sleep at night any longer ... g_strlcpy((char*)sdata, output_filename, DT_MAX_PATH_LEN); // all is good now, the last line didn't happen. format = dt_imageio_get_format_by_name(ext); if(format == NULL) { fprintf(stderr, _("unknown extension '.%s'"), ext); fprintf(stderr, "\n"); exit(1); } fdata = format->get_params(format, &dat_size); if(fdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from format module, aborting export ...")); exit(1); } uint32_t w,h,fw,fh,sw,sh; fw=fh=sw=sh=0; storage->dimension(storage, &sw, &sh); format->dimension(format, &fw, &fh); if( sw==0 || fw==0) w=sw>fw?sw:fw; else w=sw<fw?sw:fw; if( sh==0 || fh==0) h=sh>fh?sh:fh; else h=sh<fh?sh:fh; fdata->max_width = width; fdata->max_height = height; fdata->max_width = (w!=0 && fdata->max_width >w)?w:fdata->max_width; fdata->max_height = (h!=0 && fdata->max_height >h)?h:fdata->max_height; fdata->style[0] = '\0'; //TODO: add a callback to set the bpp without going through the config storage->store(storage,sdata, id, format, fdata, 1, 1, high_quality); // cleanup time if(storage->finalize_store) storage->finalize_store(storage, sdata); storage->free_params(storage, sdata); format->free_params(format, fdata); dt_cleanup(); }
int main(int argc, char *arg[]) { bindtextdomain(GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); if(!gtk_parse_args(&argc, &arg)) exit(1); // parse command line arguments char *input_filename = NULL; char *xmp_filename = NULL; char *output_filename = NULL; int file_counter = 0; int width = 0, height = 0, bpp = 0; gboolean verbose = FALSE, high_quality = TRUE, upscale = FALSE; int k; for(k = 1; k < argc; k++) { if(arg[k][0] == '-') { if(!strcmp(arg[k], "--help")) { usage(arg[0]); exit(1); } else if(!strcmp(arg[k], "--version")) { printf("this is darktable-cli %s\ncopyright (c) 2012-2016 johannes hanika, tobias ellinghaus\n", darktable_package_version); exit(1); } else if(!strcmp(arg[k], "--width") && argc > k + 1) { k++; width = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--height") && argc > k + 1) { k++; height = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--bpp") && argc > k + 1) { k++; bpp = MAX(atoi(arg[k]), 0); fprintf(stderr, "%s %d\n", _("TODO: sorry, due to API restrictions we currently cannot set the BPP to"), bpp); } else if(!strcmp(arg[k], "--hq") && argc > k + 1) { k++; gchar *str = g_ascii_strup(arg[k], -1); if(!g_strcmp0(str, "0") || !g_strcmp0(str, "FALSE")) high_quality = FALSE; else if(!g_strcmp0(str, "1") || !g_strcmp0(str, "TRUE")) high_quality = TRUE; else { fprintf(stderr, "%s: %s\n", _("unknown option for --hq"), arg[k]); usage(arg[0]); exit(1); } g_free(str); } else if(!strcmp(arg[k], "--upscale") && argc > k + 1) { k++; gchar *str = g_ascii_strup(arg[k], -1); if(!g_strcmp0(str, "0") || !g_strcmp0(str, "FALSE")) upscale = FALSE; else if(!g_strcmp0(str, "1") || !g_strcmp0(str, "TRUE")) upscale= TRUE; else { fprintf(stderr, "%s: %s\n", _("unknown option for --upscale"), arg[k]); usage(arg[0]); exit(1); } g_free(str); } else if(!strcmp(arg[k], "-v") || !strcmp(arg[k], "--verbose")) { verbose = TRUE; } else if(!strcmp(arg[k], "--core")) { // everything from here on should be passed to the core k++; break; } } else { if(file_counter == 0) input_filename = arg[k]; else if(file_counter == 1) xmp_filename = arg[k]; else if(file_counter == 2) output_filename = arg[k]; file_counter++; } } int m_argc = 0; char **m_arg = malloc((5 + argc - k + 1) * sizeof(char *)); m_arg[m_argc++] = "darktable-cli"; m_arg[m_argc++] = "--library"; m_arg[m_argc++] = ":memory:"; m_arg[m_argc++] = "--conf"; m_arg[m_argc++] = "write_sidecar_files=FALSE"; for(; k < argc; k++) m_arg[m_argc++] = arg[k]; m_arg[m_argc] = NULL; if(file_counter < 2 || file_counter > 3) { usage(arg[0]); free(m_arg); exit(1); } else if(file_counter == 2) { // no xmp file given output_filename = xmp_filename; xmp_filename = NULL; } if(g_file_test(output_filename, G_FILE_TEST_IS_DIR)) { fprintf(stderr, _("error: output file is a directory. please specify file name")); fprintf(stderr, "\n"); free(m_arg); exit(1); } // the output file already exists, so there will be a sequence number added if(g_file_test(output_filename, G_FILE_TEST_EXISTS)) { fprintf(stderr, "%s\n", _("output file already exists, it will get renamed")); } // init dt without gui: if(dt_init(m_argc, m_arg, 0, NULL)) { free(m_arg); exit(1); } GList *id_list = NULL; if(g_file_test(input_filename, G_FILE_TEST_IS_DIR)) { int filmid = dt_film_import(input_filename); if(!filmid) { fprintf(stderr, _("error: can't open folder %s"), input_filename); fprintf(stderr, "\n"); free(m_arg); exit(1); } id_list = dt_film_get_image_ids(filmid); } else { dt_film_t film; int id = 0; int filmid = 0; gchar *directory = g_path_get_dirname(input_filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, input_filename, TRUE); if(!id) { fprintf(stderr, _("error: can't open file %s"), input_filename); fprintf(stderr, "\n"); free(m_arg); exit(1); } g_free(directory); id_list = g_list_append(id_list, GINT_TO_POINTER(id)); } int total = g_list_length(id_list); if(total == 0) { fprintf(stderr, _("no images to export, aborting\n")); free(m_arg); exit(1); } // attach xmp, if requested: if(xmp_filename) { for(GList *iter = id_list; iter; iter = g_list_next(iter)) { int id = GPOINTER_TO_INT(iter->data); dt_image_t *image = dt_image_cache_get(darktable.image_cache, id, 'w'); dt_exif_xmp_read(image, xmp_filename, 1); // don't write new xmp: dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_RELAXED); } } // print the history stack. only look at the first image and assume all got the same processing applied if(verbose) { int id = GPOINTER_TO_INT(id_list->data); gchar *history = dt_history_get_items_as_string(id); if(history) printf("%s\n", history); else printf("[%s]\n", _("empty history stack")); } // try to find out the export format from the output_filename char *ext = output_filename + strlen(output_filename); while(ext > output_filename && *ext != '.') ext--; *ext = '\0'; ext++; if(!strcmp(ext, "jpg")) ext = "jpeg"; if(!strcmp(ext, "tif")) ext = "tiff"; // init the export data structures dt_imageio_module_format_t *format; dt_imageio_module_storage_t *storage; dt_imageio_module_data_t *sdata, *fdata; storage = dt_imageio_get_storage_by_name("disk"); // only exporting to disk makes sense if(storage == NULL) { fprintf( stderr, "%s\n", _("cannot find disk storage module. please check your installation, something seems to be broken.")); free(m_arg); exit(1); } sdata = storage->get_params(storage); if(sdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from storage module, aborting export ...")); free(m_arg); exit(1); } // and now for the really ugly hacks. don't tell your children about this one or they won't sleep at night // any longer ... g_strlcpy((char *)sdata, output_filename, DT_MAX_PATH_FOR_PARAMS); // all is good now, the last line didn't happen. format = dt_imageio_get_format_by_name(ext); if(format == NULL) { fprintf(stderr, _("unknown extension '.%s'"), ext); fprintf(stderr, "\n"); free(m_arg); exit(1); } fdata = format->get_params(format); if(fdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from format module, aborting export ...")); free(m_arg); exit(1); } uint32_t w, h, fw, fh, sw, sh; fw = fh = sw = sh = 0; storage->dimension(storage, sdata, &sw, &sh); format->dimension(format, fdata, &fw, &fh); if(sw == 0 || fw == 0) w = sw > fw ? sw : fw; else w = sw < fw ? sw : fw; if(sh == 0 || fh == 0) h = sh > fh ? sh : fh; else h = sh < fh ? sh : fh; fdata->max_width = width; fdata->max_height = height; fdata->max_width = (w != 0 && fdata->max_width > w) ? w : fdata->max_width; fdata->max_height = (h != 0 && fdata->max_height > h) ? h : fdata->max_height; fdata->style[0] = '\0'; fdata->style_append = 0; if(storage->initialize_store) { storage->initialize_store(storage, sdata, &format, &fdata, &id_list, high_quality, upscale); format->set_params(format, fdata, format->params_size(format)); storage->set_params(storage, sdata, storage->params_size(storage)); } // TODO: add a callback to set the bpp without going through the config int num = 1; for(GList *iter = id_list; iter; iter = g_list_next(iter), num++) { int id = GPOINTER_TO_INT(iter->data); storage->store(storage, sdata, id, format, fdata, num, total, high_quality, upscale); } // cleanup time if(storage->finalize_store) storage->finalize_store(storage, sdata); storage->free_params(storage, sdata); format->free_params(format, fdata); g_list_free(id_list); dt_cleanup(); free(m_arg); }