void dt_image_set_flip(const int32_t imgid, const int32_t orientation) { sqlite3_stmt *stmt; // push new orientation to sql via additional history entry: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select MAX(num) from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); int num = 0; if(sqlite3_step(stmt) == SQLITE_ROW) { num = 1 + sqlite3_column_int(stmt, 0); } sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into history (imgid, num, module, operation, op_params, enabled, " "blendop_params, blendop_version) values" " (?1, ?2, 1, 'flip', ?3, 1, null, 0) ", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, num); DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 3, &orientation, sizeof(int32_t), SQLITE_TRANSIENT); sqlite3_step (stmt); sqlite3_finalize(stmt); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); // write that through to xmp: dt_image_write_sidecar_file(imgid); }
void dt_image_synch_xmp(const int selected) { if(selected > 0) { dt_image_write_sidecar_file(selected); } else if(dt_conf_get_bool("write_sidecar_files")) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images", -1, &stmt, NULL); while(sqlite3_step(stmt) == SQLITE_ROW) { const int imgid = sqlite3_column_int(stmt, 0); dt_image_write_sidecar_file(imgid); } sqlite3_finalize(stmt); } }
// drops the write privileges on an image struct. // this triggers a write-through to sql, and if the setting // is present, also to xmp sidecar files (safe setting). void dt_image_cache_write_release(dt_image_cache_t *cache, dt_image_t *img, dt_image_cache_write_mode_t mode) { if(img->id <= 0) return; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2( dt_database_get(darktable.db), "UPDATE main.images SET width = ?1, height = ?2, maker = ?3, model = ?4, " "lens = ?5, exposure = ?6, aperture = ?7, iso = ?8, focal_length = ?9, " "focus_distance = ?10, film_id = ?11, datetime_taken = ?12, flags = ?13, " "crop = ?14, orientation = ?15, raw_parameters = ?16, group_id = ?17, longitude = ?18, " "latitude = ?19, altitude = ?20, color_matrix = ?21, colorspace = ?22, raw_black = ?23, " "raw_maximum = ?24 WHERE id = ?25", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, img->width); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, img->height); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, img->exif_maker, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, img->exif_model, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, img->exif_lens, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, img->exif_exposure); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, img->exif_aperture); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, img->exif_iso); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, img->exif_focal_length); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, img->exif_focus_distance); DT_DEBUG_SQLITE3_BIND_INT(stmt, 11, img->film_id); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 12, img->exif_datetime_taken, -1, SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_INT(stmt, 13, img->flags); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 14, img->exif_crop); DT_DEBUG_SQLITE3_BIND_INT(stmt, 15, img->orientation); DT_DEBUG_SQLITE3_BIND_INT(stmt, 16, *(uint32_t *)(&img->legacy_flip)); DT_DEBUG_SQLITE3_BIND_INT(stmt, 17, img->group_id); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 18, img->longitude); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 19, img->latitude); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 20, img->elevation); DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 21, &img->d65_color_matrix, sizeof(img->d65_color_matrix), SQLITE_STATIC); DT_DEBUG_SQLITE3_BIND_INT(stmt, 22, img->colorspace); DT_DEBUG_SQLITE3_BIND_INT(stmt, 23, img->raw_black_level); DT_DEBUG_SQLITE3_BIND_INT(stmt, 24, img->raw_white_point); DT_DEBUG_SQLITE3_BIND_INT(stmt, 25, img->id); int rc = sqlite3_step(stmt); if(rc != SQLITE_DONE) fprintf(stderr, "[image_cache_write_release] sqlite3 error %d\n", rc); sqlite3_finalize(stmt); // TODO: make this work in relaxed mode, too. if(mode == DT_IMAGE_CACHE_SAFE) { // rest about sidecars: // also synch dttags file: dt_image_write_sidecar_file(img->id); } dt_cache_release(&cache->cache, img->cache_entry); }
void dt_image_synch_all_xmp(const gchar *pathname) { if(dt_conf_get_bool("write_sidecar_files")) { // Delete all existing .xmp files. glob_t *globbuf = g_malloc(sizeof(glob_t)); gchar *fname = g_strdup(pathname); gchar pattern[1024]; g_snprintf(pattern, 1024, "%s", pathname); char *c1 = pattern + strlen(pattern); while(*c1 != '.' && c1 > pattern) c1--; g_snprintf(c1, pattern + 1024 - c1, "_*"); char *c2 = fname + strlen(fname); while(*c2 != '.' && c2 > fname) c2--; g_snprintf(c1+2, pattern + 1024 - c1 - 2, "%s.xmp", c2); if (!glob(pattern, 0, NULL, globbuf)) { for (int i=0; i < globbuf->gl_pathc; i++) { (void)g_unlink(globbuf->gl_pathv[i]); } globfree(globbuf); } sqlite3_stmt *stmt; gchar *imgfname = g_path_get_basename(pathname); gchar *imgpath = g_path_get_dirname(pathname); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where film_id in (select id from film_rolls " "where folder = ?1) and filename = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, imgpath, strlen(imgpath), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, imgfname, strlen(imgfname), SQLITE_TRANSIENT); while(sqlite3_step(stmt) == SQLITE_ROW) { const int imgid = sqlite3_column_int(stmt, 0); dt_image_write_sidecar_file(imgid); } sqlite3_finalize(stmt); g_free(fname); g_free(imgfname); g_free(imgpath); g_free(globbuf); } }
// overwrite xmp files of the selected images void _overwrite_button_clicked(GtkButton *button, gpointer user_data) { dt_control_crawler_gui_t *gui = (dt_control_crawler_gui_t *)user_data; GtkTreeIter iter; gboolean valid = gtk_tree_model_get_iter_first(gui->model, &iter); while(valid) { gboolean selected; int id; gtk_tree_model_get(gui->model, &iter, DT_CONTROL_CRAWLER_COL_SELECTED, &selected, DT_CONTROL_CRAWLER_COL_ID, &id, -1); if(selected) { dt_image_write_sidecar_file(id); valid = gtk_list_store_remove(GTK_LIST_STORE(gui->model), &iter); } else valid = gtk_tree_model_iter_next(gui->model, &iter); } // we also want to disable the "select all" thing _clear_select_all(gui); }
int32_t dt_image_copy(const int32_t imgid, const int32_t filmid) { int32_t newid = -1; sqlite3_stmt *stmt; gchar srcpath[DT_MAX_PATH_LEN] = {0}; gchar *newdir = NULL; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select folder from film_rolls where id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filmid); if(sqlite3_step(stmt) == SQLITE_ROW) newdir = g_strdup((gchar *) sqlite3_column_text(stmt, 0)); sqlite3_finalize(stmt); if(newdir) { dt_image_full_path(imgid, srcpath, DT_MAX_PATH_LEN); gchar *imgbname = g_path_get_basename(srcpath); gchar *destpath = g_build_filename(newdir, imgbname, NULL); GFile *src = g_file_new_for_path(srcpath); GFile *dest = g_file_new_for_path(destpath); g_free(imgbname); imgbname = NULL; g_free(newdir); newdir = NULL; g_free(destpath); destpath = NULL; // copy image to new folder // if image file already exists, continue GError *gerror = NULL; g_file_copy(src, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &gerror); if((gerror == NULL) || (gerror != NULL && gerror->code == G_IO_ERROR_EXISTS)) { // update database DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into images " "(id, group_id, film_id, width, height, filename, maker, model, lens, exposure, " "aperture, iso, focal_length, focus_distance, datetime_taken, flags, " "output_width, output_height, crop, raw_parameters, raw_denoise_threshold, " "raw_auto_bright_threshold, raw_black, raw_maximum, orientation) " "select null, group_id, ?1 as film_id, width, height, filename, maker, model, lens, " "exposure, aperture, iso, focal_length, focus_distance, datetime_taken, " "flags, width, height, crop, raw_parameters, raw_denoise_threshold, " "raw_auto_bright_threshold, raw_black, raw_maximum, orientation " "from images where id = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filmid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select a.id from images as a join images as b where " "a.film_id = ?1 and a.filename = b.filename and " "b.id = ?2 order by a.id desc", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filmid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); if(sqlite3_step(stmt) == SQLITE_ROW) newid = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); if(newid != -1) { DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into color_labels (imgid, color) select ?1, color from " "color_labels where imgid = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into meta_data (id, key, value) select ?1, key, value " "from meta_data where id = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into tagged_images (imgid, tagid) select ?1, tagid from " "tagged_images where imgid = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update tagxtag set count = count + 1 where " "(id1 in (select tagid from tagged_images where imgid = ?1)) or " "(id2 in (select tagid from tagged_images where imgid = ?1))", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, newid); sqlite3_step(stmt); sqlite3_finalize(stmt); // write xmp file dt_image_write_sidecar_file(newid); } } else { fprintf(stderr, "Failed to copy image %s: %s\n", srcpath, gerror->message); } g_object_unref(dest); g_object_unref(src); g_clear_error(&gerror); } return newid; }