Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
image_cache.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2012, 2014 johannes hanika.
4 Copyright (C) 2010-2011 Henrik Andersson.
5 Copyright (C) 2010-2014, 2016 Tobias Ellinghaus.
6 Copyright (C) 2011 Robert Bieber.
7 Copyright (C) 2011 Rostyslav Pidgornyi.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2013 Simon Spannagel.
10 Copyright (C) 2013 Ulrich Pegelow.
11 Copyright (C) 2014-2015 Pedro Côrte-Real.
12 Copyright (C) 2014-2016 Roman Lebedev.
13 Copyright (C) 2018 Edgardo Hoszowski.
14 Copyright (C) 2019 Andreas Schneider.
15 Copyright (C) 2019 August Schwerdfeger.
16 Copyright (C) 2019 Bill Ferguson.
17 Copyright (C) 2019-2020 Hanno Schwalm.
18 Copyright (C) 2019-2022 Pascal Obry.
19 Copyright (C) 2020 Heiko Bauke.
20 Copyright (C) 2020 JP Verrue.
21 Copyright (C) 2020, 2022 Philippe Weyland.
22 Copyright (C) 2021 Aldric Renaudin.
23 Copyright (C) 2021 Vincent THOMAS.
24 Copyright (C) 2022 Martin Bařinka.
25 Copyright (C) 2022 paolodepetrillo.
26 Copyright (C) 2022 Philipp Lutz.
27 Copyright (C) 2025-2026 Aurélien PIERRE.
28 Copyright (C) 2026 Guillaume Stutin.
29
30 darktable is free software: you can redistribute it and/or modify
31 it under the terms of the GNU General Public License as published by
32 the Free Software Foundation, either version 3 of the License, or
33 (at your option) any later version.
34
35 darktable is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with darktable. If not, see <http://www.gnu.org/licenses/>.
42*/
43
45#include "caches/image_cache.h"
46#include "system/macros.h"
47#include "system/mem_alloc.h"
48#include "common/hash.h"
49#include "common/logging.h"
50#include "common/paths.h"
51#include "common/image.h"
52#include "common/datetime.h"
53#include "control/control.h"
54#include "control/signal.h"
55#include "develop/supervisor.h"
56
57#include <inttypes.h>
58#include "colorprofiles/colorspaces.h" // dt_colorspaces_free_image_profile
59
60/* Set once by dt_image_cache_init(); see the header for why it is not read live. */
61static gboolean _verbose = FALSE;
62
63/* Statement-safe: a bare `if(_verbose) dt_print(...)` swallows a following `else`. */
64#define _cache_print(channel, ...) \
65 do { \
66 if(_verbose) dt_print((channel), __VA_ARGS__); \
67 } while(0)
68
69
70/* PRIVATE. Nothing outside this file reads a field of it -- the header exposes the
71 * type as an opaque handle so that it cannot. */
72typedef struct dt_image_cache_t
73{
75}
77
78
79/* The cache instance, owned HERE. It used to be calloc'd by darktable.c and hung off the
80 * application struct, so the accessor lived in the orchestrator and the struct was reachable
81 * from anything that included darktable.h. */
83
85{
87}
88
89
90
92{
93 if(IS_NULL_PTR(img) || img->id <= 0) return 0;
94
95 struct
96 {
97 dt_image_orientation_t orientation;
98 float exif_exposure;
99 float exif_exposure_bias;
100 float exif_aperture;
101 float exif_iso;
102 float exif_focal_length;
103 float exif_focus_distance;
104 float exif_crop;
105 char exif_maker[64];
106 char exif_model[64];
107 char exif_lens[128];
108 GTimeSpan exif_datetime_taken;
109 char filename[DT_MAX_FILENAME_LEN];
110 int32_t width, height;
111 int32_t crop_x, crop_y, crop_width, crop_height;
112 int32_t flags, film_id, id, group_id, version;
113 uint64_t history_hash;
114 float d65_color_matrix[9];
115 dt_image_colorspace_t colorspace;
116 dt_image_raw_parameters_t legacy_flip;
117 dt_image_geoloc_t geoloc;
118 uint16_t raw_black_level;
119 uint32_t raw_white_point;
120 int color_labels;
121 } persisted = { 0 };
122
123 /*
124 * Track only the dt_image_t fields that are explicitly written back to the database
125 * from dt_image_cache_write_release(), plus the history hash and color labels that
126 * are flushed through their own SQL paths right below it. Runtime-only fields such
127 * as cached ICC pointers, DNG gain-map lists, loader state or derived path strings
128 * must stay out of this hash, otherwise merely opening an image can look like an
129 * edit and spuriously bump change_timestamp.
130 */
131 persisted.orientation = img->orientation;
132 persisted.exif_exposure = img->exif_exposure;
133 persisted.exif_exposure_bias = img->exif_exposure_bias;
134 persisted.exif_aperture = img->exif_aperture;
135 persisted.exif_iso = img->exif_iso;
136 persisted.exif_focal_length = img->exif_focal_length;
137 persisted.exif_focus_distance = img->exif_focus_distance;
138 persisted.exif_crop = img->exif_crop;
139 memcpy(persisted.exif_maker, img->exif_maker, sizeof(persisted.exif_maker));
140 memcpy(persisted.exif_model, img->exif_model, sizeof(persisted.exif_model));
141 memcpy(persisted.exif_lens, img->exif_lens, sizeof(persisted.exif_lens));
142 persisted.exif_datetime_taken = img->exif_datetime_taken;
143 memcpy(persisted.filename, img->filename, sizeof(persisted.filename));
144 persisted.width = img->width;
145 persisted.height = img->height;
146 persisted.crop_x = img->crop_x;
147 persisted.crop_y = img->crop_y;
148 persisted.crop_width = img->crop_width;
149 persisted.crop_height = img->crop_height;
150 persisted.flags = img->flags;
151 persisted.film_id = img->film_id;
152 persisted.id = img->id;
153 persisted.group_id = img->group_id;
154 persisted.version = img->version;
155 persisted.history_hash = img->history_hash;
156 memcpy(persisted.d65_color_matrix, img->d65_color_matrix, sizeof(persisted.d65_color_matrix));
157 persisted.colorspace = img->colorspace;
158 persisted.legacy_flip = img->legacy_flip;
159 persisted.geoloc = img->geoloc;
160 persisted.raw_black_level = img->raw_black_level;
161 persisted.raw_white_point = img->raw_white_point;
162 persisted.color_labels = img->color_labels;
163
164 return dt_hash(5381, (const char *)&persisted, sizeof(persisted));
165}
166
167static inline void _image_cache_lock_init(dt_image_t *img)
168{
170}
171
172
173
174
175/* Fields the database does not store because they are computed from the ones it does:
176 * the rating, the monochrome and HDR predicates, the extension cross-check, makermodel.
177 * They live here rather than in database/image_repository.c because they need
178 * imageio/ and views/ symbols, and a row mapper reaching two layers up for them is exactly
179 * what kept this code in common/. Every path that produces a dt_image_t from a database row
180 * calls this next -- the repository's own load, and gui/dtgtk/thumbtable.c's bulk query. */
182{
183 if(IS_NULL_PTR(img)) return;
185 img->has_audio = (img->flags & DT_IMAGE_HAS_WAV);
187 img->rating = (xmp_rating == -1) ? DT_VIEW_REJECT : xmp_rating;
190 img->is_hdr = dt_image_is_hdr(img);
191
192 // Instrumentation: the LDR/HDR flags are now pure flag predicates (no filename sniffing at read
193 // time). Historically the flag could have been mis-set at import, so cross-check the flags loaded
194 // from the DB against the unambiguous extension hint and log any contradiction. Containers whose
195 // dynamic range only the decoder can settle (TIFF/AVIF/HEIF/DNG ...) return 0 here and are skipped
196 // to avoid false positives. This surfaces stale/garbage flags persisted in the database.
197 {
198 const gchar *ext = g_strrstr(img->filename, ".");
200 const gboolean db_hdr = (img->flags & DT_IMAGE_HDR) != 0;
201 const gboolean db_ldr = (img->flags & DT_IMAGE_LDR) != 0;
202
203 if(ext_hint == DT_IMAGE_HDR && !db_hdr)
205 "[image_cache] DB flag mismatch: id=%d filename='%s' has an HDR extension but stored "
206 "flags=0x%08x lack DT_IMAGE_HDR (ldr=%d hdr=%d)\n",
207 img->id, img->filename, (unsigned int)img->flags, db_ldr, db_hdr);
208 else if((ext_hint == DT_IMAGE_LDR || ext_hint == DT_IMAGE_RAW) && db_hdr)
210 "[image_cache] DB flag mismatch: id=%d filename='%s' has a %s extension but stored "
211 "flags=0x%08x carry DT_IMAGE_HDR (ldr=%d hdr=%d)\n",
212 img->id, img->filename, (ext_hint == DT_IMAGE_RAW) ? "RAW" : "LDR",
213 (unsigned int)img->flags, db_ldr, db_hdr);
214 }
215
217}
218
219static void _image_cache_reload_from_db(dt_image_t *img, const uint32_t imgid, const dt_sv_op_t sv_op)
220{
221 dt_image_repository_load((int32_t)imgid, img);
223
224 // The image's dt_image_t was just (re)loaded from the database: `create` on
225 // first allocation, `update` on a reload (get_reload / IMAGE_INFO_CHANGED).
226 // Notifying is the cache's job, not the repository's -- the repository does not
227 // know what a supervisor is.
228 if(dt_supervisor_active()) dt_supervisor_image(sv_op, (int32_t)imgid, img);
229}
230
232{
233 entry->cost = sizeof(dt_image_t);
234
235 // dt_alloc_align: dt_image_t embeds dt_aligned_pixel_t members (alignof 64); see #1212.
237 entry->data = img;
238 dt_image_init(img);
239 _image_cache_reload_from_db(img, entry->key, DT_SV_CREATE); // emits the create event
240
241 img->cache_entry = entry; // init backref
242}
243
257
258void dt_image_cache_init(const gboolean verbose)
259{
260 _verbose = verbose;
261 if(_image_cache) return;
263 if(IS_NULL_PTR(_image_cache)) return;
265 // the image cache does no serialization.
266 // (unsafe. data should be in db/xmp, not in any other additional cache,
267 // also, it should be relatively fast to get the image_t structs from sql.)
268 // TODO: actually an independent conf var?
269 // too large: dangerous and wasteful?
270 // can we get away with a fixed size?
271 const uint32_t size = 50;
272 const uint32_t max_mem = size * 1024 * 1024;
273 const uint32_t num = (uint32_t)(1.5f * max_mem / sizeof(dt_image_t));
274 dt_cache_init(&cache->cache, sizeof(dt_image_t), max_mem);
277
278 _cache_print(DT_DEBUG_CACHE, "[image_cache] has %d entries (%u MiB)\n", num, size);
279}
280
282{
284 if(IS_NULL_PTR(cache)) return;
286
287 dt_cache_cleanup(&cache->cache);
288
291}
292
294{
295 const dt_image_cache_t *const cache = _image_cache;
296 printf("[image cache] fill %.2f/%.2f MB (%.2f%%)\n", cache->cache.cost / (1024.0 * 1024.0),
297 cache->cache.cost_quota / (1024.0 * 1024.0),
298 (float)cache->cache.cost / (float)cache->cache.cost_quota);
299}
300
301void dt_image_cache_get_usage(size_t *current, size_t *max)
302{
304 if(current) *current = 0;
305 if(max) *max = 0;
306 if(IS_NULL_PTR(cache)) return;
308 if(current) *current = cache->cache.cost;
309 if(max) *max = cache->cache.cost_quota;
311}
312
314{
317 if(IS_NULL_PTR(cache)) return out;
318
321 gpointer key, value;
324 {
325 const dt_cache_entry_t *ce = (const dt_cache_entry_t *)value;
326 if(IS_NULL_PTR(ce)) continue;
328 s.imgid = (int32_t)ce->key;
329 s.size = ce->cost ? ce->cost : ce->data_size;
330 const dt_image_t *img = (const dt_image_t *)ce->data;
331 if(img && img->filename[0]) g_strlcpy(s.filename, img->filename, sizeof(s.filename));
333 }
335 return out;
336}
337
338dt_image_t *dt_image_cache_get(const int32_t imgid, char mode)
339{
341 if(imgid <= 0) return NULL;
342 dt_cache_entry_t *entry = dt_cache_get(&cache->cache, (uint32_t)imgid, mode);
344 dt_image_t *img = (dt_image_t *)entry->data;
345 img->cache_entry = entry;
346
347 if(dt_image_invalid(img))
348 {
349 dt_cache_release(&cache->cache, entry);
350 return NULL;
351 }
352
354 return img;
355}
356
357dt_image_t *dt_image_cache_testget(const int32_t imgid, char mode)
358{
360 if(imgid <= 0) return NULL;
361 dt_cache_entry_t *entry = dt_cache_testget(&cache->cache, (uint32_t)imgid, mode);
362 if(IS_NULL_PTR(entry)) return 0;
364 dt_image_t *img = (dt_image_t *)entry->data;
365 img->cache_entry = entry;
366
367 /* Same contract as dt_image_cache_get() and dt_image_cache_get_reload(): an entry whose row
368 * has gone stays in the cache with id == UNKNOWN_IMAGE, and handing it out LOCKED is how the
369 * lock leaks -- the caller has no way to release what it was told was not an image. */
370 if(dt_image_invalid(img))
371 {
372 dt_cache_release(&cache->cache, entry);
373 return NULL;
374 }
375
377 return img;
378}
379
380dt_image_t *dt_image_cache_get_existing(const int32_t imgid, char mode)
381{
383 if(imgid <= 0) return NULL;
384
385 // contains() answers "is there an entry" without taking the entry's lock, which is the one
386 // question testget() conflates with "is it free right now"
387 if(!dt_cache_contains(&cache->cache, (uint32_t)imgid)) return NULL;
388 return dt_image_cache_get(imgid, mode);
389}
390
391// Always reload the cache entry from DB before returning it.
392// This is critical for IMAGE_INFO_CHANGED: other handlers will read from the cache.
393dt_image_t *dt_image_cache_get_reload(const int32_t imgid, char mode)
394{
396 if(imgid <= 0) return NULL;
397
398 // We must take a write lock to reload in-place, then demote to read if requested.
399 dt_cache_entry_t *entry = dt_cache_get(&cache->cache, (uint32_t)imgid, 'w');
401 dt_image_t *img = (dt_image_t *)entry->data;
402 _image_cache_reload_from_db(img, (uint32_t)imgid, DT_SV_UPDATE);
403
404 img->cache_entry = entry;
405
406 if(dt_image_invalid(img))
407 {
408 dt_cache_release(&cache->cache, entry);
409 return NULL;
410 }
411
412 if(mode == 'r')
413 {
414 // demote the lock to read mode (see mipmap cache for rationale)
415 entry->_lock_demoting = 1;
416 dt_cache_release(&cache->cache, entry);
417 entry = dt_cache_get(&cache->cache, (uint32_t)imgid, 'r');
418 entry->_lock_demoting = 0;
420 img = (dt_image_t *)entry->data;
421 img->cache_entry = entry;
422 }
423
425 return img;
426}
427
429{
430 return (IS_NULL_PTR(img) || img->id <= 0);
431}
432
434{
436 if(IS_NULL_PTR(cache) || dt_image_invalid(img)) return -1;
437
438 dt_image_t seeded = *img;
439
440 // Avoid ownership issues for pointers that the cache cleanup would free.
442 seeded.profile_size = 0;
443 seeded.dng_gain_maps = NULL;
444 seeded.cache_entry = NULL;
445
446 // dt_image_cache_deallocate() frees entry->data with dt_free_align(); dt_cache_seed()
447 // allocates with dt_alloc_align() and no longer offers any other option.
448 return dt_cache_seed(&cache->cache, (uint32_t)seeded.id, &seeded, sizeof(dt_image_t), sizeof(dt_image_t));
449}
450
451// This callback must run before any other DT_SIGNAL_IMAGE_INFO_CHANGED handler.
452// The signal notifies about DB changes, and most listeners read image info from the cache.
453// We therefore force a DB reload here so every subsequent handler sees up-to-date data.
454static void _image_cache_info_changed_reload_callback(gpointer instance, gpointer imgs, gpointer user_data)
455{
456 for(GList *l = g_list_first((GList *)imgs); l; l = g_list_next(l))
457 {
458 const int32_t imgid = GPOINTER_TO_INT(l->data);
459 if(imgid <= 0) continue;
460
461 dt_image_t *img = dt_image_cache_get_reload(imgid, 'r');
462 if(img)
464 }
465}
466
473
474// drops the read lock on an image struct
476{
478 if(IS_NULL_PTR(img)) return;
479
480 /* What is being returned is the LOCK, not the image, so an entry whose row has gone in the
481 * meantime is released like any other. The guard used to read `|| img->id <= 0` -- which is
482 * dt_image_invalid() spelled out -- and that silently skipped the release for exactly the
483 * entries most likely to have one outstanding, deadlocking the next writer for good. */
484 if(dt_image_invalid(img))
485 {
486 if(!IS_NULL_PTR(img->cache_entry)) dt_cache_release(&cache->cache, img->cache_entry);
487 return;
488 }
489
490 const uint64_t self_hash = _image_cache_self_hash(img);
491 if(self_hash != img->self_hash)
492 g_error("[image_cache] read lock modified image %d, you need to use a write lock\n", img->id);
493
494 // just force the dt_image_t struct to make sure it has been locked before.
495 dt_cache_release(&cache->cache, img->cache_entry);
496}
497
498// drops the write privileges on an image struct.
499// this triggers a write-through to sql, and optionally queues xmp sidecar writing.
501{
503 if(IS_NULL_PTR(img)) return;
504
505 // same as the read side: release the lock, write nothing back for a row that is gone
506 if(dt_image_invalid(img))
507 {
508 if(!IS_NULL_PTR(img->cache_entry)) dt_cache_release(&cache->cache, img->cache_entry);
509 return;
510 }
511
512 const uint64_t self_hash = _image_cache_self_hash(img);
513 const gboolean changed = (self_hash != img->self_hash);
514
515 if(changed)
517
518 // even if nothing changed, we might need to write export/print timestamps
519 // and mipmap hash, so we can't exit just yet.
520
521 if(mode == DT_IMAGE_CACHE_MINIMAL)
522 {
523 if(changed)
524 g_error("[image_cache] minimal write release modified image %d, you need to commit those changes to DB.\n", img->id);
525
526 dt_cache_release(&cache->cache, img->cache_entry);
527 return;
528 }
529
530 // Recompute full/local copy paths (and derived folder/filmroll/datetime) from possibly updated filename.
531 // Avoid SQL here; rely on the cached folder/fullpath, or leave fields empty if they can't be rebuilt.
532 char folder[DT_PATH_MAX] = { 0 };
533 if(img->folder[0])
534 {
535 g_strlcpy(folder, img->folder, sizeof(folder));
536 }
537 else if(img->fullpath[0])
538 {
539 gchar *dir = g_path_get_dirname(img->fullpath);
540 if(dir && dir[0] && strcmp(dir, "."))
541 g_strlcpy(folder, dir, sizeof(folder));
542 dt_free(dir);
543 }
544
545 if(img->filename[0] && folder[0])
546 {
547 g_snprintf(img->fullpath, sizeof(img->fullpath), "%s" G_DIR_SEPARATOR_S "%s", folder, img->filename);
548 g_strlcpy(img->folder, folder, sizeof(img->folder));
549 }
550 else
551 {
552 img->fullpath[0] = '\0';
553 img->folder[0] = '\0';
554 }
555 if(img->folder[0])
556 g_strlcpy(img->filmroll, dt_image_film_roll_name(img->folder), sizeof(img->filmroll));
557 else if(img->film_id < 0)
558 g_strlcpy(img->filmroll, _("orphaned image"), sizeof(img->filmroll));
559 else
560 img->filmroll[0] = '\0';
563 sizeof(img->local_copy_path), img->local_copy_legacy_path,
564 sizeof(img->local_copy_legacy_path));
565
567 img->has_audio = (img->flags & DT_IMAGE_HAS_WAV);
569 img->rating = (xmp_rating == -1) ? DT_VIEW_REJECT : xmp_rating;
572 img->is_hdr = dt_image_is_hdr(img);
573
575
576 const int32_t imgid = img->id;
577 dt_cache_release(&cache->cache, img->cache_entry);
578
580 dt_control_save_xmp(imgid);
581
582 // The signal owns the list. `img` may be evicted once released, hence the saved id.
583 GList *imgs = g_list_prepend(NULL, GINT_TO_POINTER(imgid));
585}
586
587
588// remove the image from the cache
589void dt_image_cache_remove(const int32_t imgid)
590{
592 dt_cache_remove(&cache->cache, imgid);
593}
594
595void dt_image_cache_set_export_timestamp(const int32_t imgid)
596{
597 if(imgid <= 0) return;
598 dt_image_t *img = dt_image_cache_get(imgid, 'w');
599 if(IS_NULL_PTR(img)) return;
602}
603
604void dt_image_cache_set_print_timestamp(const int32_t imgid)
605{
606 if(imgid <= 0) return;
607 dt_image_t *img = dt_image_cache_get(imgid, 'w');
608 if(IS_NULL_PTR(img)) return;
611}
612
613// clang-format off
614// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
615// vim: shiftwidth=2 expandtab tabstop=2 cindent
616// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
617// clang-format on
#define FALSE
Definition ashift_lsd.c:158
#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_colorspaces_free_image_profile(struct dt_colorspaces_color_profile_t *profile)
Release a profile container owned by an image, closing the LCMS2 handle inside it if and only if the ...
The colour-profile module's API: which profiles exist, and how to apply one.
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
dt_image_flags_t dt_image_flags_from_extension(const char *extension)
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_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_alloc_align(size_t size)
Allocate cacheline-aligned memory.
Definition darktable.c:508
gboolean dt_datetime_gtimespan_to_local(char *local, const size_t local_size, const GTimeSpan gts, const gboolean msec, const gboolean tz)
Definition datetime.c:178
GTimeSpan dt_datetime_now_to_gtimespan()
Definition datetime.c:237
GtkWidget * folder
destination folder chooser
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:127
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:117
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
Definition hash.h:55
dt_image_colorspace_t
Definition image.h:191
dt_image_orientation_t
Definition image.h:216
dt_image_flags_t
Definition image.h:104
@ DT_IMAGE_HAS_WAV
Definition image.h:138
@ DT_IMAGE_LOCAL_COPY
Definition image.h:134
@ DT_IMAGE_RAW
Definition image.h:124
@ DT_IMAGE_HDR
Definition image.h:126
@ DT_IMAGE_LDR
Definition image.h:122
@ DT_VIEW_REJECT
Definition image.h:355
static dt_image_cache_t * _image_cache
Definition image_cache.c:82
void dt_image_cache_set_print_timestamp(const int32_t imgid)
dt_image_t * dt_image_cache_get_existing(const int32_t imgid, char mode)
void dt_image_cache_write_release(dt_image_t *img, dt_image_cache_write_mode_t mode)
static uint64_t _image_cache_self_hash(const dt_image_t *img)
Definition image_cache.c:91
dt_image_t * dt_image_cache_testget(const int32_t imgid, char mode)
gboolean dt_image_cache_is_ready(void)
Has the image cache been initialised? Callers that run before dt_image_cache_init() or after its clea...
Definition image_cache.c:84
void dt_image_cache_get_usage(size_t *current, size_t *max)
GArray * dt_image_cache_get_entries_stats(void)
static gboolean _verbose
Definition image_cache.c:61
void dt_image_cache_set_export_timestamp(const int32_t imgid)
#define _cache_print(channel,...)
Definition image_cache.c:64
void dt_image_cache_allocate(void *data, dt_cache_entry_t *entry)
void dt_image_cache_init(const gboolean verbose)
Initialise the cache.
void dt_image_derive_fields(dt_image_t *img)
Compute the fields the database does not store: rating, monochrome and HDR predicates,...
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
dt_image_t * dt_image_cache_get_reload(const int32_t imgid, char mode)
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)
int dt_image_invalid(const dt_image_t *img)
int dt_image_cache_seed(const dt_image_t *img)
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)
void dt_image_cache_print(void)
void dt_image_cache_remove(const int32_t imgid)
void dt_image_cache_read_release(const dt_image_t *img)
void dt_image_cache_cleanup(void)
dt_image_cache_write_mode_t
Definition image_cache.h:46
@ DT_IMAGE_CACHE_MINIMAL
Definition image_cache.h:53
@ DT_IMAGE_CACHE_SAFE
Definition image_cache.h:48
void dt_image_repository_cleanup(void)
Finalise the prepared statements. Called at shutdown, after the last cache release and before the dat...
gboolean dt_image_repository_load(const int32_t imgid, dt_image_t *img)
Fill img from the main.images row for imgid.
void dt_image_repository_store(const dt_image_t *img)
Write img back to main.images, plus its colour labels and history hash.
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
@ DT_DEBUG_CACHE
Definition logging.h:51
@ DT_DEBUG_IMAGEIO
Definition logging.h:68
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
Definition mem_alloc.h:184
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
char * key
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
size_t size
Definition mipmap_cache.c:3
dt_mipmap_buffer_dsc_flags flags
Definition mipmap_cache.c:4
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
#define DT_MAX_FILENAME_LEN
Definition paths.h:35
void dt_control_signal_connect(const dt_control_signal_t *ctlsig, dt_signal_t signal, GCallback cb, gpointer user_data)
Definition signal.c:496
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:390
struct dt_control_signal_t * dt_control_signal_get_global(void)
Definition darktable.c:616
@ DT_SIGNAL_IMAGE_INFO_CHANGED
This signal is raised when any of image info has changed
Definition signal.h:148
static const dt_aligned_pixel_simd_t value
Definition simd.h:144
int32_t dt_cache_contains(dt_cache_t *cache, const uint32_t key)
dt_cache_entry_t * dt_cache_testget(dt_cache_t *cache, const uint32_t key, char mode)
int dt_cache_seed(dt_cache_t *cache, const uint32_t key, const void *data, size_t data_size, size_t cost)
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)
unsigned __int64 uint64_t
Definition strptime.c:75
uint32_t key
int _lock_demoting
void * data
size_t cost
size_t cost
size_t cost_quota
GHashTable * hashtable
dt_pthread_mutex_t lock
Definition image_cache.h:77
char filename[128]
Definition image_cache.h:80
size_t size
Definition image_cache.h:79
int32_t imgid
Definition image_cache.h:78
dt_cache_t cache
Definition image_cache.c:74
gboolean has_audio
Definition image.h:476
gboolean is_hdr
Definition image.h:479
float exif_exposure
Definition image.h:367
int32_t height
Definition image.h:397
GTimeSpan export_timestamp
Definition image.h:415
uint64_t history_hash
Definition image.h:404
float exif_focus_distance
Definition image.h:372
gboolean is_bw
Definition image.h:477
int32_t group_id
Definition image.h:401
float exif_exposure_bias
Definition image.h:368
uint16_t raw_black_level
Definition image.h:437
float exif_iso
Definition image.h:370
GList * dng_gain_maps
Definition image.h:464
uint32_t raw_white_point
Definition image.h:439
float exif_aperture
Definition image.h:369
char local_copy_path[DT_PATH_MAX]
Definition image.h:388
int32_t version
Definition image.h:401
int32_t crop_height
Definition image.h:398
dt_image_geoloc_t geoloc
Definition image.h:434
int32_t flags
Definition image.h:401
dt_image_orientation_t orientation
Definition image.h:366
int32_t width
Definition image.h:397
float exif_focal_length
Definition image.h:371
char exif_maker[64]
Definition image.h:374
GTimeSpan change_timestamp
Definition image.h:415
int32_t crop_y
Definition image.h:398
int rating
Definition image.h:473
gboolean has_localcopy
Definition image.h:475
char exif_lens[128]
Definition image.h:376
GTimeSpan print_timestamp
Definition image.h:415
int32_t film_id
Definition image.h:401
char folder[DT_PATH_MAX]
Definition image.h:390
GTimeSpan exif_datetime_taken
Definition image.h:377
int32_t crop_x
Definition image.h:398
int color_labels
Definition image.h:472
float d65_color_matrix[9]
Definition image.h:421
char filmroll[DT_PATH_MAX]
Definition image.h:391
char exif_model[64]
Definition image.h:375
dt_image_colorspace_t colorspace
Definition image.h:429
struct dt_colorspaces_color_profile_t * embedded_profile
Definition image.h:428
uint8_t * profile
Definition image.h:422
char datetime[200]
Definition image.h:392
struct dt_cache_entry_t * cache_entry
Definition image.h:482
int32_t crop_width
Definition image.h:398
char local_copy_legacy_path[DT_PATH_MAX]
Definition image.h:389
dt_image_raw_parameters_t legacy_flip
Definition image.h:431
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:386
int32_t id
Definition image.h:401
uint64_t self_hash
Definition image.h:412
float exif_crop
Definition image.h:373
char fullpath[DT_PATH_MAX]
Definition image.h:387
gboolean is_bw_flow
Definition image.h:478
void dt_supervisor_image(const dt_sv_op_t op, const int32_t imgid, const dt_image_t *img)
dt_sv_op_t
Definition supervisor.h:77
@ DT_SV_UPDATE
Definition supervisor.h:79
@ DT_SV_CREATE
Definition supervisor.h:78
@ DT_SV_DELETE
Definition supervisor.h:81
static gboolean dt_supervisor_active(void)
Definition supervisor.h:95