Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
useless.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010 Bruce Guenter.
4 Copyright (C) 2010-2012 johannes hanika.
5 Copyright (C) 2011 Henrik Andersson.
6 Copyright (C) 2011 Jérémy Rosen.
7 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2014 Ulrich Pegelow.
10 Copyright (C) 2015 Pedro Côrte-Real.
11 Copyright (C) 2015-2016 Roman Lebedev.
12 Copyright (C) 2018-2021 Pascal Obry.
13 Copyright (C) 2020 Aldric Renaudin.
14 Copyright (C) 2020, 2022 Diederik Ter Rahe.
15 Copyright (C) 2020-2021 Hubert Kowalski.
16 Copyright (C) 2020-2021 Ralf Brown.
17 Copyright (C) 2021 luzpaz.
18 Copyright (C) 2022 Hanno Schwalm.
19 Copyright (C) 2022 Martin Bařinka.
20 Copyright (C) 2022 Philipp Lutz.
21 Copyright (C) 2022 Sebatian Glasl.
22 Copyright (C) 2025-2026 Aurélien PIERRE.
23
24 darktable is free software: you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation, either version 3 of the License, or
27 (at your option) any later version.
28
29 darktable is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with darktable. If not, see <http://www.gnu.org/licenses/>.
36*/
37#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41// our includes go first:
42#include "widgets/bauhaus.h"
43#include "system/macros.h"
45#include "system/mem_alloc.h"
46#include "system/simd.h"
48#include "develop/imageop.h"
49#include "develop/imageop_gui.h"
51#include "iop/iop_api.h"
52
53#include <gtk/gtk.h>
54#include <stdlib.h>
55
56// This is an example implementation of an image operation module that does nothing useful.
57// It demonstrates how the different functions work together. To build your own module,
58// take all of the functions that are mandatory, stripping them of comments.
59// Then add only the optional functions that are required to implement the functionality
60// you need. Don't copy default implementations (hint: if you don't need to change or add
61// anything, you probably don't need the copy). Make sure you choose descriptive names
62// for your fields and variables. The ones given here are just examples; rename them.
63//
64// To have your module compile and appear in darkroom, add it to CMakeLists.txt, with
65// add_iop(useless "useless.c")
66// and to iop_order.c, in the initialisation of legacy_order & v30_order with:
67// { {XX.0f }, "useless", 0},
68
69// This is the version of the module's parameters,
70// and includes version information about compile-time dt.
71// The first released version should be 1.
73
74// TODO: some build system to support dt-less compilation and translation!
75
76// Enums used in params_t can have $DESCRIPTIONs that will be used to
77// automatically populate a combobox with dt_bauhaus_combobox_from_params.
78// They are also used in the history changes tooltip.
79// Combobox options will be presented in the same order as defined here.
80// These numbers must not be changed when a new version is introduced.
82{
83 DT_USELESS_NONE = 0, // $DESCRIPTION: "no"
84 DT_USELESS_FIRST = 1, // $DESCRIPTION: "first option"
85 DT_USELESS_SECOND = 2, // $DESCRIPTION: "second one"
87
89{
90 // The parameters defined here fully record the state of the module and are stored
91 // (as a serialized binary blob) into the db.
92 // Make sure everything is in here does not depend on temporary memory (pointers etc).
93 // This struct defines the layout of self->params and self->default_params.
94 // You should keep changes to this struct to a minimum.
95 // If you have to change this struct, it will break
96 // user data bases, and you have to increment the version
97 // of DT_MODULE_INTROSPECTION(VERSION) above and provide a legacy_params upgrade path!
98 //
99 // Tags in the comments get picked up by the introspection framework and are
100 // used in gui_init to set range and labels (for widgets and history)
101 // and value checks before commit_params.
102 // If no explicit init() is specified, the default implementation uses $DEFAULT tags
103 // to initialise self->default_params, which is then used in gui_init to set widget defaults.
104 //
105 // These field names are just examples; chose meaningful ones! For performance reasons, align
106 // to 4 byte boundaries (use gboolean, not bool).
107 int checker_scale; // $MIN: 0 $MAX: 10 $DEFAULT: 1 $DESCRIPTION: "size"
108 float factor; // $MIN: -5.0 $MAX: 5.0 $DEFAULT: 0
109 gboolean check; // $DESCRIPTION: "checkbox option"
110 dt_iop_useless_type_t method; // $DEFAULT: DT_USELESS_SECOND $DESCRIPTION: "parameter choices"
112
114{
115 // Whatever you need to make your gui happy and provide access to widgets between gui_init, gui_update etc.
116 // Stored in self->gui_data while in darkroom.
117 // To permanently store per-user gui configuration settings, you could use dt_conf_set/_get.
118 GtkWidget *scale, *factor, *check, *method, *extra; // this is needed by gui_update
120
122{
123 // This is optionally stored in self->global_data
124 // and can be used to alloc globally needed stuff
125 // which is needed in gui mode and during processing.
126
127 // We don't need it for this example (as for most dt plugins).
129
130// this returns a translatable name
131const char *name()
132{
133 // make sure you put all your translatable strings into _() !
134 return _("silly example");
135}
136
137// some additional flags (self explanatory i think):
138int flags()
139{
141 // optionally add IOP_FLAGS_ALLOW_TILING and implement tiling_callback
142}
143
144// where does it appear in the gui?
146{
147 return IOP_GROUP_BASIC | IOP_GROUP_TECHNICAL;
148}
149
151{
152 return IOP_CS_RGB;
153}
154
155// Whenever new fields are added to (or removed from) dt_iop_..._params_t or when their meaning
156// changes, a translation from the old to the new version must be added here.
157// A verbatim copy of the old struct definition should be copied into the routine with a _v?_t ending.
158// Since this will get very little future testing (because few developers still have very
159// old versions lying around) existing code should be changed as little as possible, if at all.
160//
161// Upgrading from an older version than the previous one should always go through all in between versions
162// (unless there was a bug) so that the end result will always be the same.
163//
164// Be careful with changes to structs that are included in _params_t
165//
166// Individually copy each existing field that is still in the new version. This is robust even if reordered.
167// If only new fields were added at the end, one call can be used:
168// memcpy(n, o, sizeof *o);
169//
170// Hardcode the default values for new fields that were added, rather than referring to default_params;
171// in future, the field may not exist anymore or the default may change. The best default for a new version
172// to replicate a previous version might not be the optimal default for a fresh image.
173//
174// FIXME: the calling logic needs to be improved to call upgrades from consecutive version in sequence.
175int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
176 void *new_params, const int new_version)
177{
178 typedef dt_iop_useless_params_t dt_iop_useless_params_v3_t; // always create copy of current so code below doesn't need to be touched
179
180 typedef struct dt_iop_useless_params_v2_t
181 {
182 int checker_scale;
183 float factor;
184 } dt_iop_useless_params_v2_t;
185
186 if(old_version == 2 && new_version == 3)
187 {
188 dt_iop_useless_params_v2_t *o = (dt_iop_useless_params_v2_t *)old_params;
189 dt_iop_useless_params_v3_t *n = (dt_iop_useless_params_v3_t *)new_params;
190
191 memcpy(n, o, sizeof *o);
192 n->check = FALSE;
193 n->method = DT_USELESS_SECOND;
194 return 0;
195 }
196
197 typedef struct dt_iop_useless_params_v1_t
198 {
199 int checker_scale;
200 } dt_iop_useless_params_v1_t;
201
202 if(old_version == 1 && new_version == 2)
203 {
204 dt_iop_useless_params_v1_t *o = (dt_iop_useless_params_v1_t *)old_params;
205 dt_iop_useless_params_v2_t *n = (dt_iop_useless_params_v2_t *)new_params;
206
207 n->checker_scale = o->checker_scale;
208 n->factor = 0.0;
209 return 0;
210 }
211 return 1;
212}
213
214static const int mask_id = 1; // key "0" is reserved for the pipe
215static const char *mask_name = "useless checkerboard";
216
218{
220 piece->data_size = sizeof(dt_iop_useless_params_t);
221}
223{
224 dt_free_align(piece->data);
225 piece->data = NULL;
226}
227
229{
230 memcpy(piece->data, p1, self->params_size);
231
232 // there is no real need for this, but if the number of masks can be changed by the user this is the way to go.
233 // otherwise we can have old stale masks floating around
234 g_hash_table_remove_all(self->raster_mask.source.masks);
235 g_hash_table_insert(self->raster_mask.source.masks, GINT_TO_POINTER(mask_id), g_strdup(mask_name));
236}
237
238#if 0
242void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
243{
244 const dt_iop_roi_t *const roi_in = &piece->roi_in;
245 const dt_iop_roi_t *const roi_out = &piece->roi_out;
246 tiling->factor = 2.0f; // input buffer + output buffer; increase if additional memory allocated
247 tiling->factor_cl = 2.0f; // same, but for OpenCL code path running on GPU
248 tiling->maxbuf = 1.0f; // largest buffer needed regardless of how tiling splits up the processing
249 tiling->maxbuf_cl = 1.0f; // same, but for running on GPU
250 tiling->overhead = 0; // number of bytes of fixed overhead
251 tiling->overlap = 0; // how many pixels do we need to access from the neighboring tile?
252 tiling->xalign = 1;
253 tiling->yalign = 1;
254}
255#endif
256
258// void modify_roi_out(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t
259// *roi_out, const dt_iop_roi_t *roi_in);
260// void modify_roi_in(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t
261// *roi_out, dt_iop_roi_t *roi_in);
262
263#if 0
266 float *points, size_t points_count)
267{
269
270 const float adjx = 0.0 * d->factor;
271 const float adjy = 0.0;
272
273 // nothing to be done if parameters are set to neutral values (no pixel shifts)
274 if (adjx == 0.0 && adjy == 0.0) return 1;
275
276 // apply the coordinate adjustment to each provided point
277 for(size_t i = 0; i < points_count * 2; i += 2)
278 {
279 points[i] -= adjx;
280 points[i + 1] -= adjy;
281 }
282
283 return 1; // return 1 on success, 0 if one or more points could not be transformed
284}
285#endif
286
287#if 0
290 float *points, size_t points_count)
291{
293
294 const float adjx = 0.0 * d->factor;
295 const float adjy = 0.0;
296
297 // nothing to be done if parameters are set to neutral values (no pixel shifts)
298 if (adjx == 0.0 && adjy == 0.0) return 1;
299
300 // apply the inverse coordinate adjustment to each provided point
301 for(size_t i = 0; i < points_count * 2; i += 2)
302 {
303 points[i] += adjx;
304 points[i + 1] += adjy;
305 }
306
307 return 1; // return 1 on success, 0 if one or more points could not be back-transformed
308}
309#endif
310
312// void distort_mask(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const float *const in,
313// float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out);
314
323int process(struct 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)
324{
325 const dt_iop_roi_t *const roi_in = &piece->roi_in;
326 const dt_iop_roi_t *const roi_out = &piece->roi_out;
327 // this is called for preview and full pipe separately, each with its own pixelpipe piece.
328 // get our data struct:
330 // the total scale is composed of scale before input to the pipeline (iscale),
331 // and the scale of the roi.
332 const float scale = dt_dev_get_module_scale(pipe, roi_in);
333 // how many colors in our buffer?
334 const size_t ch = piece->dsc_in.channels;
335
336 // most modules only support a single type of input data, so we can check whether that format has been supplied
337 // and simply pass along the data if not (setting a trouble flag to inform the user)
339
340 // we create a raster mask as an example
341 float *mask = NULL;
343 {
344 // Attempt to allocate all of the buffers we need. For this example, we need one buffer that is equal in
345 // dimensions to the output buffer, has one color channel, and has been zero'd. (See common/imagebuf.h for
346 // more details on all of the options.)
347 if (dt_iop_alloc_image_buffers(module, roi_in, roi_out,
348 1/*ch per pixel*/ | DT_IMGSZ_OUTPUT | DT_IMGSZ_FULL | DT_IMGSZ_CLEARBUF, &mask,
349 0 /* end of list of buffers to allocate */))
350 {
351 // Uh oh, we didn't have enough memory! If multiple buffers were requested, any that had already
352 // been allocated have been freed, and the module's trouble flag has been set. We can simply pass
353 // through the input image and return now, since there isn't anything else we need to clean up at
354 // this point.
355 dt_iop_copy_image_roi(ovoid, ivoid, ch, roi_in, roi_out, TRUE);
356 return 1;
357 }
358 }
359
360// iterate over all output pixels (same coordinates as input)
361#ifdef _OPENMP
362// optional: parallelize it!
363#pragma omp parallel for default(firstprivate)
364#endif
365 for(int j = 0; j < roi_out->height; j++)
366 {
367 float *in = ((float *)ivoid)
368 + (size_t)ch * roi_in->width
369 * j; // make sure to address input, output and temp buffers with size_t as we want to also
370 float *out = ((float *)ovoid) + (size_t)ch * roi_out->width * j; // correctly handle huge images
371 float *out_mask = mask ? &(mask[(size_t)roi_out->width * j]) : NULL;
372 for(int i = 0; i < roi_out->width; i++)
373 {
374 // calculate world space coordinates:
375 int wi = (roi_in->x + i) * scale, wj = (roi_in->y + j) * scale;
376 if((wi / d->checker_scale + wj / d->checker_scale) & 1)
377 {
378 for_each_channel(c, aligned(in,out)) // vectorize if possible
379 out[c] = in[c] * (1.0 - d->factor); // does this for c=0..2 or c=0..3, whichever is faster
380 if(!IS_NULL_PTR(out_mask)) out_mask[i] = 1.0;
381 }
382 else
383 {
384 copy_pixel(out, in);
385 }
386 in += ch;
387 out += ch;
388 }
389 }
390
391 // now that the mask is generated we can publish it
392 if(!IS_NULL_PTR(mask))
393 {
394 const size_t mask_size = sizeof(float) * (size_t)roi_out->width * roi_out->height;
395 const uint64_t mask_hash = dt_dev_pixelpipe_raster_mask_hash(piece, mask_id);
396 dt_pixel_cache_entry_t *mask_entry = NULL;
397 void *cache_data = NULL;
398 const int created = dt_dev_pixelpipe_cache_get(
399 mask_hash, mask_size, "useless raster mask",
400 pipe->type, TRUE, &cache_data, &mask_entry);
401
402 if(IS_NULL_PTR(cache_data) || IS_NULL_PTR(mask_entry))
403 {
404 if(created && !IS_NULL_PTR(mask_entry))
406 FALSE, mask_entry);
407 if(!IS_NULL_PTR(mask_entry))
408 {
410 FALSE, mask_entry);
411 if(created)
413 TRUE, mask_entry);
414 }
416 return 1;
417 }
418
419 if(created)
420 {
421 memcpy(cache_data, mask, mask_size);
423 FALSE, mask_entry);
424 }
425 dt_dev_pixelpipe_t *mutable_pipe = (dt_dev_pixelpipe_t *)pipe;
426 g_array_append_val(mutable_pipe->raster_mask_hashes, mask_hash);
428 }
429}
430
433{
434 // Allocates memory for a module instance and fills default_params.
435 // If this callback is not provided, the standard implementation in
436 // dt_iop_default_init is used, which looks at the $DEFAULT introspection tags
437 // in the comments of the params_t struct definition.
438 // An explicit implementation of init is only required if not all fields are
439 // fully supported by dt_iop_default_init, for example arrays with non-identical values.
440 // In that case, dt_iop_default_init can be called first followed by additional initialisation.
441 // The values in params will not be used and default_params can be overwritten by
442 // reload_params on a per-image basis.
443 dt_iop_default_init(module);
444
445 // Any non-default settings; for example disabling the on/off switch:
446 module->hide_enable_button = 1;
447 // To make this work correctly, you also need to hide the widgets, otherwise moving one
448 // would enable the module anyway. The standard way is to set up a gtk_stack and show
449 // the page that only has a label with an explanatory text when the module can't be used.
450}
451
453{
454 module->data = malloc(sizeof(dt_iop_useless_global_data_t));
455}
456
458{
459 // Releases any memory allocated in init(module)
460 // Implement this function explicitly if the module allocates additional memory besides (default_)params.
461 // this is rare.
462 dt_free(module->params);
463 dt_free(module->default_params);
464}
465
467{
468 dt_free(module->data);
469}
470
473{
474 // this is important to avoid cycles!
475 if(dt_gui_widgets_suppressed()) return;
476
479
480 float extra = dt_bauhaus_slider_get(w);
481
482 // Setting a widget value will trigger a callback that will update params.
483 // If this is not desirable (because it might result in a cycle) then use
484 // dt_gui_freeze_begin();
485 dt_bauhaus_slider_set(g->factor, p->factor + extra);
486 // and reverse with dt_gui_freeze_end();
487
488 // If any params updated directly, not via a callback, then
489 // let core know of the changes
490 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
491}
492
494void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
495{
496 // If defined, this gets called when any of the introspection based widgets
497 // (created with dt_bauhaus_..._from_params) are changed.
498 // The updated value from the widget is already set in params.
499 // any additional side-effects can be achieved here.
502
503 // Test which widget was changed.
504 // If allowing IS_NULL_PTR(w), this can be called from gui_update, so that
505 // gui configuration adjustments only need to be dealt with once, here.
506 if(IS_NULL_PTR(w) || w == g->method)
507 {
508 gtk_widget_set_visible(g->check, p->method == DT_USELESS_SECOND);
509 }
510
511 // Widget configurations that don't depend any any current params values should
512 // go in reload_defaults (if they depend on the image) or gui_init.
513}
514
516{
519
520 // This automatically gets called when any of the color pickers set up with
521 // dt_color_picker_new in gui_init is used. If there is more than one,
522 // check which one is active first.
523 if(picker == g->factor)
524 {
525 p->factor = self->picked_color[1];
526 }
527
528 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
529 dt_control_queue_redraw_widget(self->widget);
530}
531
534{
535 // This gets called when switching to darkroom, with each image change or when
536 // a different history item is selected.
537 // Here, all the widgets need to be set to the current values in param.
538 //
539 // Note, this moves data from params -> gui. All fields at same time.
540 // The opposite direction, gui -> params happens one field at a time, for example
541 // when the user manipulates a slider. It is handled by gui_changed (and the
542 // automatic callback) for introspection based widgets or by the explicit callback
543 // set up manually (see example of extra_callback above).
547
548 // slider reset value follows the per-image default computed by reload_defaults()
549 dt_bauhaus_slider_set_default(g->scale, d->checker_scale);
550 dt_bauhaus_slider_set(g->scale, p->checker_scale);
551
552 // For introspection based widgets (dt_bauhaus_slider_from_params) do not use
553 // any transformations here (for example *100 for percentages) because that will
554 // break enforcement of $MIN/$MAX.
555 // Use dt_bauhaus_slider_set_factor/offset in gui_init instead.
556 dt_bauhaus_slider_set(g->factor, p->factor);
557
558 // dt_bauhaus_toggle_from_params creates a standard gtk_toggle_button.
559 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->check), p->check);
560
561 // Use set_from_value to correctly handle out of order values.
562 dt_bauhaus_combobox_set_from_value(g->method, p->method);
563
564 // Any configuration changes to the gui that depend on field values should be done here,
565 // or can be done in gui_changed which can then be called from here with IS_NULL_PTR(widget).
566 gui_changed(self, NULL, NULL);
567}
568
572{
573 // This only has to be provided if module settings or default_params need to depend on
574 // image type (raw?) or exif data.
575 // Make sure to always reset to the default for non-special cases, otherwise the override
576 // will stick when switching to another image.
578
579 // As an example, switch off for non-raw images. The enable button was already hidden in init().
580 if(!dt_image_is_raw(&module->dev->image_storage))
581 {
582 module->default_enabled = 0;
583 }
584 else
585 {
586 module->default_enabled = 1;
587 d->checker_scale = 3; // something dependent on exif, for example.
588 }
589
590 // Widget defaults that depend on these per-image default_params (e.g. the slider reset value)
591 // are applied in gui_update(), which runs on the GUI thread when the widgets exist. Do NOT touch
592 // widgets here: reload_defaults() also runs on export/thumbnail devs that have no gui_data, and
593 // off the GUI thread.
594}
595
601gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
602{
603 // This needs to be enabled for raw images, disabled for other images.
604 // There is no messing around.
605
606 const int is_raw = dt_image_is_raw(&self->dev->image_storage);
607 gboolean enable = current_state;
608
609 if(is_raw && (!self->enabled))
610 {
611 enable = TRUE;
612 }
613 else if(!is_raw && (self->enabled))
614 {
615 enable = FALSE;
616 }
617 return enable;
618}
619
620
622{
623 // Allocates memory for the module's user interface in the darkroom and
624 // sets up the widgets in it.
625 //
626 // self->widget needs to be set to the top level widget.
627 // This can be a (vertical) box, a grid or even a notebook. Modules that are
628 // disabled for certain types of images (for example non-raw) may use a stack
629 // where one of the pages contains just a label explaining why it is disabled.
630 //
631 // Widgets that are directly linked to a field in params_t may be set up using the
632 // dt_bauhaus_..._from_params family. They take a string with the field
633 // name in the params_t struct definition. The $MIN, $MAX and $DEFAULT tags will be
634 // used to set up the widget (slider) ranges and default values and the $DESCRIPTION
635 // is used as the widget label.
636 //
637 // The _from_params calls also set up an automatic callback that updates the field in params
638 // whenever the widget is changed. In addition, gui_changed is called, if it exists,
639 // so that any other required changes, to dependent fields or to gui widgets, can be made.
640 //
641 // Whenever self->params changes (switching images or history) the widget values have to
642 // be updated in gui_update.
643 //
644 // Do not set the value of widgets or configure them depending on field values here;
645 // this should be done in gui_update (or gui_changed or individual widget callbacks)
646 //
647 // If any default values for (slider) widgets or options (in comboboxes) depend on the
648 // type of image, then the widgets have to be updated in reload_params.
650
651 // If the first widget is created using a _from_params call, self->widget does not have to
652 // be explicitly initialised, as a new vertical box will be created automatically.
653 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
654
655 // Linking a slider to an integer will make it take only whole numbers (step=1).
656 // The new slider is added to self->widget
657 g->scale = dt_bauhaus_slider_from_params(self, "checker_scale");
658
659 // If the field name should be used as label too, it does not need a $DESCRIPTION;
660 // mark it for translation here using N_()
661 //
662 // A colorpicker can be attached to a slider, as here, or put standalone in a box.
663 // When a color is picked, color_picker_apply is called with either the slider or the
664 // button that triggered it.
666 dt_bauhaus_slider_from_params(self, N_("factor")));
667 // The initial slider range can be reduced from the introspection $MIN - $MAX
668 dt_bauhaus_slider_set_soft_range(g->factor, 0.5f, 1.5f);
669 // The default step is range/100, but can be changed here
670 dt_bauhaus_slider_set_step(g->factor, .1);
672 // Additional parameters determine how the value will be shown.
673 dt_bauhaus_slider_set_format(g->factor, "%");
674 // For a percentage, use factor 100.
675 dt_bauhaus_slider_set_factor(g->factor, -100.0f);
676 dt_bauhaus_slider_set_offset(g->factor, 100.0f);
677 // Tooltips explain the otherwise compact interface
678 gtk_widget_set_tooltip_text(g->factor, _("adjust factor"));
679
680 // A combobox linked to struct field will be filled with the values and $DESCRIPTIONs
681 // in the struct definition, in the same order. The automatic callback will put the
682 // enum value, not the position within the combobox list, in the field.
683 g->method = dt_bauhaus_combobox_from_params(self, "method");
684
685 g->check = dt_bauhaus_toggle_from_params(self, "check");
686
687 // Any widgets that are _not_ directly linked to a field need to have a custom callback
688 // function set up to respond to the "value-changed" signal.
689 g->extra = dt_bauhaus_slider_new_with_range(dt_bauhaus_get_global(), DT_GUI_MODULE(self), -0.5, 0.5, 0, 0, 2);
690 dt_bauhaus_widget_set_label(g->extra, N_("extra"));
691 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->extra), TRUE, TRUE, 0);
692 g_signal_connect(G_OBJECT(g->extra), "value-changed", G_CALLBACK(extra_callback), self);
693}
694
696{
697 // This only needs to be provided if gui_init allocates any memory or resources besides
698 // self->widget and gui_data_t. The default function (if an explicit one isn't provided here)
699 // takes care of gui_data_t (and gtk destroys the widget anyway). If you override the default,
700 // you have to do whatever you have to do, and also call IOP_GUI_FREE to clean up gui_data_t.
701
703}
704
706// void gui_post_expose(dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx,
707// int32_t pointery);
708// int mouse_moved(dt_iop_module_t *self, double x, double y, double pressure, int which);
709// int button_pressed(dt_iop_module_t *self, double x, double y, double pressure, int which, int type,
710// uint32_t state);
711// int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state);
712// int scrolled(dt_iop_module_t *self, double x, double y, int up, uint32_t state);
713
714// clang-format off
715// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
716// vim: shiftwidth=2 expandtab tabstop=2 cindent
717// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
718// clang-format on
int distort_transform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
Definition ashift.c:999
int distort_backtransform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *points, size_t points_count)
Definition ashift.c:1030
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
Definition bauhaus.c:1498
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
Definition bauhaus.c:3343
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
Definition bauhaus.c:1491
float dt_bauhaus_slider_get(GtkWidget *widget)
Definition bauhaus.c:3280
gboolean dt_bauhaus_combobox_set_from_value(GtkWidget *widget, int value)
Definition bauhaus.c:2119
void dt_bauhaus_slider_set_offset(GtkWidget *widget, float offset)
Definition bauhaus.c:3430
void dt_bauhaus_slider_set_step(GtkWidget *widget, float val)
Definition bauhaus.c:3357
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3331
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1504
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
Definition bauhaus.c:1632
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3407
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
Definition bauhaus.c:3423
@ IOP_CS_RGB
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
@ DT_COLOR_PICKER_AREA
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
gboolean dt_image_is_raw(const dt_image_t *img)
void dt_control_queue_redraw_widget(GtkWidget *widget)
threadsafe request of redraw of specific widget. Use this function if you need to redraw a specific w...
Definition control.c:969
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
Definition darktable.c:646
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:43
#define DT_GUI_MODULE(x)
static gboolean enable(const dt_image_t *image)
Definition highlights.c:879
int dt_iop_alloc_image_buffers(struct dt_iop_module_t *const module, const struct dt_iop_roi_t *const roi_in, const struct dt_iop_roi_t *const roi_out,...)
Definition imagebuf.c:35
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
Definition imagebuf.c:163
#define DT_IMGSZ_CLEARBUF
Definition imagebuf.h:62
#define DT_IMGSZ_OUTPUT
Definition imagebuf.h:58
#define DT_IMGSZ_FULL
Definition imagebuf.h:65
gboolean dt_iop_is_raster_mask_used(dt_iop_module_t *module, int id)
Definition imageop.c:1825
void dt_iop_default_init(dt_iop_module_t *module)
Definition imageop.c:308
float dt_dev_get_module_scale(const dt_dev_pixelpipe_t *const pipe, const dt_iop_roi_t *const roi_in)
Definition imageop.c:134
@ IOP_FLAGS_INCLUDE_IN_STYLES
Definition imageop.h:185
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:186
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
GtkWidget * dt_bauhaus_toggle_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
#define IOP_GUI_FREE
Definition imageop_gui.h:96
#define IOP_GUI_ALLOC(module)
Definition imageop_gui.h:93
void *const ovoid
float *const restrict const size_t const size_t ch
#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_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.
const float factor
Definition pdf.h:91
uint64_t dt_dev_pixelpipe_raster_mask_hash(const dt_dev_pixelpipe_iop_t *piece, const int raster_mask_id)
Definition pixelpipe.c:53
void dt_dev_pixelpipe_cache_wrlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
void dt_dev_pixelpipe_cache_ref_count_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
int dt_dev_pixelpipe_cache_get(const uint64_t hash, const size_t size, const char *name, const int id, const gboolean alloc, void **data, dt_pixel_cache_entry_t **entry)
Get a cache line from the cache.
int dt_dev_pixelpipe_cache_remove(const gboolean force, dt_pixel_cache_entry_t *cache_entry)
Arbitrarily remove the cache entry matching hash. Entries having a reference count > 0 (inter-thread ...
#define dt_pixelpipe_cache_free_align(mem)
static void copy_pixel(float *const __restrict__ out, const float *const __restrict__ in)
Definition simd.h:217
#define for_each_channel(_var,...)
Definition simd.h:87
unsigned __int64 uint64_t
Definition strptime.c:75
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
gboolean store_all_raster_masks
GArray * raster_mask_hashes
dt_image_t image_storage
Definition develop.h:225
unsigned int channels
Definition format.h:83
dt_iop_global_data_t * data
Definition imageop.h:238
dt_iop_params_t * default_params
Definition imageop.h:333
GHashTable * masks
Definition imageop.h:362
struct dt_develop_t * dev
Definition imageop.h:311
gboolean enabled
Definition imageop.h:313
struct dt_iop_module_t::@23::@24 source
struct dt_iop_module_t::@23 raster_mask
int32_t params_size
Definition imageop.h:335
dt_aligned_pixel_t picked_color
Definition imageop.h:287
dt_iop_params_t * params
Definition imageop.h:333
Region of interest passed through the pixelpipe.
Definition format.h:49
int width
Definition format.h:50
int height
Definition format.h:50
dt_iop_useless_type_t method
Definition useless.c:110
#define __DT_CLONE_TARGETS__
void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
Definition atrous.c:664
void init(dt_iop_module_t *module)
Definition useless.c:432
int default_group()
Definition useless.c:145
__DT_CLONE_TARGETS__ int process(struct 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 useless.c:323
void reload_defaults(dt_iop_module_t *module)
Definition useless.c:571
static const int mask_id
Definition useless.c:214
dt_iop_useless_type_t
Definition useless.c:82
@ DT_USELESS_NONE
Definition useless.c:83
@ DT_USELESS_FIRST
Definition useless.c:84
@ DT_USELESS_SECOND
Definition useless.c:85
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
Definition useless.c:533
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition useless.c:217
void cleanup(dt_iop_module_t *module)
Definition useless.c:457
const char * name()
Definition useless.c:131
void gui_init(dt_iop_module_t *self)
Definition useless.c:621
static void extra_callback(GtkWidget *w, dt_iop_module_t *self)
Definition useless.c:472
commit_params(dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition useless.c:228
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
Definition useless.c:494
void gui_cleanup(dt_iop_module_t *self)
Definition useless.c:695
void cleanup_global(dt_iop_module_so_t *module)
Definition useless.c:466
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition useless.c:150
int flags()
Definition useless.c:138
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
Definition useless.c:601
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition useless.c:222
void init_global(dt_iop_module_so_t *module)
Definition useless.c:452
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition useless.c:515
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
Definition useless.c:175
static const char * mask_name
Definition useless.c:215
gboolean dt_gui_widgets_suppressed(void)
#define DT_GUI_BOX_SPACING