81 float exif_exposure_bias;
84 float exif_focal_length;
85 float exif_focus_distance;
90 GTimeSpan exif_datetime_taken;
93 int32_t crop_x, crop_y, crop_width, crop_height;
94 int32_t
flags, film_id, id, group_id, version;
96 float d65_color_matrix[9];
100 uint16_t raw_black_level;
101 uint32_t raw_white_point;
121 memcpy(persisted.exif_maker, img->
exif_maker,
sizeof(persisted.exif_maker));
122 memcpy(persisted.exif_model, img->
exif_model,
sizeof(persisted.exif_model));
123 memcpy(persisted.exif_lens, img->
exif_lens,
sizeof(persisted.exif_lens));
125 memcpy(persisted.filename, img->
filename,
sizeof(persisted.filename));
126 persisted.width = img->
width;
127 persisted.height = img->
height;
128 persisted.crop_x = img->
crop_x;
129 persisted.crop_y = img->
crop_y;
132 persisted.flags = img->
flags;
133 persisted.film_id = img->
film_id;
134 persisted.id = img->
id;
136 persisted.version = img->
version;
138 memcpy(persisted.d65_color_matrix, img->
d65_color_matrix,
sizeof(persisted.d65_color_matrix));
141 persisted.geoloc = img->
geoloc;
146 return dt_hash(5381, (
const char *)&persisted,
sizeof(persisted));
165 "INSERT INTO main.history_hash (imgid, current_hash, basic_hash, auto_hash, mipmap_hash)"
166 " VALUES (?1, ?2, NULL, NULL, ?3)"
167 " ON CONFLICT (imgid)"
168 " DO UPDATE SET current_hash = ?2, basic_hash = NULL, auto_hash = NULL, mipmap_hash = ?3",
174 sqlite3_clear_bindings(stmt);
189 "SELECT i.id, i.group_id, "
190 " (SELECT COUNT(id) FROM main.images WHERE group_id = i.group_id), "
191 " (SELECT COUNT(imgid) FROM main.history WHERE imgid = i.id), "
192 " COALESCE((SELECT current_hash FROM main.history_hash WHERE imgid = i.id), -1), "
193 " COALESCE((SELECT mipmap_hash FROM main.history_hash WHERE imgid = i.id), -1), "
194 " i.film_id, i.version, i.width, i.height, i.orientation, i.flags, "
195 " i.import_timestamp, i.change_timestamp, i.export_timestamp, i.print_timestamp, "
196 " i.exposure, i.exposure_bias, i.aperture, i.iso, i.focal_length, i.focus_distance, "
197 " i.datetime_taken, i.longitude, i.latitude, i.altitude, "
198 " i.filename, f.folder || '" G_DIR_SEPARATOR_S
"' || i.filename, "
199 " i.maker, i.model, i.lens, f.folder, "
200 " COALESCE((SELECT SUM(1 << color) FROM main.color_labels WHERE imgid=i.id), 0), "
201 " i.crop, i.raw_parameters, i.color_matrix, i.colorspace, "
202 " i.raw_black, i.raw_maximum, i.aspect_ratio, i.output_width, i.output_height"
203 " FROM main.images AS i"
204 " LEFT JOIN main.film_rolls AS f ON f.id = i.film_id"
217 if(sqlite3_column_type(stmt, 0) != SQLITE_NULL) img->
id = sqlite3_column_int(stmt, 0);
218 if(sqlite3_column_type(stmt, 1) != SQLITE_NULL) img->
group_id = sqlite3_column_int(stmt, 1);
219 if(sqlite3_column_type(stmt, 2) != SQLITE_NULL) img->
group_members = (uint32_t)sqlite3_column_int(stmt, 2);
220 if(sqlite3_column_type(stmt, 3) != SQLITE_NULL) img->
history_items = (uint32_t)sqlite3_column_int(stmt, 3);
221 if(sqlite3_column_type(stmt, 4) != SQLITE_NULL) img->
history_hash = sqlite3_column_int64(stmt, 4);
222 if(sqlite3_column_type(stmt, 5) != SQLITE_NULL) img->
mipmap_hash = sqlite3_column_int64(stmt, 5);
223 if(sqlite3_column_type(stmt, 6) != SQLITE_NULL) img->
film_id = sqlite3_column_int(stmt, 6);
224 if(sqlite3_column_type(stmt, 7) != SQLITE_NULL) img->
version = sqlite3_column_int(stmt, 7);
225 if(sqlite3_column_type(stmt, 8) != SQLITE_NULL) img->
width = sqlite3_column_int(stmt, 8);
226 if(sqlite3_column_type(stmt, 9) != SQLITE_NULL) img->
height = sqlite3_column_int(stmt, 9);
227 if(sqlite3_column_type(stmt, 10) != SQLITE_NULL) img->
orientation = sqlite3_column_int(stmt, 10);
228 if(sqlite3_column_type(stmt, 11) != SQLITE_NULL) img->
flags = sqlite3_column_int(stmt, 11);
229 if(sqlite3_column_type(stmt, 12) != SQLITE_NULL) img->
import_timestamp = sqlite3_column_int64(stmt, 12);
230 if(sqlite3_column_type(stmt, 13) != SQLITE_NULL) img->
change_timestamp = sqlite3_column_int64(stmt, 13);
231 if(sqlite3_column_type(stmt, 14) != SQLITE_NULL) img->
export_timestamp = sqlite3_column_int64(stmt, 14);
232 if(sqlite3_column_type(stmt, 15) != SQLITE_NULL) img->
print_timestamp = sqlite3_column_int64(stmt, 15);
233 if(sqlite3_column_type(stmt, 16) != SQLITE_NULL) img->
exif_exposure = sqlite3_column_double(stmt, 16);
234 if(sqlite3_column_type(stmt, 17) != SQLITE_NULL) img->
exif_exposure_bias = sqlite3_column_double(stmt, 17);
235 if(sqlite3_column_type(stmt, 18) != SQLITE_NULL) img->
exif_aperture = sqlite3_column_double(stmt, 18);
236 if(sqlite3_column_type(stmt, 19) != SQLITE_NULL) img->
exif_iso = sqlite3_column_double(stmt, 19);
237 if(sqlite3_column_type(stmt, 20) != SQLITE_NULL) img->
exif_focal_length = sqlite3_column_double(stmt, 20);
238 if(sqlite3_column_type(stmt, 21) != SQLITE_NULL) img->
exif_focus_distance = sqlite3_column_double(stmt, 21);
239 if(sqlite3_column_type(stmt, 22) != SQLITE_NULL) img->
exif_datetime_taken = sqlite3_column_int64(stmt, 22);
240 if(sqlite3_column_type(stmt, 23) != SQLITE_NULL) img->
geoloc.
longitude = sqlite3_column_double(stmt, 23);
241 if(sqlite3_column_type(stmt, 24) != SQLITE_NULL) img->
geoloc.
latitude = sqlite3_column_double(stmt, 24);
242 if(sqlite3_column_type(stmt, 25) != SQLITE_NULL) img->
geoloc.
elevation = sqlite3_column_double(stmt, 25);
244 const char *filename = (
const char *)sqlite3_column_text(stmt, 26);
246 const char *fullpath = (
const char *)sqlite3_column_text(stmt, 27);
248 const char *
maker = (
const char *)sqlite3_column_text(stmt, 28);
250 const char *
model = (
const char *)sqlite3_column_text(stmt, 29);
252 const char *lens = (
const char *)sqlite3_column_text(stmt, 30);
254 const char *folder = (
const char *)sqlite3_column_text(stmt, 31);
255 if(folder) g_strlcpy(img->
folder, folder,
sizeof(img->
folder));
257 if(sqlite3_column_type(stmt, 32) != SQLITE_NULL) img->
color_labels = sqlite3_column_int(stmt, 32);
259 if(sqlite3_column_type(stmt, 33) != SQLITE_NULL) img->
exif_crop = sqlite3_column_double(stmt, 33);
260 if(sqlite3_column_type(stmt, 34) != SQLITE_NULL)
262 uint32_t tmp = sqlite3_column_int(stmt, 34);
265 const void *color_matrix = sqlite3_column_blob(stmt, 35);
267 if(sqlite3_column_type(stmt, 36) != SQLITE_NULL) img->
colorspace = sqlite3_column_int(stmt, 36);
268 if(sqlite3_column_type(stmt, 37) != SQLITE_NULL) img->
raw_black_level = sqlite3_column_int(stmt, 37);
269 if(sqlite3_column_type(stmt, 38) != SQLITE_NULL) img->
raw_white_point = sqlite3_column_int(stmt, 38);
303 const gchar *ext = g_strrstr(img->
filename,
".");
310 "[image_cache] DB flag mismatch: id=%d filename='%s' has an HDR extension but stored "
311 "flags=0x%08x lack DT_IMAGE_HDR (ldr=%d hdr=%d)\n",
315 "[image_cache] DB flag mismatch: id=%d filename='%s' has a %s extension but stored "
316 "flags=0x%08x carry DT_IMAGE_HDR (ldr=%d hdr=%d)\n",
318 (
unsigned int)img->
flags, db_ldr, db_hdr);
331 sqlite3_clear_bindings(stmt);
333 if(sqlite3_step(stmt) == SQLITE_ROW)
352 fprintf(stderr,
"[image_cache_reload] failed to open image %" PRIu32
" from database: %s\n", imgid,
388 const uint32_t
size = 50;
389 const uint32_t max_mem =
size * 1024 * 1024;
390 const uint32_t num = (uint32_t)(1.5f * max_mem /
sizeof(
dt_image_t));
421 printf(
"[image cache] fill %.2f/%.2f MB (%.2f%%)\n", cache->
cache.
cost / (1024.0 * 1024.0),
428 if(imgid <= 0)
return NULL;
446 if(imgid <= 0)
return NULL;
460 if(imgid <= 0)
return NULL;
517 for(GList *l = g_list_first((GList *)imgs); l; l = g_list_next(l))
519 const int32_t imgid = GPOINTER_TO_INT(l->data);
520 if(imgid <= 0)
continue;
541 g_error(
"[image_cache] read lock modified image %d, you need to use a write lock\n", img->
id);
555 if(img->
id <= 0)
return;
558 const gboolean changed = (self_hash != img->
self_hash);
569 g_error(
"[image_cache] minimal write release modified image %d, you need to commit those changes to DB.\n", img->
id);
580 g_strlcpy(folder, img->
folder,
sizeof(folder));
584 gchar *dir = g_path_get_dirname(img->
fullpath);
585 if(dir && dir[0] && strcmp(dir,
"."))
586 g_strlcpy(folder, dir,
sizeof(folder));
623 " SET width = ?1, height = ?2, filename = ?3, maker = ?4, model = ?5,"
624 " lens = ?6, exposure = ?7, aperture = ?8, iso = ?9, focal_length = ?10,"
625 " focus_distance = ?11, film_id = ?12, datetime_taken = ?13, flags = ?14,"
626 " crop = ?15, orientation = ?16, raw_parameters = ?17, group_id = ?18,"
627 " longitude = ?19, latitude = ?20, altitude = ?21, color_matrix = ?22,"
628 " colorspace = ?23, raw_black = ?24, raw_maximum = ?25,"
629 " aspect_ratio = ROUND(?26,1), exposure_bias = ?27,"
630 " import_timestamp = ?28, change_timestamp = ?29, export_timestamp = ?30,"
631 " print_timestamp = ?31, output_width = ?32, output_height = ?33"
675 const int rc = sqlite3_step(stmt);
676 if(rc != SQLITE_DONE) fprintf(stderr,
"[image_cache_write_release] sqlite3 error %d\n", rc);
677 sqlite3_finalize(stmt);
682 const int32_t imgid = img->
id;
690 imgs = g_list_prepend(imgs, GINT_TO_POINTER(img->
id));
703 if(imgid <= 0)
return;
712 if(imgid <= 0)
return;
void dt_colorlabels_set_labels(const int32_t imgid, const int colors)
#define dt_cache_release(A, B)
#define dt_cache_get(A, B, C)
static void dt_cache_set_cleanup_callback(dt_cache_t *cache, dt_cache_cleanup_t cleanup_cb, void *cleanup_data)
static void dt_cache_set_allocate_callback(dt_cache_t *cache, dt_cache_allocate_t allocate_cb, void *allocate_data)
void dt_image_refresh_makermodel(dt_image_t *img)
int dt_image_monochrome_flags(const dt_image_t *img)
gboolean dt_image_is_hdr(const dt_image_t *img)
void dt_image_init(dt_image_t *img)
const char * dt_image_film_roll_name(const char *path)
gboolean dt_image_use_monochrome_workflow(const dt_image_t *img)
int dt_image_get_xmp_rating_from_flags(const int flags)
gboolean dt_image_get_xmp_mode()
void dt_image_set_provisional_dsc(dt_image_t *img)
void dt_image_local_copy_paths_from_fullpath(const char *fullpath, int32_t imgid, char *local_copy_path, size_t local_copy_len, char *local_copy_legacy_path, size_t local_copy_legacy_len)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
void dt_control_save_xmp(const int32_t imgid)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
static void dt_free_gpointer(gpointer ptr)
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
#define DT_MAX_FILENAME_LEN
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
sqlite3 * dt_database_get(const dt_database_t *db)
gboolean dt_datetime_gtimespan_to_local(char *local, const size_t local_size, const GTimeSpan gts, const gboolean msec, const gboolean tz)
GTimeSpan dt_datetime_now_to_gtimespan()
#define DT_DEBUG_SQLITE3_BIND_BLOB(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_TEXT(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
#define DT_DEBUG_SQLITE3_BIND_INT64(a, b, c)
#define DT_DEBUG_SQLITE3_BIND_DOUBLE(a, b, c)
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
static dt_pthread_mutex_t _image_cache_stmt_mutex
void dt_image_cache_cleanup(dt_image_cache_t *cache)
void dt_image_cache_init(dt_image_cache_t *cache)
static sqlite3_stmt * _image_cache_write_history_hash_stmt
static uint64_t _image_cache_self_hash(const dt_image_t *img)
static void _image_cache_write_history_hash(const dt_image_t *img)
static gsize _image_cache_stmt_mutex_inited
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
dt_image_t * dt_image_cache_get_reload(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_cache_allocate(void *data, dt_cache_entry_t *entry)
static sqlite3_stmt * _image_cache_load_stmt
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
int dt_image_cache_seed(dt_image_cache_t *cache, const dt_image_t *img)
static void _image_cache_lock_init(dt_image_t *img)
static void _image_cache_info_changed_reload_callback(gpointer instance, gpointer imgs, gpointer user_data)
void dt_image_cache_set_export_timestamp(dt_image_cache_t *cache, const int32_t imgid)
int dt_image_invalid(const dt_image_t *img)
void dt_image_cache_write_release(dt_image_cache_t *cache, dt_image_t *img, dt_image_cache_write_mode_t mode)
void dt_image_cache_remove(dt_image_cache_t *cache, const int32_t imgid)
void dt_image_from_stmt(dt_image_t *img, sqlite3_stmt *stmt)
void dt_image_cache_deallocate(void *data, dt_cache_entry_t *entry)
void dt_image_cache_connect_info_changed_first(const struct dt_control_signal_t *ctlsig)
dt_image_t * dt_image_cache_testget(dt_image_cache_t *cache, const int32_t imgid, char mode)
static sqlite3_stmt * _image_cache_get_stmt(void)
static void _image_cache_reload_from_db(dt_image_t *img, const uint32_t imgid)
void dt_image_cache_set_print_timestamp(dt_image_cache_t *cache, const int32_t imgid)
static void _image_cache_stmt_mutex_ensure(void)
void dt_image_cache_print(dt_image_cache_t *cache)
dt_image_cache_write_mode_t
dt_image_flags_t dt_imageio_get_type_from_extension(const char *extension)
Map Exiv2 preview MIME types to decoder format identifiers.
dt_mipmap_buffer_dsc_flags flags
void dt_control_signal_connect(const dt_control_signal_t *ctlsig, dt_signal_t signal, GCallback cb, gpointer user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_IMAGE_INFO_CHANGED
This signal is raised when any of image info has changed
int dt_cache_seed(dt_cache_t *cache, const uint32_t key, const void *data, size_t data_size, size_t cost, gboolean aligned_alloc)
dt_cache_entry_t * dt_cache_testget(dt_cache_t *cache, const uint32_t key, char mode)
void dt_cache_init(dt_cache_t *cache, size_t entry_size, size_t cost_quota)
int dt_cache_remove(dt_cache_t *cache, const uint32_t key)
void dt_cache_cleanup(dt_cache_t *cache)
const float const int flip
unsigned __int64 uint64_t
const struct dt_database_t * db
struct dt_control_signal_t * signals
struct dt_image_cache_t * image_cache
GTimeSpan export_timestamp
float exif_focus_distance
GTimeSpan import_timestamp
dt_image_orientation_t orientation
GTimeSpan change_timestamp
char local_copy_path[PATH_MAX]
GTimeSpan print_timestamp
GTimeSpan exif_datetime_taken
float d65_color_matrix[9]
dt_image_colorspace_t colorspace
struct dt_cache_entry_t * cache_entry
dt_image_raw_parameters_t legacy_flip
char filename[DT_MAX_FILENAME_LEN]
char local_copy_legacy_path[PATH_MAX]