Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
generate-cache/main.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2015-2016 Roman Lebedev.
4 Copyright (C) 2015-2017 Tobias Ellinghaus.
5 Copyright (C) 2016 Jan Kundrát.
6 Copyright (C) 2016-2017, 2020 Pascal Obry.
7 Copyright (C) 2019 parafin.
8 Copyright (C) 2020 Aldric Renaudin.
9 Copyright (C) 2020 David-Tillmann Schaefer.
10 Copyright (C) 2020 Hubert Kowalski.
11 Copyright (C) 2020 Philippe Weyland.
12 Copyright (C) 2021 Hanno Schwalm.
13 Copyright (C) 2021 Ralf Brown.
14 Copyright (C) 2022, 2025 Aurélien PIERRE.
15 Copyright (C) 2022 Martin Bařinka.
16 Copyright (C) 2022 Victor Forsiuk.
17 Copyright (C) 2023 Maurizio Paglia.
18
19 darktable is free software: you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation, either version 3 of the License, or
22 (at your option) any later version.
23
24 darktable is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
28
29 You should have received a copy of the GNU General Public License
30 along with darktable. If not, see <http://www.gnu.org/licenses/>.
31*/
32
33#include <glib.h> // for g_mkdir_with_parents, _
34#include <gtk/gtk.h> // for gtk_init_check
35#include <libintl.h> // for bind_textdomain_codeset, etc
36#include <limits.h> // for PATH_MAX
37#include <sqlite3.h> // for sqlite3_column_int, etc
38#include <stddef.h> // for size_t
39#include <stdint.h> // for uint32_t
40#include <stdio.h> // for fprintf, stderr, snprintf, NULL, etc
41#include <stdlib.h> // for exit, EXIT_FAILURE
42#include <string.h> // for strcmp
43#include <unistd.h> // for access, R_OK
44
45#include "common/darktable.h" // for darktable, darktable_t, dt_cleanup, etc
46#include "common/database.h" // for dt_database_get
47#include "common/debug.h" // for DT_DEBUG_SQLITE3_PREPARE_V2
48#include "common/mipmap_cache.h" // for dt_mipmap_size_t, etc
50#include "config.h" // for GETTEXT_PACKAGE, etc
51#include "control/conf.h" // for dt_conf_get_bool
52
53#ifdef __APPLE__
54#include "osx/osx.h"
55#endif
56
57#ifdef _WIN32
58#include "win/main_wrapper.h"
59#endif
60
61static int generate_thumbnail_cache(const dt_mipmap_size_t min_mip, const dt_mipmap_size_t max_mip, const int32_t min_imgid, const int32_t max_imgid)
62{
63 fprintf(stderr, _("creating cache directories\n"));
64 for(dt_mipmap_size_t k = min_mip; k <= max_mip; k++)
65 {
66 char dirname[PATH_MAX] = { 0 };
68
69 fprintf(stderr, _("creating cache directory '%s'\n"), dirname);
70 if(g_mkdir_with_parents(dirname, 0750))
71 {
72 fprintf(stderr, _("could not create directory '%s'!\n"), dirname);
73 return 1;
74 }
75 }
76
77 // some progress counter
78 sqlite3_stmt *stmt;
79 size_t image_count = 0, counter = 0;
81 "SELECT COUNT(*) FROM main.images WHERE id >= ?1 AND id <= ?2", -1, &stmt, 0);
82 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, min_imgid);
83 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_imgid);
84 if(sqlite3_step(stmt) == SQLITE_ROW)
85 {
86 image_count = sqlite3_column_int(stmt, 0);
87 sqlite3_finalize(stmt);
88 }
89 else
90 {
91 return 1;
92 }
93
94 if(!image_count)
95 {
96 fprintf(stderr, _("warning: no images are matching the requested image id range\n"));
97 if(min_imgid > max_imgid)
98 {
99 fprintf(stderr, _("warning: did you want to swap these boundaries?\n"));
100 }
101 }
102
103 // go through all images:
105 "SELECT id, filename FROM main.images WHERE id >= ?1 AND id <= ?2", -1, &stmt, 0);
106 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, min_imgid);
107 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_imgid);
108 while(sqlite3_step(stmt) == SQLITE_ROW)
109 {
110 const int32_t imgid = sqlite3_column_int(stmt, 0);
111 const char *imgfilename = (const char*)sqlite3_column_text(stmt, 1);
112
113 counter++;
114 fprintf(stderr, "image %" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT " (%.02f%%) (id:%d, file=%s)\n", counter, image_count, 100.0 * counter / (float)image_count, imgid, imgfilename);
115
116 for(int k = max_mip; k >= min_mip && k >= 0; k--)
117 {
118 char filename[PATH_MAX] = { 0 };
120
121 // if a valid thumbnail file is already on disc - do nothing
122 if(dt_util_test_image_file(filename)) continue;
123
124 // else, generate thumbnail and store in mipmap cache.
128 }
129
130 // and immediately write thumbs to disc and remove from mipmap cache.
132 // thumbnail in sync with image
133 }
134
135 sqlite3_finalize(stmt);
136 fprintf(stderr, "done\n");
137
138 return 0;
139}
140
141static void usage(const char *progname)
142{
143 fprintf(stderr,
144 "usage: %s [-h, --help; --version]\n"
145 " [--min-mip <0-8> (default = 0)] [-m, --max-mip <0-8> (default = 2)]\n"
146 " [--min-imgid <N>] [--max-imgid <N>]\n"
147 " [--core <darktable options>]\n"
148 "\n"
149 "When multiple mipmap sizes are requested, the biggest one is computed\n"
150 "while the rest are quickly downsampled.\n"
151 "\n"
152 "The --min-imgid and --max-imgid specify the range of internal image ID\n"
153 "numbers to work on.\n",
154 progname);
155}
156
157int main(int argc, char *arg[])
158{
159#ifdef __APPLE__
161#endif
162
163 // get valid locale dir
164 dt_loc_init(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
165 char localedir[PATH_MAX] = { 0 };
166 dt_loc_get_localedir(localedir, sizeof(localedir));
167 bindtextdomain(GETTEXT_PACKAGE, localedir);
168
169 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
170 textdomain(GETTEXT_PACKAGE);
171
172 gtk_init_check(&argc, &arg);
173
174 // parse command line arguments
177 int32_t min_imgid = UNKNOWN_IMAGE;
178 int32_t max_imgid = INT32_MAX;
179
180 int k;
181 for(k = 1; k < argc; k++)
182 {
183 if(!strcmp(arg[k], "-h") || !strcmp(arg[k], "--help"))
184 {
185 usage(arg[0]);
186 exit(EXIT_FAILURE);
187 }
188 else if(!strcmp(arg[k], "--version"))
189 {
190 printf("this is ansel-generate-cache %s\ncopyright (c) 2014 johannes hanika; 2015 LebedevRI\n",
192 exit(EXIT_FAILURE);
193 }
194 else if((!strcmp(arg[k], "-m") || !strcmp(arg[k], "--max-mip")) && argc > k + 1)
195 {
196 k++;
197 max_mip = (dt_mipmap_size_t)MIN(MAX(atoi(arg[k]), DT_MIPMAP_0), DT_MIPMAP_7);
198 }
199 else if(!strcmp(arg[k], "--min-mip") && argc > k + 1)
200 {
201 k++;
202 min_mip = (dt_mipmap_size_t)MIN(MAX(atoi(arg[k]), DT_MIPMAP_0), DT_MIPMAP_7);
203 }
204 else if(!strcmp(arg[k], "--min-imgid") && argc > k + 1)
205 {
206 k++;
207 min_imgid = (int32_t)MIN(MAX(atoi(arg[k]), 0), INT32_MAX);
208 }
209 else if(!strcmp(arg[k], "--max-imgid") && argc > k + 1)
210 {
211 k++;
212 max_imgid = (int32_t)MIN(MAX(atoi(arg[k]), 0), INT32_MAX);
213 }
214 else if(!strcmp(arg[k], "--core"))
215 {
216 // everything from here on should be passed to the core
217 k++;
218 break;
219 }
220 }
221
222 int m_argc = 0;
223 char **m_arg = malloc(sizeof(char *) * (3 + argc - k + 1));
224 m_arg[m_argc++] = "ansel-generate-cache";
225 m_arg[m_argc++] = "--conf";
226 m_arg[m_argc++] = "write_sidecar_files=never";
227 for(; k < argc; k++) m_arg[m_argc++] = arg[k];
228 m_arg[m_argc] = NULL;
229
230 // init dt without gui:
231 if(dt_init(m_argc, m_arg, FALSE, TRUE))
232 {
233 dt_free(m_arg);
234 exit(EXIT_FAILURE);
235 }
236
237 if(!dt_conf_get_bool("cache_disk_backend"))
238 {
239 fprintf(stderr, _("warning: disk backend for thumbnail cache is disabled (cache_disk_backend)\nif you want "
240 "to pre-generate thumbnails and for Ansel to use them, you need to enable disk backend "
241 "for thumbnail cache\nno thumbnails to be generated, done.\n"));
242 dt_cleanup();
243 dt_free(m_arg);
244 exit(EXIT_FAILURE);
245 }
246
247 if(min_mip > max_mip)
248 {
249 fprintf(stderr, _("error: ensure that min_mip <= max_mip\n"));
250 dt_free(m_arg);
251 exit(EXIT_FAILURE);
252 }
253
254 fprintf(stderr, _("creating complete lighttable thumbnail cache\n"));
255
256 if(generate_thumbnail_cache(min_mip, max_mip, min_imgid, max_imgid))
257 {
258 dt_free(m_arg);
259 exit(EXIT_FAILURE);
260 }
261
262 dt_cleanup();
263
264 dt_free(m_arg);
265}
266
267// clang-format off
268// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
269// vim: shiftwidth=2 expandtab tabstop=2 cindent
270// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
271// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
const char darktable_package_version[]
#define GETTEXT_PACKAGE
int dt_conf_get_bool(const char *name)
void dt_cleanup()
Definition darktable.c:1311
darktable_t darktable
Definition darktable.c:181
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
Definition darktable.c:451
#define UNKNOWN_IMAGE
Definition darktable.h:182
#define dt_free(ptr)
Definition darktable.h:456
#define PATH_MAX
Definition darktable.h:1062
sqlite3 * dt_database_get(const dt_database_t *db)
Definition database.c:3646
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
Definition debug.h:107
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
Definition debug.h:115
void dt_loc_get_localedir(char *localedir, size_t bufsize)
void dt_loc_init(const char *datadir, const char *moduledir, const char *localedir, const char *configdir, const char *cachedir, const char *tmpdir, const char *kerneldir)
static void usage(const char *progname)
static int generate_thumbnail_cache(const dt_mipmap_size_t min_mip, const dt_mipmap_size_t max_mip, const int32_t min_imgid, const int32_t max_imgid)
float *const restrict const size_t k
void dt_mipmap_get_cache_filename(char path[PATH_MAX], const dt_mipmap_cache_t *cache, dt_mipmap_size_t mip, const int32_t imgid)
void dt_mimap_cache_evict(dt_mipmap_cache_t *cache, const int32_t imgid)
void dt_mipmap_get_cache_dir(char path[PATH_MAX], const dt_mipmap_cache_t *cache, dt_mipmap_size_t mip)
#define dt_mipmap_cache_get(A, B, C, D, E, F)
@ DT_MIPMAP_BLOCKING
#define dt_mipmap_cache_release(A, B)
dt_mipmap_size_t
@ DT_MIPMAP_7
@ DT_MIPMAP_0
@ DT_MIPMAP_2
void dt_osx_prepare_environment()
Definition osx.mm:212
int main()
Definition prova.c:47
struct dt_mipmap_cache_t * mipmap_cache
Definition darktable.h:776
const struct dt_database_t * db
Definition darktable.h:779
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
gboolean dt_util_test_image_file(const char *filename)
Definition utility.c:318