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
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 <stddef.h> // for size_t
38#include <stdint.h> // for uint32_t
39#include <stdio.h> // for fprintf, stderr, snprintf, NULL, etc
40#include <stdlib.h> // for exit, EXIT_FAILURE
41#include <string.h> // for strcmp
42
43#include "darktable.h" // for darktable, darktable_t, dt_cleanup, etc
44#include "database/image_repository.h" // for dt_image_repository_foreach_in_id_range
45#include "caches/mipmap_cache.h" // for dt_mipmap_size_t, etc
47#include "config.h" // for GETTEXT_PACKAGE, etc
48#include "common/conf.h" // for dt_conf_get_bool
49#include "common/utility.h"
50
51#ifdef __APPLE__
52#include "osx/osx.h"
53#endif
54
55#ifdef _WIN32
56#include "win/main_wrapper.h"
57#endif
58
59/* What _generate_one() needs that is not in the row: the mip range to fill, and where the
60 * progress line is up to. */
68
69static void _generate_one(const int32_t imgid, const char *imgfilename, void *user_data)
70{
71 _generate_ctx_t *ctx = (_generate_ctx_t *)user_data;
72
73 ctx->counter++;
74 fprintf(stderr, "image %" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT " (%.02f%%) (id:%d, file=%s)\n",
75 ctx->counter, ctx->image_count, 100.0 * ctx->counter / (float)ctx->image_count, imgid,
77
78 for(int k = ctx->max_mip; k >= ctx->min_mip && k >= 0; k--)
79 {
80 char filename[PATH_MAX] = { 0 };
81 dt_mipmap_get_cache_filename(filename, k, imgid);
82
83 // if a valid thumbnail file is already on disc - do nothing
84 if(dt_util_test_image_file(filename)) continue;
85
86 // else, generate thumbnail and store in mipmap cache.
88 dt_mipmap_cache_get(&buf, imgid, k, DT_MIPMAP_BLOCKING, 'r');
90 }
91
92 // and immediately write thumbs to disc and remove from mipmap cache.
94 // thumbnail in sync with image
95}
96
97static 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)
98{
99 fprintf(stderr, _("creating cache directories\n"));
100 for(dt_mipmap_size_t k = min_mip; k <= max_mip; k++)
101 {
102 char dirname[PATH_MAX] = { 0 };
103 dt_mipmap_get_cache_dir(dirname, k);
104
105 fprintf(stderr, _("creating cache directory '%s'\n"), dirname);
106 if(g_mkdir_with_parents(dirname, 0750))
107 {
108 fprintf(stderr, _("could not create directory '%s'!\n"), dirname);
109 return 1;
110 }
111 }
112
113 // some progress counter
115 if(counted < 0) return 1;
116 size_t image_count = (size_t)counted;
117
118 if(!image_count)
119 {
120 fprintf(stderr, _("warning: no images are matching the requested image id range\n"));
121 if(min_imgid > max_imgid)
122 {
123 fprintf(stderr, _("warning: did you want to swap these boundaries?\n"));
124 }
125 }
126
127 // go through all images:
128 _generate_ctx_t ctx = { .image_count = image_count, .counter = 0,
129 .min_mip = min_mip, .max_mip = max_mip };
131
132 fprintf(stderr, "done\n");
133
134 return 0;
135}
136
137static void usage(const char *progname)
138{
140 "usage: %s [-h, --help; --version]\n"
141 " [--min-mip <0-8> (default = 0)] [-m, --max-mip <0-8> (default = 2)]\n"
142 " [--min-imgid <N>] [--max-imgid <N>]\n"
143 " [--core <darktable options>]\n"
144 "\n"
145 "When multiple mipmap sizes are requested, the biggest one is computed\n"
146 "while the rest are quickly downsampled.\n"
147 "\n"
148 "The --min-imgid and --max-imgid specify the range of internal image ID\n"
149 "numbers to work on.\n",
150 progname);
151}
152
153int main(int argc, char *arg[])
154{
155#ifdef __APPLE__
157#endif
158
159 // get valid locale dir
161 char localedir[PATH_MAX] = { 0 };
162 dt_loc_get_localedir(localedir, sizeof(localedir));
164
167
169
170 // parse command line arguments
173 int32_t min_imgid = UNKNOWN_IMAGE;
174 int32_t max_imgid = INT32_MAX;
175
176 int k;
177 for(k = 1; k < argc; k++)
178 {
179 if(!strcmp(arg[k], "-h") || !strcmp(arg[k], "--help"))
180 {
181 usage(arg[0]);
182 exit(EXIT_FAILURE);
183 }
184 else if(!strcmp(arg[k], "--version"))
185 {
186 printf("this is ansel-generate-cache %s\ncopyright (c) 2014 johannes hanika; 2015 LebedevRI\n",
188 exit(EXIT_FAILURE);
189 }
190 else if((!strcmp(arg[k], "-m") || !strcmp(arg[k], "--max-mip")) && argc > k + 1)
191 {
192 k++;
194 }
195 else if(!strcmp(arg[k], "--min-mip") && argc > k + 1)
196 {
197 k++;
199 }
200 else if(!strcmp(arg[k], "--min-imgid") && argc > k + 1)
201 {
202 k++;
203 min_imgid = (int32_t)MIN(MAX(atoi(arg[k]), 0), INT32_MAX);
204 }
205 else if(!strcmp(arg[k], "--max-imgid") && argc > k + 1)
206 {
207 k++;
208 max_imgid = (int32_t)MIN(MAX(atoi(arg[k]), 0), INT32_MAX);
209 }
210 else if(!strcmp(arg[k], "--core"))
211 {
212 // everything from here on should be passed to the core
213 k++;
214 break;
215 }
216 }
217
218 int m_argc = 0;
219 char **m_arg = malloc(sizeof(char *) * (3 + argc - k + 1));
220 m_arg[m_argc++] = "ansel-generate-cache";
221 m_arg[m_argc++] = "--conf";
222 m_arg[m_argc++] = "write_sidecar_files=never";
223 for(; k < argc; k++) m_arg[m_argc++] = arg[k];
224 m_arg[m_argc] = NULL;
225
226 // init dt without gui:
228 {
229 dt_free(m_arg);
230 exit(EXIT_FAILURE);
231 }
232
233 if(!dt_conf_get_bool("cache_disk_backend"))
234 {
235 fprintf(stderr, _("warning: disk backend for thumbnail cache is disabled (cache_disk_backend)\nif you want "
236 "to pre-generate thumbnails and for Ansel to use them, you need to enable disk backend "
237 "for thumbnail cache\nno thumbnails to be generated, done.\n"));
238 dt_cleanup();
239 dt_free(m_arg);
240 exit(EXIT_FAILURE);
241 }
242
243 if(min_mip > max_mip)
244 {
245 fprintf(stderr, _("error: ensure that min_mip <= max_mip\n"));
246 dt_free(m_arg);
247 exit(EXIT_FAILURE);
248 }
249
250 fprintf(stderr, _("creating complete lighttable thumbnail cache\n"));
251
252 if(generate_thumbnail_cache(min_mip, max_mip, min_imgid, max_imgid))
253 {
254 dt_free(m_arg);
255 exit(EXIT_FAILURE);
256 }
257
258 dt_cleanup();
259
260 dt_free(m_arg);
261}
262
263// clang-format off
264// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
265// vim: shiftwidth=2 expandtab tabstop=2 cindent
266// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
267// 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:1840
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
Definition darktable.c:878
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)
#define UNKNOWN_IMAGE
Definition image.h:77
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)
Definition mem_alloc.h:97
void dt_mipmap_get_cache_filename(char path[PATH_MAX], dt_mipmap_size_t mip, const int32_t imgid)
void dt_mimap_cache_evict(const int32_t imgid)
void dt_mipmap_get_cache_dir(char path[PATH_MAX], dt_mipmap_size_t mip)
@ 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 PATH_MAX
Definition paths.h:45
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:321