84 float exif_exposure_bias;
87 float exif_focal_length;
88 float exif_focus_distance;
93 GTimeSpan exif_datetime_taken;
96 int32_t crop_x, crop_y, crop_width, crop_height;
97 int32_t
flags, film_id, id, group_id, version;
99 float d65_color_matrix[9];
103 uint16_t raw_black_level;
104 uint32_t raw_white_point;
124 memcpy(persisted.exif_maker, img->
exif_maker,
sizeof(persisted.exif_maker));
125 memcpy(persisted.exif_model, img->
exif_model,
sizeof(persisted.exif_model));
126 memcpy(persisted.exif_lens, img->
exif_lens,
sizeof(persisted.exif_lens));
128 memcpy(persisted.filename, img->
filename,
sizeof(persisted.filename));
129 persisted.width = img->
width;
130 persisted.height = img->
height;
131 persisted.crop_x = img->
crop_x;
132 persisted.crop_y = img->
crop_y;
135 persisted.flags = img->
flags;
136 persisted.film_id = img->
film_id;
137 persisted.id = img->
id;
139 persisted.version = img->
version;
141 memcpy(persisted.d65_color_matrix, img->
d65_color_matrix,
sizeof(persisted.d65_color_matrix));
144 persisted.geoloc = img->
geoloc;
149 return dt_hash(5381, (
const char *)&persisted,
sizeof(persisted));
168 "INSERT INTO main.history_hash (imgid, current_hash, basic_hash, auto_hash, mipmap_hash)"
169 " VALUES (?1, ?2, NULL, NULL, ?3)"
170 " ON CONFLICT (imgid)"
171 " DO UPDATE SET current_hash = ?2, basic_hash = NULL, auto_hash = NULL, mipmap_hash = ?3",
177 sqlite3_clear_bindings(stmt);
192 "SELECT i.id, i.group_id, "
193 " (SELECT COUNT(id) FROM main.images WHERE group_id = i.group_id), "
194 " (SELECT COUNT(imgid) FROM main.history WHERE imgid = i.id), "
195 " COALESCE((SELECT current_hash FROM main.history_hash WHERE imgid = i.id), -1), "
196 " COALESCE((SELECT mipmap_hash FROM main.history_hash WHERE imgid = i.id), -1), "
197 " i.film_id, i.version, i.width, i.height, i.orientation, i.flags, "
198 " i.import_timestamp, i.change_timestamp, i.export_timestamp, i.print_timestamp, "
199 " i.exposure, i.exposure_bias, i.aperture, i.iso, i.focal_length, i.focus_distance, "
200 " i.datetime_taken, i.longitude, i.latitude, i.altitude, "
201 " i.filename, f.folder || '" G_DIR_SEPARATOR_S
"' || i.filename, "
202 " i.maker, i.model, i.lens, f.folder, "
203 " COALESCE((SELECT SUM(1 << color) FROM main.color_labels WHERE imgid=i.id), 0), "
204 " i.crop, i.raw_parameters, i.color_matrix, i.colorspace, "
205 " i.raw_black, i.raw_maximum, i.aspect_ratio, i.output_width, i.output_height"
206 " FROM main.images AS i"
207 " LEFT JOIN main.film_rolls AS f ON f.id = i.film_id"
220 if(sqlite3_column_type(stmt, 0) != SQLITE_NULL) img->
id = sqlite3_column_int(stmt, 0);
221 if(sqlite3_column_type(stmt, 1) != SQLITE_NULL) img->
group_id = sqlite3_column_int(stmt, 1);
222 if(sqlite3_column_type(stmt, 2) != SQLITE_NULL) img->
group_members = (uint32_t)sqlite3_column_int(stmt, 2);
223 if(sqlite3_column_type(stmt, 3) != SQLITE_NULL) img->
history_items = (uint32_t)sqlite3_column_int(stmt, 3);
224 if(sqlite3_column_type(stmt, 4) != SQLITE_NULL) img->
history_hash = sqlite3_column_int64(stmt, 4);
225 if(sqlite3_column_type(stmt, 5) != SQLITE_NULL) img->
mipmap_hash = sqlite3_column_int64(stmt, 5);
226 if(sqlite3_column_type(stmt, 6) != SQLITE_NULL) img->
film_id = sqlite3_column_int(stmt, 6);
227 if(sqlite3_column_type(stmt, 7) != SQLITE_NULL) img->
version = sqlite3_column_int(stmt, 7);
228 if(sqlite3_column_type(stmt, 8) != SQLITE_NULL) img->
width = sqlite3_column_int(stmt, 8);
229 if(sqlite3_column_type(stmt, 9) != SQLITE_NULL) img->
height = sqlite3_column_int(stmt, 9);
230 if(sqlite3_column_type(stmt, 10) != SQLITE_NULL) img->
orientation = sqlite3_column_int(stmt, 10);
231 if(sqlite3_column_type(stmt, 11) != SQLITE_NULL) img->
flags = sqlite3_column_int(stmt, 11);
232 if(sqlite3_column_type(stmt, 12) != SQLITE_NULL) img->
import_timestamp = sqlite3_column_int64(stmt, 12);
233 if(sqlite3_column_type(stmt, 13) != SQLITE_NULL) img->
change_timestamp = sqlite3_column_int64(stmt, 13);
234 if(sqlite3_column_type(stmt, 14) != SQLITE_NULL) img->
export_timestamp = sqlite3_column_int64(stmt, 14);
235 if(sqlite3_column_type(stmt, 15) != SQLITE_NULL) img->
print_timestamp = sqlite3_column_int64(stmt, 15);
236 if(sqlite3_column_type(stmt, 16) != SQLITE_NULL) img->
exif_exposure = sqlite3_column_double(stmt, 16);
237 if(sqlite3_column_type(stmt, 17) != SQLITE_NULL) img->
exif_exposure_bias = sqlite3_column_double(stmt, 17);
238 if(sqlite3_column_type(stmt, 18) != SQLITE_NULL) img->
exif_aperture = sqlite3_column_double(stmt, 18);
239 if(sqlite3_column_type(stmt, 19) != SQLITE_NULL) img->
exif_iso = sqlite3_column_double(stmt, 19);
240 if(sqlite3_column_type(stmt, 20) != SQLITE_NULL) img->
exif_focal_length = sqlite3_column_double(stmt, 20);
241 if(sqlite3_column_type(stmt, 21) != SQLITE_NULL) img->
exif_focus_distance = sqlite3_column_double(stmt, 21);
242 if(sqlite3_column_type(stmt, 22) != SQLITE_NULL) img->
exif_datetime_taken = sqlite3_column_int64(stmt, 22);
243 if(sqlite3_column_type(stmt, 23) != SQLITE_NULL) img->
geoloc.
longitude = sqlite3_column_double(stmt, 23);
244 if(sqlite3_column_type(stmt, 24) != SQLITE_NULL) img->
geoloc.
latitude = sqlite3_column_double(stmt, 24);
245 if(sqlite3_column_type(stmt, 25) != SQLITE_NULL) img->
geoloc.
elevation = sqlite3_column_double(stmt, 25);
247 const char *filename = (
const char *)sqlite3_column_text(stmt, 26);
249 const char *fullpath = (
const char *)sqlite3_column_text(stmt, 27);
251 const char *
maker = (
const char *)sqlite3_column_text(stmt, 28);
253 const char *
model = (
const char *)sqlite3_column_text(stmt, 29);
255 const char *lens = (
const char *)sqlite3_column_text(stmt, 30);
257 const char *folder = (
const char *)sqlite3_column_text(stmt, 31);
258 if(folder) g_strlcpy(img->
folder, folder,
sizeof(img->
folder));
260 if(sqlite3_column_type(stmt, 32) != SQLITE_NULL) img->
color_labels = sqlite3_column_int(stmt, 32);
262 if(sqlite3_column_type(stmt, 33) != SQLITE_NULL) img->
exif_crop = sqlite3_column_double(stmt, 33);
263 if(sqlite3_column_type(stmt, 34) != SQLITE_NULL)
265 uint32_t tmp = sqlite3_column_int(stmt, 34);
268 const void *color_matrix = sqlite3_column_blob(stmt, 35);
270 if(sqlite3_column_type(stmt, 36) != SQLITE_NULL) img->
colorspace = sqlite3_column_int(stmt, 36);
271 if(sqlite3_column_type(stmt, 37) != SQLITE_NULL) img->
raw_black_level = sqlite3_column_int(stmt, 37);
272 if(sqlite3_column_type(stmt, 38) != SQLITE_NULL) img->
raw_white_point = sqlite3_column_int(stmt, 38);
306 const gchar *ext = g_strrstr(img->
filename,
".");
313 "[image_cache] DB flag mismatch: id=%d filename='%s' has an HDR extension but stored "
314 "flags=0x%08x lack DT_IMAGE_HDR (ldr=%d hdr=%d)\n",
318 "[image_cache] DB flag mismatch: id=%d filename='%s' has a %s extension but stored "
319 "flags=0x%08x carry DT_IMAGE_HDR (ldr=%d hdr=%d)\n",
321 (
unsigned int)img->
flags, db_ldr, db_hdr);
334 sqlite3_clear_bindings(stmt);
336 if(sqlite3_step(stmt) == SQLITE_ROW)
355 fprintf(stderr,
"[image_cache_reload] failed to open image %" PRIu32
" from database: %s\n", imgid,
398 const uint32_t
size = 50;
399 const uint32_t max_mem =
size * 1024 * 1024;
400 const uint32_t num = (uint32_t)(1.5f * max_mem /
sizeof(
dt_image_t));
431 printf(
"[image cache] fill %.2f/%.2f MB (%.2f%%)\n", cache->
cache.
cost / (1024.0 * 1024.0),
438 if(current) *current = 0;
442 if(current) *current = cache->
cache.
cost;
456 while(g_hash_table_iter_next(&it, &
key, &
value))
465 g_array_append_val(
out, s);
473 if(imgid <= 0)
return NULL;
491 if(imgid <= 0)
return NULL;
505 if(imgid <= 0)
return NULL;
562 for(GList *l = g_list_first((GList *)imgs); l; l = g_list_next(l))
564 const int32_t imgid = GPOINTER_TO_INT(l->data);
565 if(imgid <= 0)
continue;
586 g_error(
"[image_cache] read lock modified image %d, you need to use a write lock\n", img->
id);
603 const gboolean changed = (self_hash != img->
self_hash);
614 g_error(
"[image_cache] minimal write release modified image %d, you need to commit those changes to DB.\n", img->
id);
625 g_strlcpy(folder, img->
folder,
sizeof(folder));
629 gchar *dir = g_path_get_dirname(img->
fullpath);
630 if(dir && dir[0] && strcmp(dir,
"."))
631 g_strlcpy(folder, dir,
sizeof(folder));
668 " SET width = ?1, height = ?2, filename = ?3, maker = ?4, model = ?5,"
669 " lens = ?6, exposure = ?7, aperture = ?8, iso = ?9, focal_length = ?10,"
670 " focus_distance = ?11, film_id = ?12, datetime_taken = ?13, flags = ?14,"
671 " crop = ?15, orientation = ?16, raw_parameters = ?17, group_id = ?18,"
672 " longitude = ?19, latitude = ?20, altitude = ?21, color_matrix = ?22,"
673 " colorspace = ?23, raw_black = ?24, raw_maximum = ?25,"
674 " aspect_ratio = ROUND(?26,1), exposure_bias = ?27,"
675 " import_timestamp = ?28, change_timestamp = ?29, export_timestamp = ?30,"
676 " print_timestamp = ?31, output_width = ?32, output_height = ?33"
720 const int rc = sqlite3_step(stmt);
721 if(rc != SQLITE_DONE) fprintf(stderr,
"[image_cache_write_release] sqlite3 error %d\n", rc);
722 sqlite3_finalize(stmt);
727 const int32_t imgid = img->
id;
735 imgs = g_list_prepend(imgs, GINT_TO_POINTER(img->
id));
748 if(imgid <= 0)
return;
757 if(imgid <= 0)
return;
void dt_colorlabels_set_labels(const int32_t imgid, const int colors)
const dt_colormatrix_t dt_aligned_pixel_t out
#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)
static const dt_aligned_pixel_simd_t value
#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)
void dt_image_cache_get_usage(dt_image_cache_t *cache, size_t *current, size_t *max)
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_reload_from_db(dt_image_t *img, const uint32_t imgid, const dt_sv_op_t sv_op)
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)
GArray * dt_image_cache_get_entries_stats(dt_image_cache_t *cache)
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)
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]
void dt_supervisor_image(const dt_sv_op_t op, const int32_t imgid, const dt_image_t *img)
static gboolean dt_supervisor_active(void)