static gboolean star_key_accel_callback(GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer data) { long int num = (long int)data; switch (num) { case DT_VIEW_REJECT: case DT_VIEW_DESERT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: case 666: { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id <= 0) { 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 dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, sqlite3_column_int(stmt, 0)); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if(num == 666 || num == DT_VIEW_DESERT) image->flags &= ~0xf; else if(num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); } sqlite3_finalize(stmt); } else { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if(num == 666 || num == DT_VIEW_DESERT) image->flags &= ~0xf; else if(num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); } dt_control_queue_redraw_center(); break; } default: break; } return TRUE; }
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; }
static void deflicker_prepare_histogram(dt_iop_module_t *self, uint32_t **histogram, dt_dev_histogram_stats_t *histogram_stats) { dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, self->dev->image_storage.id, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, self->dev->image_storage.id); dt_image_t image = *img; dt_image_cache_read_release(darktable.image_cache, img); if(buf.size != DT_MIPMAP_FULL) { dt_control_log(_("failed to get raw buffer from image `%s'"), image.filename); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); return; } dt_dev_histogram_collection_params_t histogram_params; memcpy(&histogram_params, &self->histogram_params, sizeof(dt_dev_histogram_collection_params_t)); dt_iop_roi_t roi = {0, 0, image.width, image.height, 1.0f}; histogram_params.roi = &roi; dt_histogram_worker(&histogram_params, histogram_stats, buf.buf, histogram, dt_histogram_helper_cs_RAW_uint16); histogram_stats->ch = 1u; dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); }
static void _jump_to() { int32_t imgid = dt_control_get_mouse_over_id(); if(imgid == -1) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) imgid = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } if(imgid != -1) { char path[512]; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_film_roll_directory(img, path, sizeof(path)); dt_image_cache_read_release(darktable.image_cache, img); char collect[1024]; snprintf(collect, sizeof(collect), "1:0:0:%s$", path); dt_collection_deserialize(collect); } }
static void drag_and_drop_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint time, gpointer data) { dt_view_t *self = (dt_view_t*)data; dt_map_t *lib = (dt_map_t*)self->data; gboolean success = FALSE; if((selection_data != NULL) && (selection_data->length >= 0) && target_type == DND_TARGET_IMGID) { float longitude, latitude; int *imgid = (int*)selection_data->data; if(imgid > 0) { OsmGpsMapPoint *pt = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(lib->map, x, y, pt); osm_gps_map_point_get_degrees(pt, &latitude, &longitude); osm_gps_map_point_free(pt); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, *imgid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); img->longitude = longitude; img->latitude = latitude; dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); success = TRUE; } } gtk_drag_finish(context, success, FALSE, time); }
static gboolean _lib_filmstrip_ratings_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { int num = GPOINTER_TO_INT(data); switch (num) { case DT_VIEW_DESERT: case DT_VIEW_REJECT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: case 666: { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if (mouse_over_id <= 0) return FALSE; /* get image from cache */ int32_t activated_image = -1; activated_image = darktable.view_manager->proxy.filmstrip.activated_image(darktable.view_manager->proxy.filmstrip.module); int offset = 0; if(mouse_over_id == activated_image) offset = dt_collection_image_offset(mouse_over_id); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if (num == 666) image->flags &= ~0xf; else if (num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else if(num == DT_VIEW_REJECT && ((image->flags & 0x7) == 6)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); dt_collection_hint_message(darktable.collection); // More than this, we need to redraw all if(mouse_over_id == activated_image) if(_lib_filmstrip_imgid_in_collection(darktable.collection, mouse_over_id) == 0) dt_view_filmstrip_scroll_relative(0, offset); /* redraw all */ dt_control_queue_redraw(); break; } default: break; } return TRUE; }
void dt_dev_reload_image(dt_develop_t *dev, const uint32_t imgid) { const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, imgid); dev->image_storage = *image; dt_image_cache_read_release(darktable.image_cache, image); dev->image_force_reload = dev->image_loading = dev->preview_loading = 1; dev->pipe->changed |= DT_DEV_PIPE_SYNCH; dt_dev_invalidate(dev); // only invalidate image, preview will follow once it's loaded. }
void dt_image_add_time_offset(const int imgid, const long int offset) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); if (!cimg) return; // get the datetime_taken and calculate the new time gint year; gint month; gint day; gint hour; gint minute; gint seconds; if (sscanf(cimg->exif_datetime_taken, "%d:%d:%d %d:%d:%d", (int*)&year, (int*)&month, (int*)&day, (int*)&hour,(int*)&minute,(int*)&seconds) != 6) { fprintf(stderr,"broken exif time in db, '%s', imgid %d\n", cimg->exif_datetime_taken, imgid); dt_image_cache_read_release(darktable.image_cache, cimg); return; } GTimeZone *tz = g_time_zone_new_utc(); GDateTime *datetime_original = g_date_time_new(tz, year, month, day, hour, minute, seconds); g_time_zone_unref(tz); if(!datetime_original) { dt_image_cache_read_release(darktable.image_cache, cimg); return; } // let's add our offset GDateTime *datetime_new = g_date_time_add_seconds(datetime_original, offset); g_date_time_unref(datetime_original); if(!datetime_new) { dt_image_cache_read_release(darktable.image_cache, cimg); return; } gchar *datetime = g_date_time_format(datetime_new, "%Y:%m:%d %H:%M:%S"); g_date_time_unref(datetime_new); // update exif_datetime_taken in img if(datetime) { dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); g_strlcpy(img->exif_datetime_taken, datetime, 20); dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE); } dt_image_cache_read_release(darktable.image_cache, cimg); g_free(datetime); }
void dt_image_remove(const int32_t imgid) { sqlite3_stmt *stmt; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); int old_group_id = img->group_id; dt_image_cache_read_release(darktable.image_cache, img); // make sure we remove from the cache first, or else the cache will look for imgid in sql dt_image_cache_remove(darktable.image_cache, imgid); int new_group_id = dt_grouping_remove_from_group(imgid); if(darktable.gui && darktable.gui->expanded_group_id == old_group_id) darktable.gui->expanded_group_id = new_group_id; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from images where id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update tagxtag set count = count - 1 where " "(id2 in (select tagid from tagged_images where imgid = ?1)) or " "(id1 in (select tagid from tagged_images where imgid = ?1))", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from tagged_images where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from color_labels where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from meta_data where id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from selected_images where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step(stmt); sqlite3_finalize(stmt); // also clear all thumbnails in mipmap_cache. dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); }
static void remove_preset_flag(const int imgid) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); // clear flag image->flags &= ~DT_IMAGE_AUTO_PRESETS_APPLIED; // write through to sql+xmp dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); }
void dt_ratings_apply_to_image (int imgid, int rating) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); // one star is a toggle, so you can easily reject images by removing the last star: if(((image->flags & 0x7) == 1) && (rating == 1)) rating = 0; image->flags = (image->flags & ~0x7) | (0x7 & rating); // synch through: dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); dt_collection_hint_message(darktable.collection); }
static void _view_map_filmstrip_activate_callback(gpointer instance, gpointer user_data) { double longitude, latitude; int32_t imgid = 0; if ((imgid=dt_view_filmstrip_get_activated_imgid(darktable.view_manager))>0) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); longitude = cimg->longitude; latitude = cimg->latitude; dt_image_cache_read_release(darktable.image_cache, cimg); if(!isnan(longitude) && !isnan(latitude)) _view_map_center_on_location((dt_view_t*)user_data, longitude, latitude, 16); // TODO: is it better to keep the zoom level? } }
void finalize_store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *params) { dt_imageio_email_t *d = (dt_imageio_email_t *)params; // All images are exported, generate a mailto uri and startup default mail client gchar uri[4096]= {0}; gchar body[4096]= {0}; gchar attachments[4096]= {0}; gchar *uriFormat=NULL; gchar *subject=_("images exported from darktable"); gchar *imageBodyFormat="%s %s"; // filename, exif oneliner gchar *attachmentFormat=NULL; gchar *attachmentSeparator=""; // If no default handler detected above, we use gtk_show_uri with mailto:// and hopes things goes right.. uriFormat="xdg-email --subject \"%s\" --body \"%s\" %s &"; // subject, body, and list of attachments with format: attachmentFormat=" --attach \"%s\""; while( d->images ) { gchar exif[256]= {0}; _email_attachment_t *attachment=( _email_attachment_t *)d->images->data; gchar *filename = g_path_get_basename( attachment->file ); const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, attachment->imgid); dt_image_print_exif(img, exif, sizeof(exif)); g_snprintf(body+strlen(body),4096-strlen(body), imageBodyFormat, filename, exif ); g_free(filename); if( strlen( attachments ) ) g_snprintf(attachments+strlen(attachments),4096-strlen(attachments), "%s", attachmentSeparator ); g_snprintf(attachments+strlen(attachments),4096-strlen(attachments), attachmentFormat, attachment->file ); // Free attachment item and remove dt_image_cache_read_release(darktable.image_cache, img); g_free( d->images->data ); d->images = g_list_remove( d->images, d->images->data ); } // build uri and launch before we quit... g_snprintf(uri, sizeof(uri), uriFormat, subject, body, attachments ); fprintf(stderr, "[email] launching `%s'\n", uri); if(system( uri ) < 0) { // TODO: after string freeze is broken again, report to ui: // dt_control_log(_("could not launch email client!")); fprintf(stderr, "[email] could not launch subprocess!\n"); } }
static gboolean _lib_filmstrip_button_press_callback(GtkWidget *w, GdkEventButton *e, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; int32_t mouse_over_id = strip->mouse_over_id; /* is this an activation of image */ if (e->button == 1 && e->type == GDK_2BUTTON_PRESS) if (mouse_over_id > 0) { strip->activated_image = mouse_over_id; dt_control_signal_raise(darktable.signals, DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE); return TRUE; } /* let check if any thumb controls was clicked */ switch(strip->image_over) { case DT_VIEW_DESERT: break; case DT_VIEW_REJECT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); image->dirty = 1; if(strip->image_over == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else if(strip->image_over == DT_VIEW_REJECT && ((image->flags & 0x7) == 6)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= strip->image_over; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); break; } default: return FALSE; } return TRUE; }
void dt_image_set_location(const int32_t imgid, double lon, double lat) { /* fetch image from cache */ const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); if (!cimg) return; dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); /* set image location */ image->longitude = lon; image->latitude = lat; /* store */ dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); }
void dt_dev_load_image(dt_develop_t *dev, const uint32_t imgid) { const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, imgid); dev->image_storage = *image; dt_image_cache_read_release(darktable.image_cache, image); if(dev->pipe) { dev->pipe->processed_width = 0; dev->pipe->processed_height = 0; } dev->image_loading = 1; dev->preview_loading = 1; dev->image_dirty = dev->preview_dirty = 1; dev->iop = dt_iop_load_modules(dev); dt_dev_read_history(dev); }
int group_with(lua_State *L) { dt_lua_image_t first_image; luaA_to(L,dt_lua_image_t,&first_image,1); if(lua_isnoneornil(L,2)) { dt_grouping_remove_from_group(first_image); return 0; } dt_lua_image_t second_image; luaA_to(L,dt_lua_image_t,&second_image,2); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, second_image); int group_id = cimg->group_id; dt_image_cache_read_release(darktable.image_cache, cimg); dt_grouping_add_to_group(group_id,first_image); return 0; }
int try_enter(dt_view_t *self) { int selected; DT_CTL_GET_GLOBAL(selected, lib_image_mouse_over_id); if(selected < 0) { // try last selected sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select * from selected_images", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) selected = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); // Leave as selected only the image being edited DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert or ignore into selected_images values (?1)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, selected); sqlite3_step(stmt); sqlite3_finalize(stmt); } if(selected < 0) { // fail :( dt_control_log(_("no image selected!")); return 1; } // this loads the image from db if needed: const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, selected); // get image and check if it has been deleted from disk first! char imgfilename[DT_MAX_PATH_LEN]; dt_image_full_path(img->id, imgfilename, DT_MAX_PATH_LEN); if(!g_file_test(imgfilename, G_FILE_TEST_IS_REGULAR)) { dt_control_log(_("image `%s' is currently unavailable"), img->filename); // dt_image_remove(selected); dt_image_cache_read_release(darktable.image_cache, img); return 1; } // and drop the lock again. dt_image_cache_read_release(darktable.image_cache, img); darktable.develop->image_storage.id = selected; return 0; }
int32_t dt_control_write_sidecar_files_job_run(dt_job_t *job) { long int imgid = -1; dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param; GList *t = t1->index; while(t) { imgid = (long int)t->data; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, (int32_t)imgid); char dtfilename[DT_MAX_PATH_LEN+4]; dt_image_full_path(img->id, dtfilename, DT_MAX_PATH_LEN); char *c = dtfilename + strlen(dtfilename); sprintf(c, ".xmp"); dt_exif_xmp_write(imgid, dtfilename); dt_image_cache_read_release(darktable.image_cache, img); t = g_list_delete_link(t, t); } return 0; }
static gboolean _lib_filmstrip_ratings_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { long int num = (long int)data; switch (num) { case DT_VIEW_DESERT: case DT_VIEW_REJECT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: case 666: { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if (mouse_over_id <= 0) return FALSE; /* get image from cache */ const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if (num == 666) image->flags &= ~0xf; else if (num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); /* redraw all */ dt_control_queue_redraw(); break; } default: break; } return TRUE; }
int get_group(lua_State *L) { dt_lua_image_t first_image; luaA_to(L,dt_lua_image_t,&first_image,1); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, first_image); int group_id = cimg->group_id; dt_image_cache_read_release(darktable.image_cache, cimg); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where group_id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, group_id); lua_newtable(L); while(sqlite3_step(stmt) == SQLITE_ROW) { int imgid = sqlite3_column_int(stmt, 0); luaA_push(L,dt_lua_image_t,&imgid); luaL_ref(L,-2); } luaA_push(L,dt_lua_image_t,&group_id); lua_setfield(L,-2,"leader"); return 1; }
static void _view_map_filmstrip_activate_callback(gpointer instance, gpointer user_data) { dt_view_t *self = (dt_view_t*)user_data; dt_map_t *lib = (dt_map_t*)self->data; double longitude, latitude; int32_t imgid = 0; if ((imgid=dt_view_filmstrip_get_activated_imgid(darktable.view_manager))>0) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); longitude = cimg->longitude; latitude = cimg->latitude; dt_image_cache_read_release(darktable.image_cache, cimg); if(!isnan(longitude) && !isnan(latitude)) { int zoom; g_object_get(G_OBJECT(lib->map), "zoom", &zoom, NULL); _view_map_center_on_location(self, longitude, latitude, zoom); // TODO: is it better to keep the zoom level or to zoom in? 16 is a nice close up. } } }
int dt_history_load_and_apply(int imgid, gchar *filename, int history_only) { int res = 0; const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); 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_image_cache_read_release(darktable.image_cache, img); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); } return res; }
void dt_ratings_apply_to_selection (int rating) { uint32_t count = dt_collection_get_selected_count(darktable.collection); if (count) { dt_control_log(ngettext("applying rating %d to %d image", "applying rating %d to %d images", count), rating, count); #if 0 // not updating cache gchar query[1024]={0}; g_snprintf(query,1024, "update images set flags=(images.flags & ~7) | (7 & %d) where id in (select imgid from selected_images)", rating ); DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), query, NULL, NULL, NULL); #endif /* for each selected image update rating */ 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 dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, sqlite3_column_int(stmt, 0)); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); image->flags = (image->flags & ~0x7) | (0x7 & rating); // synch through: dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); } sqlite3_finalize(stmt); /* redraw view */ dt_control_queue_redraw_center(); } else dt_control_log(_("no images selected to apply rating")); }
static const dt_image_t*checkreadimage(lua_State*L,int index) { dt_lua_image_t imgid; luaA_to(L,dt_lua_image_t,&imgid,index); return dt_image_cache_read_get(darktable.image_cache,imgid); }
int32_t dt_image_move(const int32_t imgid, const int32_t filmid) { //TODO: several places where string truncation could occur unnoticed int32_t result = -1; gchar oldimg[DT_MAX_PATH_LEN] = {0}; gchar newimg[DT_MAX_PATH_LEN] = {0}; dt_image_full_path(imgid, oldimg, DT_MAX_PATH_LEN); gchar *newdir = NULL; sqlite3_stmt *film_stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select folder from film_rolls where id = ?1", -1, &film_stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(film_stmt, 1, filmid); if(sqlite3_step(film_stmt) == SQLITE_ROW) newdir = g_strdup((gchar *) sqlite3_column_text(film_stmt, 0)); sqlite3_finalize(film_stmt); if(newdir) { gchar *imgbname = g_path_get_basename(oldimg); g_snprintf(newimg, DT_MAX_PATH_LEN, "%s%c%s", newdir, G_DIR_SEPARATOR, imgbname); g_free(imgbname); g_free(newdir); // statement for getting ids of the image to be moved and it's duplicates sqlite3_stmt *duplicates_stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select id from images where filename in (select filename from images " "where id = ?1) and film_id in (select film_id from images where id = ?1)", -1, &duplicates_stmt, NULL); // move image // TODO: Use gio's' g_file_move instead of g_rename? if (!g_file_test(newimg, G_FILE_TEST_EXISTS) && (g_rename(oldimg, newimg) == 0)) { // first move xmp files of image and duplicates GList *dup_list = NULL; DT_DEBUG_SQLITE3_BIND_INT(duplicates_stmt, 1, imgid); while (sqlite3_step(duplicates_stmt) == SQLITE_ROW) { int32_t id = sqlite3_column_int(duplicates_stmt, 0); dup_list = g_list_append(dup_list, GINT_TO_POINTER(id)); gchar oldxmp[512], newxmp[512]; g_strlcpy(oldxmp, oldimg, 512); g_strlcpy(newxmp, newimg, 512); dt_image_path_append_version(id, oldxmp, 512); dt_image_path_append_version(id, newxmp, 512); g_strlcat(oldxmp, ".xmp", 512); g_strlcat(newxmp, ".xmp", 512); if (g_file_test(oldxmp, G_FILE_TEST_EXISTS)) (void)g_rename(oldxmp, newxmp); } sqlite3_reset(duplicates_stmt); sqlite3_clear_bindings(duplicates_stmt); // then update database and cache // if update was performed in above loop, dt_image_path_append_version() // would return wrong version! while (dup_list) { long int id = GPOINTER_TO_INT(dup_list->data); 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->film_id = filmid; // 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); dup_list = g_list_delete_link(dup_list, dup_list); } g_list_free(dup_list); result = 0; } } return result; }
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; }
int32_t dt_image_duplicate(const int32_t imgid) { sqlite3_stmt *stmt; 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, 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 = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 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 = b.film_id and a.filename = b.filename and " "b.id = ?1 order by a.id desc", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); int32_t newid = -1; 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); if(darktable.gui && darktable.gui->grouping) { const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, newid); darktable.gui->expanded_group_id = img->group_id; dt_image_cache_read_release(darktable.image_cache, img); dt_collection_update_query(darktable.collection); } } return newid; }
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 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; }