Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
finalscale.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2015 johannes hanika.
4 Copyright (C) 2015-2016 Roman Lebedev.
5 Copyright (C) 2015 Ulrich Pegelow.
6 Copyright (C) 2016, 2019 Tobias Ellinghaus.
7 Copyright (C) 2017 Heiko Bauke.
8 Copyright (C) 2018, 2020-2021, 2023-2026 Aurélien PIERRE.
9 Copyright (C) 2018 Edgardo Hoszowski.
10 Copyright (C) 2020 Aldric Renaudin.
11 Copyright (C) 2020-2021 Pascal Obry.
12 Copyright (C) 2021 Hanno Schwalm.
13 Copyright (C) 2022 Martin Bařinka.
14 Copyright (C) 2022 Philipp Lutz.
15
16 darktable is free software: you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation, either version 3 of the License, or
19 (at your option) any later version.
20
21 darktable is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with darktable. If not, see <http://www.gnu.org/licenses/>.
28*/
29#ifdef HAVE_CONFIG_H
30#include "system/mem_alloc.h"
31#include "common/conf.h"
33#include "common/logging.h"
34#include "config.h"
35#endif
36#include "develop/imageop_gui.h"
37#include "widgets/bauhaus.h"
38#include "pixel/interpolation.h"
39#include "develop/imageop.h"
41#include "develop/tiling.h"
42#include "iop/iop_api.h"
43
45
50
52
53const char *name()
54{
55 return C_("modulename", "Final resampling");
56}
57
62
64{
66}
67
72
73
74// see ../../doc/resizing-scaling.md for details
76 const dt_iop_roi_t *const roi_out,
77 dt_iop_roi_t *roi_in)
78{
79 *roi_in = *roi_out;
80 int scaling_pref = dt_conf_get_int("darkroom/render_size");
81
82 // Use cases :
83 // 1. we run an export pipeline. We mandatorily get a 1:1 image, process it whole, downscale at the end.
84 // 2. we run a GUI (darkroom) pipeline. If we upsample it, we want it done at the end of the pipe,
85 // so sharpening and blurring is at most 1:1.
86 if(roi_in->scale > 1.f)
87 {
88 roi_in->x = (int)roundf((float)roi_in->x / roi_out->scale);
89 roi_in->y = (int)roundf((float)roi_in->y / roi_out->scale);
90 roi_in->width = (int)roundf(roi_out->width / roi_out->scale);
91 roi_in->height = (int)roundf(roi_out->height / roi_out->scale);
92 roi_in->scale = 1.0f;
93 }
94 // 3. we run the pipeline in full-res mode : force scale = 1 no matter what.
95 else if(scaling_pref == 0)
96 {
97 // x, y are in original-image coordinates — leave them unchanged.
98 roi_in->width = (int)roundf(roi_out->width / roi_out->scale);
99 roi_in->height = (int)roundf(roi_out->height / roi_out->scale);
100 roi_in->scale = 1.0f;
101 const float resample_scale = roi_out->scale / roi_in->scale;
102 roi_in->x = (int)roundf(roi_in->x / resample_scale);
103 roi_in->y = (int)roundf(roi_in->y / resample_scale);
104 }
105 // else if(scaling_pref == 1) : we run the pipeline scaled at display resolution
106 // nothing to resample and anyway commit_params() will self-disable
107}
108
109void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece,
110 const float *const in, float *const out, const dt_iop_roi_t *const roi_in,
111 const dt_iop_roi_t *const roi_out)
112{
114 dt_interpolation_resample_roi_1c(itor, out, roi_out, in, roi_in);
115}
116
118 const void *const ivoid, void *const ovoid)
119{
120 dt_iop_roi_t roi_in = piece->roi_in;
121 dt_iop_roi_t roi_out = piece->roi_out;
122 // ROI (x,y) are not used here since we don't crop but only scale.
123 // Leaving them will offset the result, which is not what we want.
124 roi_in.x = 0;
125 roi_in.y = 0;
126 roi_out.x = 0;
127 roi_out.y = 0;
128 dt_iop_clip_and_zoom_roi(ovoid, ivoid, &roi_out, &roi_in, roi_out.width, roi_in.width);
129 return 0;
130}
131
132#ifdef HAVE_OPENCL
133int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
134{
135 dt_iop_roi_t roi_in = piece->roi_in;
136 dt_iop_roi_t roi_out = piece->roi_out;
137 // ROI (x,y) are not used here since we don't crop but only scale.
138 // Leaving them will offset the result, which is not what we want.
139 roi_in.x = 0;
140 roi_in.y = 0;
141 roi_out.x = 0;
142 roi_out.y = 0;
143 const int devid = pipe->devid;
144 cl_int err = -999;
145
146 err = dt_iop_clip_and_zoom_roi_cl(devid, dev_out, dev_in, &roi_out, &roi_in);
147 if(err != CL_SUCCESS) goto error;
148
149 return TRUE;
150
151error:
152 dt_print(DT_DEBUG_OPENCL, "[opencl_finalscale] couldn't enqueue kernel! %d\n", err);
153 return FALSE;
154}
155#endif
156
157
160{
161 // Export always upscales at the end; thumbnails never do. Both are decided by the pipe
162 // type alone, so settle them before reading anything off dev: this callback runs on the
163 // pipeline thread, and for those two pipe types `dev` is a headless, throwaway one whose
164 // viewport fields still hold their calloc zero -- the old predicate read them and got the
165 // right answer only because its remaining clauses happened to decide first.
166 if(pipe->type == DT_DEV_PIXELPIPE_EXPORT)
167 {
168 piece->enabled = TRUE;
169 return;
170 }
172 {
173 piece->enabled = FALSE;
174 return;
175 }
176
177 // Darkroom pipes only. Depending on ROI zoom level, we may need to enable finalscale so
178 // the pipeline runs at most at 100%, for pixel-level accuracy, and we upscale at the end.
179 // This is important for consistency with exports.
180 // The pipe's latched snapshot, not a live read off dev: this runs on the pipeline thread, and
181 // piece->enabled must agree with the ROI the same iteration planned.
183 const float darkroom_zoom = request.scaling * request.natural_scale;
184 piece->enabled = (darkroom_zoom > 1.f)
185 || (dt_conf_get_int("darkroom/render_size") != 1 && darkroom_zoom != 1.f);
186}
187
189{
191 piece->data_size = sizeof(dt_iop_finalscale_data_t);
192 piece->enabled = (pipe->type == DT_DEV_PIXELPIPE_EXPORT);
193}
194
196{
197 dt_free_align(piece->data);
198 piece->data = NULL;
199}
200
202{
203 self->params = calloc(1, sizeof(dt_iop_finalscale_params_t));
204 self->default_params = calloc(1, sizeof(dt_iop_finalscale_params_t));
205 self->default_enabled = 1;
206 self->hide_enable_button = 1;
208}
209
211{
212 dt_free(self->params);
213 dt_free(self->default_params);
214}
215
218
219
221{
222 IOP_GUI_ALLOC(finalscale);
223 self->gui->widget = gtk_label_new(NULL);
224 gtk_label_set_markup(GTK_LABEL(self->gui->widget),_("This module is used to downscale images at export time. "
225 "Moving it along the pipeline will have diffent effects on exported images. "
226 "<a href='https://ansel.photos/en/doc/modules/processing-modules/finalscale/'>Learn more</a>"));
227 gtk_widget_set_halign(self->gui->widget, GTK_ALIGN_START);
228 gtk_label_set_xalign (GTK_LABEL(self->gui->widget), 0.0f);
229 gtk_label_set_line_wrap(GTK_LABEL(self->gui->widget), TRUE);
230}
231
232// clang-format off
233// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
234// vim: shiftwidth=2 expandtab tabstop=2 cindent
235// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
236// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
@ IOP_CS_RGB
const dt_colormatrix_t dt_aligned_pixel_t out
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
void dt_iop_params_t
Definition dev_history.h:43
dt_dev_roi_request_t dt_dev_roi_request_of_pipe(const dt_dev_pixelpipe_t *pipe)
void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
Definition finalscale.c:109
int process(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition finalscale.c:117
int default_group()
Definition finalscale.c:63
void modify_roi_in(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_out, dt_iop_roi_t *roi_in)
Definition finalscale.c:75
dt_iop_finalscale_params_t dt_iop_finalscale_data_t
Definition finalscale.c:51
const char * name()
Definition finalscale.c:53
void gui_init(dt_iop_module_t *self)
Definition finalscale.c:220
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition finalscale.c:195
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition finalscale.c:68
int flags()
Definition finalscale.c:58
void init(dt_iop_module_t *self)
Definition finalscale.c:201
void commit_params(dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition finalscale.c:158
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition finalscale.c:188
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
Definition finalscale.c:133
void cleanup(dt_iop_module_t *self)
Definition finalscale.c:210
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_FLAGS_TILING_FULL_ROI
Definition imageop.h:190
@ IOP_FLAGS_NO_HISTORY_STACK
Definition imageop.h:193
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
#define IOP_GUI_ALLOC(module)
Definition imageop_gui.h:93
void dt_iop_clip_and_zoom_roi(float *out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const int32_t out_stride, const int32_t in_stride)
int dt_iop_clip_and_zoom_roi_cl(int devid, cl_mem dev_out, cl_mem dev_in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in)
void *const ovoid
const struct dt_interpolation * dt_interpolation_new(enum dt_interpolation_type type)
void dt_interpolation_resample_roi_1c(const struct dt_interpolation *itor, float *out, const dt_iop_roi_t *const roi_out, const float *const in, const dt_iop_roi_t *const roi_in)
@ DT_INTERPOLATION_USERPREF_WARP
@ DT_DEBUG_OPENCL
Definition logging.h:57
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
Definition mem_alloc.h:225
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
@ DT_DEV_PIXELPIPE_THUMBNAIL
Definition pixelpipe.h:45
@ DT_DEV_PIXELPIPE_EXPORT
Definition pixelpipe.h:42
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
The coherent set of numbers a darkroom pipe plans its ROI from.
GtkWidget * widget
Definition imageop_gui.h:47
int32_t hide_enable_button
Definition imageop.h:270
dt_iop_params_t * default_params
Definition imageop.h:333
struct dt_iop_module_gui_t * gui
Definition imageop.h:346
gboolean default_enabled
Definition imageop.h:318
int32_t params_size
Definition imageop.h:335
dt_iop_params_t * params
Definition imageop.h:333
Region of interest passed through the pixelpipe.
Definition format.h:49
double scale
Definition format.h:51
int width
Definition format.h:50
int height
Definition format.h:50