Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
ansel-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 Copyright (C) 2026 Guillaume Stutin.
19
20 darktable is free software: you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation, either version 3 of the License, or
23 (at your option) any later version.
24
25 darktable is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with darktable. If not, see <http://www.gnu.org/licenses/>.
32*/
33
34#include <glib.h> // for g_mkdir_with_parents, _
35#include "common/paths.h" // DT_PATH_MAX
36#include <gtk/gtk.h> // for gtk_init_check
37#include <libintl.h> // for bind_textdomain_codeset, etc
38#include <limits.h> // for DT_PATH_MAX
39#include <stddef.h> // for size_t
40#include <stdint.h> // for uint32_t
41#include <stdio.h> // for fprintf, stderr, snprintf, NULL, etc
42#include <stdlib.h> // for exit, EXIT_FAILURE
43#include <string.h> // for strcmp
44
45#include "darktable.h" // for darktable, darktable_t, dt_cleanup, etc
46#include "database/image_repository.h" // for dt_image_repository_foreach_in_id_range
47#include "caches/mipmap_cache.h" // for dt_mipmap_size_t, etc
49#include "config.h" // for GETTEXT_PACKAGE, etc
50#include "common/conf.h" // for dt_conf_get_bool
51#include "common/utility.h"
52
53#ifdef __APPLE__
54#include "osx/osx.h"
55#endif
56
57#ifdef _WIN32
58#include "win/main_wrapper.h"
59#endif
60
61/* What _generate_one() needs that is not in the row: the mip range to fill, and where the
62 * progress line is up to. */
70
71static void _generate_one(const int32_t imgid, const char *imgfilename, void *user_data)
72{
73 _generate_ctx_t *ctx = (_generate_ctx_t *)user_data;
74
75 ctx->counter++;
76 fprintf(stderr, "image %" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT " (%.02f%%) (id:%d, file=%s)\n",
77 ctx->counter, ctx->image_count, 100.0 * ctx->counter / (float)ctx->image_count, imgid,
79
80 for(int k = ctx->max_mip; k >= ctx->min_mip && k >= 0; k--)
81 {
82 char filename[DT_PATH_MAX] = { 0 };
83 dt_mipmap_get_cache_filename(filename, k, imgid);
84
85 // if a valid thumbnail file is already on disc - do nothing
86 if(dt_util_test_image_file(filename)) continue;
87
88 // else, generate thumbnail and store in mipmap cache.
90 dt_mipmap_cache_get(&buf, imgid, k, DT_MIPMAP_BLOCKING, 'r');
92 }
93
94 // and immediately write thumbs to disc and remove from mipmap cache.
96 // thumbnail in sync with image
97}
98
99static 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)
100{
101 fprintf(stderr, _("creating cache directories\n"));
102 for(dt_mipmap_size_t k = min_mip; k <= max_mip; k++)
103 {
104 char dirname[DT_PATH_MAX] = { 0 };
105 dt_mipmap_get_cache_dir(dirname, k);
106
107 fprintf(stderr, _("creating cache directory '%s'\n"), dirname);
108 if(g_mkdir_with_parents(dirname, 0750))
109 {
110 fprintf(stderr, _("could not create directory '%s'!\n"), dirname);
111 return 1;
112 }
113 }
114
115 // some progress counter
117 if(counted < 0) return 1;
118 size_t image_count = (size_t)counted;
119
120 if(!image_count)
121 {
122 fprintf(stderr, _("warning: no images are matching the requested image id range\n"));
123 if(min_imgid > max_imgid)
124 {
125 fprintf(stderr, _("warning: did you want to swap these boundaries?\n"));
126 }
127 }
128
129 // go through all images:
130 _generate_ctx_t ctx = { .image_count = image_count, .counter = 0,
131 .min_mip = min_mip, .max_mip = max_mip };
133
134 fprintf(stderr, "done\n");
135
136 return 0;
137}
138
139static void usage(const char *progname)
140{
142 "usage: %s [-h, --help; --version]\n"
143 " [--min-mip <0-8> (default = 0)] [-m, --max-mip <0-8> (default = 2)]\n"
144 " [--min-imgid <N>] [--max-imgid <N>]\n"
145 " [--core <darktable options>]\n"
146 "\n"
147 "When multiple mipmap sizes are requested, the biggest one is computed\n"
148 "while the rest are quickly downsampled.\n"
149 "\n"
150 "The --min-imgid and --max-imgid specify the range of internal image ID\n"
151 "numbers to work on.\n",
152 progname);
153}
154
155int main(int argc, char *arg[])
156{
157#ifdef __APPLE__
159#endif
160
161 // get valid locale dir
162 char localedir[DT_PATH_MAX] = { 0 };
163 dt_loc_resolve_localedir(localedir, sizeof(localedir));
165
168
170
171 // parse command line arguments
174 int32_t min_imgid = UNKNOWN_IMAGE;
175 int32_t max_imgid = INT32_MAX;
176
177 int k;
178 for(k = 1; k < argc; k++)
179 {
180 if(!strcmp(arg[k], "-h") || !strcmp(arg[k], "--help"))
181 {
182 usage(arg[0]);
183 exit(EXIT_FAILURE);
184 }
185 else if(!strcmp(arg[k], "--version"))
186 {
187 printf("this is ansel-generate-cache %s\ncopyright (c) 2014 johannes hanika; 2015 LebedevRI\n",
189 exit(EXIT_FAILURE);
190 }
191 else if((!strcmp(arg[k], "-m") || !strcmp(arg[k], "--max-mip")) && argc > k + 1)
192 {
193 k++;
195 }
196 else if(!strcmp(arg[k], "--min-mip") && argc > k + 1)
197 {
198 k++;
200 }
201 else if(!strcmp(arg[k], "--min-imgid") && argc > k + 1)
202 {
203 k++;
204 min_imgid = (int32_t)MIN(MAX(atoi(arg[k]), 0), INT32_MAX);
205 }
206 else if(!strcmp(arg[k], "--max-imgid") && argc > k + 1)
207 {
208 k++;
209 max_imgid = (int32_t)MIN(MAX(atoi(arg[k]), 0), INT32_MAX);
210 }
211 else if(!strcmp(arg[k], "--core"))
212 {
213 // everything from here on should be passed to the core
214 k++;
215 break;
216 }
217 }
218
219 int m_argc = 0;
220 char **m_arg = malloc(sizeof(char *) * (3 + argc - k + 1));
221 m_arg[m_argc++] = "ansel-generate-cache";
222 m_arg[m_argc++] = "--conf";
223 m_arg[m_argc++] = "write_sidecar_files=never";
224 for(; k < argc; k++) m_arg[m_argc++] = arg[k];
225 m_arg[m_argc] = NULL;
226
227 // init dt without gui:
229 {
230 dt_free(m_arg);
231 exit(EXIT_FAILURE);
232 }
233
234 if(!dt_conf_get_bool("cache_disk_backend"))
235 {
236 fprintf(stderr, _("warning: disk backend for thumbnail cache is disabled (cache_disk_backend)\nif you want "
237 "to pre-generate thumbnails and for Ansel to use them, you need to enable disk backend "
238 "for thumbnail cache\nno thumbnails to be generated, done.\n"));
239 dt_cleanup();
240 dt_free(m_arg);
241 exit(EXIT_FAILURE);
242 }
243
244 if(min_mip > max_mip)
245 {
246 fprintf(stderr, _("error: ensure that min_mip <= max_mip\n"));
247 dt_free(m_arg);
248 exit(EXIT_FAILURE);
249 }
250
251 fprintf(stderr, _("creating complete lighttable thumbnail cache\n"));
252
253 if(generate_thumbnail_cache(min_mip, max_mip, min_imgid, max_imgid))
254 {
255 dt_free(m_arg);
256 exit(EXIT_FAILURE);
257 }
258
259 dt_cleanup();
260
261 dt_free(m_arg);
262}
263
264// clang-format off
265// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
266// vim: shiftwidth=2 expandtab tabstop=2 cindent
267// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
268// clang-format on
static void usage(const char *progname)
static void _generate_one(const int32_t imgid, const char *imgfilename, void *user_data)
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)
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
int dt_conf_get_bool(const char *name)
const char darktable_package_version[]
#define GETTEXT_PACKAGE
void dt_cleanup()
Definition darktable.c:1864
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
Definition darktable.c:885
void dt_loc_resolve_localedir(char *localedir, size_t bufsize)
Resolve the locale directory the way dt_loc_init() does, creating it if missing, but set no global an...
#define UNKNOWN_IMAGE
Definition image.h:78
int dt_image_repository_count_in_id_range(const int32_t min_imgid, const int32_t max_imgid)
How many images have an id in [min_imgid, max_imgid]. -1 when unreadable.
void dt_image_repository_foreach_in_id_range(const int32_t min_imgid, const int32_t max_imgid, dt_image_repository_id_filename_cb cb, void *user_data)
Walk the images whose id falls in [min_imgid, max_imgid], in row order.
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
float *const restrict const size_t k
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
void dt_mipmap_get_cache_dir(char path[DT_PATH_MAX], dt_mipmap_size_t mip)
void dt_mimap_cache_evict(const int32_t imgid)
void dt_mipmap_get_cache_filename(char path[DT_PATH_MAX], dt_mipmap_size_t mip, const int32_t imgid)
@ DT_MIPMAP_BLOCKING
dt_mipmap_size_t
@ DT_MIPMAP_7
@ DT_MIPMAP_0
@ DT_MIPMAP_2
#define dt_mipmap_cache_get(B, C, D, E, F)
#define dt_mipmap_cache_release(B)
void dt_osx_prepare_environment()
Definition osx.mm:213
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
int main()
Definition prova.c:47
#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:345