Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
flip.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011-2013, 2016 johannes hanika.
4 Copyright (C) 2012 parafin.
5 Copyright (C) 2012 Richard Wonka.
6 Copyright (C) 2012-2014, 2016, 2018-2019 Tobias Ellinghaus.
7 Copyright (C) 2012, 2014 Ulrich Pegelow.
8 Copyright (C) 2013, 2020-2021 Aldric Renaudin.
9 Copyright (C) 2013-2016 Roman Lebedev.
10 Copyright (C) 2013 Simon Spannagel.
11 Copyright (C) 2013 Thomas Pryds.
12 Copyright (C) 2014 Dan Torop.
13 Copyright (C) 2015, 2018-2022 Pascal Obry.
14 Copyright (C) 2015 Pedro Côrte-Real.
15 Copyright (C) 2017 Heiko Bauke.
16 Copyright (C) 2018-2026 Aurélien PIERRE.
17 Copyright (C) 2018 Edgardo Hoszowski.
18 Copyright (C) 2018 Maurizio Paglia.
19 Copyright (C) 2018 rawfiner.
20 Copyright (C) 2019 Jacques Le Clerc.
21 Copyright (C) 2020 Diederik Ter Rahe.
22 Copyright (C) 2020 Marco.
23 Copyright (C) 2020-2021 Ralf Brown.
24 Copyright (C) 2022 Hanno Schwalm.
25 Copyright (C) 2022 Martin Bařinka.
26 Copyright (C) 2022 Philipp Lutz.
27 Copyright (C) 2023 Alynx Zhou.
28 Copyright (C) 2025 Guillaume Stutin.
29
30 darktable is free software: you can redistribute it and/or modify
31 it under the terms of the GNU General Public License as published by
32 the Free Software Foundation, either version 3 of the License, or
33 (at your option) any later version.
34
35 darktable is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details.
39
40 You should have received a copy of the GNU General Public License
41 along with darktable. If not, see <http://www.gnu.org/licenses/>.
42*/
43#ifdef HAVE_CONFIG_H
44#include "config.h"
45#endif
47#include "database/database.h"
49#include <assert.h>
50#include "system/openmp.h"
51#include "system/mem_alloc.h"
52#include "common/logging.h"
54#include <gdk/gdkkeysyms.h>
55#include <gtk/gtk.h>
56#include <inttypes.h>
57#include <math.h>
58#include <stdlib.h>
59#include <string.h>
60
62#include "common/opencl.h"
63#include "develop/develop.h"
65#include "develop/imageop.h"
66#include "develop/imageop_gui.h"
67#include "develop/imageop_gui.h"
68
69#include "gui/presets.h"
70#include "iop/iop_api.h"
71
73
74typedef struct dt_iop_flip_params_t
75{
78
80
85
86// helper to count corners in for loops:
87static void get_corner(const int32_t *aabb, const int i, int32_t *p)
88{
89 for(int k = 0; k < 2; k++) p[k] = aabb[2 * ((i >> k) & 1) + k];
90}
91
92static void adjust_aabb(const int32_t *p, int32_t *aabb)
93{
94 aabb[0] = MIN(aabb[0], p[0]);
95 aabb[1] = MIN(aabb[1], p[1]);
96 aabb[2] = MAX(aabb[2], p[0]);
97 aabb[3] = MAX(aabb[3], p[1]);
98}
99
100const char *name()
101{
102 return _("orientation");
103}
104
105const char *aliases()
106{
107 return _("rotation|flip");
108}
109
111{
112 return IOP_GROUP_TECHNICAL;
113}
114
116{
117 return IOP_TAG_DISTORT;
118}
119
124
126{
127 return IOP_CS_RGB;
128}
129
130const char **description(struct dt_iop_module_t *self)
131{
132 return dt_iop_set_description(self, _("flip or rotate image by step of 90 degrees"), _("corrective"),
133 _("linear, RGB, scene-referred"), _("geometric, RGB"),
134 _("linear, RGB, scene-referred"));
135}
136
146 dt_image_orientation_t user_orientation)
147{
148 // Fast path: no coordinate swap needed
149 if(!(user_orientation & ORIENTATION_SWAP_XY))
150 {
151 return raw_orientation ^ user_orientation;
152 }
153
154 // When user requests XY swap, we need to swap X/Y flip bits in raw orientation
155 // Use bit manipulation for optimal performance
156 dt_image_orientation_t corrected = raw_orientation;
157
158 // Extract flip bits from raw orientation
159 const dt_image_orientation_t raw_flip_x = raw_orientation & ORIENTATION_FLIP_X;
160 const dt_image_orientation_t raw_flip_y = raw_orientation & ORIENTATION_FLIP_Y;
161
162 // Clear existing flip bits and set swapped versions
163 corrected &= ~(ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y);
164 corrected |= (raw_flip_y << 1) | (raw_flip_x >> 1); // Swap X↔Y bits efficiently
165
166 // Preserve original XY swap bit if it was set
167 corrected |= (raw_orientation & ORIENTATION_SWAP_XY);
168
169 // Apply user transformation via XOR
170 return corrected ^ user_orientation;
171}
172
173int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version,
174 void *new_params, const int new_version)
175{
176 if(old_version == 1 && new_version == 2)
177 {
178 typedef struct dt_iop_flip_params_v1_t
179 {
180 int32_t orientation;
181 } dt_iop_flip_params_v1_t;
182
183 const dt_iop_flip_params_v1_t *old = (dt_iop_flip_params_v1_t *)old_params;
186
187 *n = *d; // start with a fresh copy of default parameters
188
189 // we might be called from presets update infrastructure => there is no image
190 dt_image_orientation_t image_orientation = ORIENTATION_NONE;
191
192 if(self->dev)
193 image_orientation = dt_image_orientation(&self->dev->image_storage);
194
195 n->orientation = merge_two_orientations(image_orientation,
196 (dt_image_orientation_t)(old->orientation));
197
198 return 0;
199 }
200 return 1;
201}
202
203static void backtransform(const int32_t *x, int32_t *o, const dt_image_orientation_t orientation, int32_t iw,
204 int32_t ih)
205{
206 if(orientation & ORIENTATION_SWAP_XY)
207 {
208 o[1] = x[0];
209 o[0] = x[1];
210 const int32_t tmp = iw;
211 iw = ih;
212 ih = tmp;
213 }
214 else
215 {
216 o[0] = x[0];
217 o[1] = x[1];
218 }
219 if(orientation & ORIENTATION_FLIP_X)
220 {
221 o[0] = iw - o[0] - 1;
222 }
223 if(orientation & ORIENTATION_FLIP_Y)
224 {
225 o[1] = ih - o[1] - 1;
226 }
227}
228
229/* --- the shared geometry core ----------------------------------------------------------
230 *
231 * The ONE place flip's orientation is resolved and the ONE place its size map is expressed.
232 * commit_params() and modify_roi_out() use them, and so does geometry_record() for the
233 * pixel-less geometry service (develop/geometry/geometry.h).
234 */
235
244{
245 if(p->orientation == ORIENTATION_NULL) return dt_image_orientation(&self->dev->image_storage);
246 return p->orientation;
247}
248
250static void _flip_map_size(const dt_image_orientation_t orientation, const dt_iop_roi_t *const roi_in,
251 dt_iop_roi_t *roi_out)
252{
253 *roi_out = *roi_in;
254
255 // transform whole buffer roi
256 if(orientation & ORIENTATION_SWAP_XY)
257 {
258 roi_out->width = roi_in->height;
259 roi_out->height = roi_in->width;
260 }
261}
262
264 float *const restrict points, size_t points_count)
265{
266 // if (!self->enabled) return 2;
267 const dt_iop_flip_data_t *d = (dt_iop_flip_data_t *)piece->data;
268
269 // nothing to be done if parameters are set to neutral values (no flip or swap)
270 if (d->orientation == 0) return 1;
271 __OMP_PARALLEL_FOR__(if(points_count > 500))
272 for(size_t i = 0; i < points_count * 2; i += 2)
273 {
274 float x = points[i];
275 float y = points[i + 1];
276 if(d->orientation & ORIENTATION_FLIP_X) x = piece->buf_in.width - points[i];
277 if(d->orientation & ORIENTATION_FLIP_Y) y = piece->buf_in.height - points[i + 1];
278 if(d->orientation & ORIENTATION_SWAP_XY)
279 {
280 const float yy = y;
281 y = x;
282 x = yy;
283 }
284 points[i] = x;
285 points[i + 1] = y;
286 }
287
288 return 1;
289}
291 float *const restrict points, size_t points_count)
292{
293 // if (!self->enabled) return 2;
294 const dt_iop_flip_data_t *d = (dt_iop_flip_data_t *)piece->data;
295
296 // nothing to be done if parameters are set to neutral values (no flip or swap)
297 if (d->orientation == 0) return 1;
298 __OMP_PARALLEL_FOR__(if(points_count > 500))
299 for(size_t i = 0; i < points_count * 2; i += 2)
300 {
301 float x, y;
302 if(d->orientation & ORIENTATION_SWAP_XY)
303 {
304 y = points[i];
305 x = points[i + 1];
306 }
307 else
308 {
309 x = points[i];
310 y = points[i + 1];
311 }
312 if(d->orientation & ORIENTATION_FLIP_X) x = piece->buf_in.width - x;
313 if(d->orientation & ORIENTATION_FLIP_Y) y = piece->buf_in.height - y;
314
315 points[i] = x;
316 points[i + 1] = y;
317 }
318
319 return 1;
320}
321
322void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece,
323 const float *const in, float *const out, const dt_iop_roi_t *const roi_in,
324 const dt_iop_roi_t *const roi_out)
325{
326 (void)pipe;
327 const dt_iop_flip_data_t *d = (dt_iop_flip_data_t *)piece->data;
328
329 const int bpp = sizeof(float);
330 const int stride = bpp * roi_in->width;
331
332 dt_imageio_flip_buffers((char *)out, (const char *)in, bpp, roi_in->width, roi_in->height,
333 roi_in->width, roi_in->height, stride, d->orientation);
334}
335
336// 1st pass: how large would the output be, given this input roi?
337// this is always called with the full buffer before processing.
338void modify_roi_out(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe,
339 struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out,
340 const dt_iop_roi_t *roi_in)
341{
342 const dt_iop_flip_data_t *d = (dt_iop_flip_data_t *)piece->data;
343 _flip_map_size(d->orientation, roi_in, roi_out);
344}
345
346// 2nd pass: which roi would this operation need as input to fill the given output region?
347void modify_roi_in(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe,
348 struct dt_dev_pixelpipe_iop_t *piece,
349 const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in)
350{
351 const dt_iop_flip_data_t *d = (dt_iop_flip_data_t *)piece->data;
352 *roi_in = *roi_out;
353 // transform aabb back to roi_in
354
355 // this aabb contains all valid points (thus the -1)
356 int32_t p[2], o[2];
357 int32_t aabb[4] = { roi_out->x, roi_out->y, roi_out->x + roi_out->width - 1, roi_out->y + roi_out->height - 1 };
358 int32_t aabb_in[4] = { INT_MAX, INT_MAX, INT_MIN, INT_MIN };
359 for(int c = 0; c < 4; c++)
360 {
361 // get corner points of roi_out
362 get_corner(aabb, c, p);
363 // backtransform aabb
364 backtransform(p, o, d->orientation, piece->buf_out.width * roi_out->scale,
365 piece->buf_out.height * roi_out->scale);
366 // transform to roi_in space, get aabb.
367 adjust_aabb(o, aabb_in);
368 }
369
370 // adjust roi_in to minimally needed region
371 roi_in->x = aabb_in[0];
372 roi_in->y = aabb_in[1];
373 // to convert valid points to widths, we need to add one
374 roi_in->width = aabb_in[2] - aabb_in[0] + 1;
375 roi_in->height = aabb_in[3] - aabb_in[1] + 1;
376
377 // sanity check.
378 float w = piece->buf_in.width * roi_out->scale;
379 float h = piece->buf_in.height * roi_out->scale;
380 roi_in->x = CLAMP(roi_in->x, 0, (int)floorf(w));
381 roi_in->y = CLAMP(roi_in->y, 0, (int)floorf(h));
382 roi_in->width = CLAMP(roi_in->width, 1, (int)ceilf(w) - roi_in->x);
383 roi_in->height = CLAMP(roi_in->height, 1, (int)ceilf(h) - roi_in->y);
384}
385
386// 3rd (final) pass: you get this input region (may be different from what was requested above),
387// do your best to fill the output region!
388int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
389 void *const ovoid)
390{
391 const dt_iop_roi_t *const roi_in = &piece->roi_in;
392 const dt_iop_flip_data_t *d = (dt_iop_flip_data_t *)piece->data;
393
394 const int bpp = sizeof(float) * piece->dsc_in.channels;
395 const int stride = bpp * roi_in->width;
396
397 dt_imageio_flip_buffers((char *)ovoid, (const char *)ivoid, bpp, roi_in->width, roi_in->height,
398 roi_in->width, roi_in->height, stride, d->orientation);
399 return 0;
400}
401
402#ifdef HAVE_OPENCL
403int 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)
404{
405 const dt_iop_roi_t *const roi_in = &piece->roi_in;
406 const dt_iop_flip_data_t *data = (dt_iop_flip_data_t *)piece->data;
408 cl_int err = -999;
409
410 const int devid = pipe->devid;
411 const int width = roi_in->width;
412 const int height = roi_in->height;
413 const int orientation = data->orientation;
414
415 const size_t sizes[] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
416
417 dt_opencl_set_kernel_arg(devid, gd->kernel_flip, 0, sizeof(cl_mem), (void *)&dev_in);
418 dt_opencl_set_kernel_arg(devid, gd->kernel_flip, 1, sizeof(cl_mem), (void *)&dev_out);
419 dt_opencl_set_kernel_arg(devid, gd->kernel_flip, 2, sizeof(int), (void *)&width);
420 dt_opencl_set_kernel_arg(devid, gd->kernel_flip, 3, sizeof(int), (void *)&height);
421 dt_opencl_set_kernel_arg(devid, gd->kernel_flip, 4, sizeof(int), (void *)&orientation);
422 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_flip, sizes);
423
424 if(err != CL_SUCCESS) goto error;
425 return TRUE;
426
427error:
428 dt_print(DT_DEBUG_OPENCL, "[opencl_flip] couldn't enqueue kernel! %d\n", err);
429 return FALSE;
430}
431#endif
432
434{
435 const int program = 2; // basic.cl, from programs.conf
437 self->data = gd;
438 gd->kernel_flip = dt_opencl_create_kernel(program, "flip");
439}
440
447
450{
453
454 d->orientation = _flip_resolve(self, p);
455
456 if(d->orientation == ORIENTATION_NONE) piece->enabled = 0;
457}
458
459/* --- the geometry service's view of this module (develop/geometry/geometry.h) --------- */
460
465
466static void _flip_geometry_map_size(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
467{
468 _flip_map_size(((const dt_iop_flip_geometry_t *)data)->orientation, in, out);
469}
470
471static int _flip_geometry_transform(const void *data, const dt_geometry_record_t *const record,
472 dt_geometry_chain_t *chain, float *points, size_t points_count)
473{
474 const dt_image_orientation_t orientation = ((const dt_iop_flip_geometry_t *)data)->orientation;
475 for(size_t i = 0; i < points_count * 2; i += 2)
476 {
477 float x = points[i];
478 float y = points[i + 1];
479 if(orientation & ORIENTATION_FLIP_X) x = record->in.width - points[i];
480 if(orientation & ORIENTATION_FLIP_Y) y = record->in.height - points[i + 1];
481 if(orientation & ORIENTATION_SWAP_XY)
482 {
483 const float yy = y;
484 y = x;
485 x = yy;
486 }
487 points[i] = x;
488 points[i + 1] = y;
489 }
490 return 1;
491}
492
493static int _flip_geometry_backtransform(const void *data, const dt_geometry_record_t *const record,
494 dt_geometry_chain_t *chain, float *points, size_t points_count)
495{
496 const dt_image_orientation_t orientation = ((const dt_iop_flip_geometry_t *)data)->orientation;
497 for(size_t i = 0; i < points_count * 2; i += 2)
498 {
499 float x = points[i];
500 float y = points[i + 1];
501 if(orientation & ORIENTATION_SWAP_XY)
502 {
503 const float yy = y;
504 y = x;
505 x = yy;
506 }
507 if(orientation & ORIENTATION_FLIP_X) x = record->in.width - x;
508 if(orientation & ORIENTATION_FLIP_Y) y = record->in.height - y;
509 points[i] = x;
510 points[i + 1] = y;
511 }
512 return 1;
513}
514
520
521gboolean geometry_record(dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
522{
523 const dt_image_orientation_t orientation
524 = _flip_resolve(self, (const dt_iop_flip_params_t *)params);
525
526 /* ORIENTATION_NONE is how commit_params() clears piece->enabled: an enabled flip module whose
527 * resolved orientation is a no-op contributes nothing to the pipe, and must contribute nothing
528 * here either. Published (so the roster is satisfied) with no vtable, which the chain reads as
529 * identity -- the same thing a disabled piece is. */
530 if(orientation == ORIENTATION_NONE) return TRUE;
531
533 if(IS_NULL_PTR(data)) return FALSE;
534 data->orientation = orientation;
535
536 record->data = data;
537 record->free_data = dt_free_gpointer;
538 record->vtable = &_flip_geometry_vtable;
539 return TRUE;
540}
541
543{
544 piece->data = dt_calloc_align(sizeof(dt_iop_flip_data_t));
545 piece->data_size = sizeof(dt_iop_flip_data_t);
546}
547
549{
550 dt_free_align(piece->data);
551 piece->data = NULL;
552}
553
555{
558
559 p.orientation = ORIENTATION_NULL;
560 dt_gui_presets_add_generic(_("autodetect"), self->op,
561 self->version(), &p, sizeof(p), 1);
562 dt_gui_presets_update_autoapply(_("autodetect"), self->op, self->version(), 1);
563
564 p.orientation = ORIENTATION_NONE;
565 dt_gui_presets_add_generic(_("no rotation"), self->op,
566 self->version(), &p, sizeof(p), 1);
567
568 p.orientation = ORIENTATION_FLIP_HORIZONTALLY;
569 dt_gui_presets_add_generic(_("flip horizontally"), self->op,
570 self->version(), &p, sizeof(p), 1);
571
572 p.orientation = ORIENTATION_FLIP_VERTICALLY;
573 dt_gui_presets_add_generic(_("flip vertically"), self->op,
574 self->version(), &p, sizeof(p), 1);
575
576 p.orientation = ORIENTATION_ROTATE_CW_90_DEG;
577 dt_gui_presets_add_generic(_("rotate by -90 degrees"), self->op,
578 self->version(), &p, sizeof(p), 1);
579
580 p.orientation = ORIENTATION_ROTATE_CCW_90_DEG;
581 dt_gui_presets_add_generic(_("rotate by 90 degrees"), self->op,
582 self->version(), &p, sizeof(p), 1);
583
584 p.orientation = ORIENTATION_ROTATE_180_DEG;
585 dt_gui_presets_add_generic(_("rotate by 180 degrees"), self->op,
586 self->version(), &p, sizeof(p), 1);
587
589}
590
592{
594
595 d->orientation = ORIENTATION_NULL;
596
597 self->default_enabled = 1;
598
600 && self->dev->image_storage.legacy_flip.user_flip != 0xff)
601 {
602 // The legacy flip bits only apply when the image has no flip history of its own.
604 {
605 // convert the old legacy flip bits to a proper parameter set:
606 d->orientation
609 }
610 }
611}
612
613static void do_rotate(dt_iop_module_t *self, uint32_t cw)
614{
616 dt_image_orientation_t orientation = p->orientation;
617
618 if(orientation == ORIENTATION_NULL) orientation = dt_image_orientation(&self->dev->image_storage);
619
620 if(cw == 0)
621 {
622 if(orientation & ORIENTATION_SWAP_XY)
623 orientation ^= ORIENTATION_FLIP_Y;
624 else
625 orientation ^= ORIENTATION_FLIP_X;
626 }
627 else
628 {
629 if(orientation & ORIENTATION_SWAP_XY)
630 orientation ^= ORIENTATION_FLIP_X;
631 else
632 orientation ^= ORIENTATION_FLIP_Y;
633 }
634 orientation ^= ORIENTATION_SWAP_XY;
635
636 p->orientation = orientation;
637 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
638}
639static void rotate_cw(GtkWidget *widget, dt_iop_module_t *self)
640{
641 do_rotate(self, 1);
642}
643static void rotate_ccw(GtkWidget *widget, dt_iop_module_t *self)
644{
645 do_rotate(self, 0);
646}
647static void _flip_h(GtkWidget *widget, dt_iop_module_t *self)
648{
650 dt_image_orientation_t orientation = p->orientation;
651
652 if(orientation == ORIENTATION_NULL) orientation = dt_image_orientation(&self->dev->image_storage);
653
654 if(orientation & ORIENTATION_SWAP_XY)
655 p->orientation = orientation ^ ORIENTATION_FLIP_VERTICALLY;
656 else
657 p->orientation = orientation ^ ORIENTATION_FLIP_HORIZONTALLY;
658
659 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
660}
661static void _flip_v(GtkWidget *widget, dt_iop_module_t *self)
662{
664 dt_image_orientation_t orientation = p->orientation;
665
666 if(orientation == ORIENTATION_NULL) orientation = dt_image_orientation(&self->dev->image_storage);
667
668 if(orientation & ORIENTATION_SWAP_XY)
669 p->orientation = orientation ^ ORIENTATION_FLIP_HORIZONTALLY;
670 else
671 p->orientation = orientation ^ ORIENTATION_FLIP_VERTICALLY;
672
673 dt_dev_add_history_item(self->dev, self, TRUE, TRUE);
674}
675
676void gui_init(struct dt_iop_module_t *self)
677{
678 self->gui->gui_data = NULL;
680
681 self->gui->widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
682
683 GtkWidget *label = dt_iop_gui_reset_label_new(_("transform"), self, &p->orientation, sizeof(int32_t));
684 gtk_box_pack_start(GTK_BOX(self->gui->widget), label, TRUE, TRUE, 0);
685
686 dt_iop_button_new(self, N_("rotate 90 degrees CCW."),
687 G_CALLBACK(rotate_ccw), FALSE, GDK_KEY_bracketleft, 0,
689
690 dt_iop_button_new(self, N_("rotate 90 degrees CW."),
691 G_CALLBACK(rotate_cw), FALSE, GDK_KEY_bracketright, 0,
693
694 dt_iop_button_new(self, N_("flip horizontally."), G_CALLBACK(_flip_h), FALSE, 0, 0, dtgtk_cairo_paint_flip, 1,
695 self->gui->widget);
696
697 dt_iop_button_new(self, N_("flip vertically."), G_CALLBACK(_flip_v), FALSE, 0, 0, dtgtk_cairo_paint_flip, 0,
698 self->gui->widget);
699}
700
701void gui_cleanup(struct dt_iop_module_t *self)
702{
703 self->gui->gui_data = NULL;
704}
705
706// clang-format off
707// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
708// vim: shiftwidth=2 expandtab tabstop=2 cindent
709// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
710// 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
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
@ IOP_CS_RGB
static const float x
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
#define dt_database_start_transaction()
Definition database.h:290
#define dt_database_release_transaction()
Definition database.h:291
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:43
static void _flip_h(GtkWidget *widget, dt_iop_module_t *self)
Definition flip.c:647
int operation_tags()
Definition flip.c:115
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition flip.c:448
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 flip.c:322
const char ** description(struct dt_iop_module_t *self)
Definition flip.c:130
int default_group()
Definition flip.c:110
int distort_backtransform(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 flip.c:290
static int _flip_geometry_backtransform(const void *data, const dt_geometry_record_t *const record, dt_geometry_chain_t *chain, float *points, size_t points_count)
Definition flip.c:493
static void _flip_geometry_map_size(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
Definition flip.c:466
static void _flip_map_size(const dt_image_orientation_t orientation, const dt_iop_roi_t *const roi_in, dt_iop_roi_t *roi_out)
Input rect -> output rect: a swap, or nothing.
Definition flip.c:250
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 flip.c:263
static dt_image_orientation_t merge_two_orientations(dt_image_orientation_t raw_orientation, dt_image_orientation_t user_orientation)
Definition flip.c:145
static void rotate_cw(GtkWidget *widget, dt_iop_module_t *self)
Definition flip.c:639
static void adjust_aabb(const int32_t *p, int32_t *aabb)
Definition flip.c:92
const char * aliases()
Definition flip.c:105
static int _flip_geometry_transform(const void *data, const dt_geometry_record_t *const record, dt_geometry_chain_t *chain, float *points, size_t points_count)
Definition flip.c:471
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition flip.c:542
static const dt_geometry_vtable_t _flip_geometry_vtable
Definition flip.c:515
const char * name()
Definition flip.c:100
gboolean geometry_record(dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
Definition flip.c:521
static void rotate_ccw(GtkWidget *widget, dt_iop_module_t *self)
Definition flip.c:643
void cleanup_global(dt_iop_module_so_t *self)
Definition flip.c:441
void gui_init(struct dt_iop_module_t *self)
Definition flip.c:676
static void _flip_v(GtkWidget *widget, dt_iop_module_t *self)
Definition flip.c:661
static dt_image_orientation_t _flip_resolve(dt_iop_module_t *self, const dt_iop_flip_params_t *const p)
The orientation this module will actually apply.
Definition flip.c:243
void reload_defaults(dt_iop_module_t *self)
Definition flip.c:591
static void get_corner(const int32_t *aabb, const int i, int32_t *p)
Definition flip.c:87
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition flip.c:125
int flags()
Definition flip.c:120
void gui_cleanup(struct dt_iop_module_t *self)
Definition flip.c:701
void init_presets(dt_iop_module_so_t *self)
Definition flip.c:554
static void backtransform(const int32_t *x, int32_t *o, const dt_image_orientation_t orientation, int32_t iw, int32_t ih)
Definition flip.c:203
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 flip.c:388
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition flip.c:548
struct dt_iop_flip_params_t dt_iop_flip_data_t
Definition flip.c:79
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 flip.c:403
void init_global(dt_iop_module_so_t *self)
Definition flip.c:433
void modify_roi_in(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in)
Definition flip.c:347
void modify_roi_out(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *roi_in)
Definition flip.c:338
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 flip.c:173
static void do_rotate(dt_iop_module_t *self, uint32_t cw)
Definition flip.c:613
Where things are on the image, answered without a pipeline.
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled)
void dt_gui_presets_update_autoapply(const char *name, dt_dev_operation_t op, const int32_t version, const int autoapply)
gboolean dt_history_repository_module_exists(const int32_t imgid, const char *operation)
dt_image_orientation_t
Definition image.h:216
@ ORIENTATION_SWAP_XY
Definition image.h:221
@ ORIENTATION_FLIP_Y
Definition image.h:219
@ ORIENTATION_ROTATE_CCW_90_DEG
Definition image.h:228
@ ORIENTATION_NULL
Definition image.h:217
@ ORIENTATION_ROTATE_CW_90_DEG
Definition image.h:229
@ ORIENTATION_NONE
Definition image.h:218
@ ORIENTATION_FLIP_X
Definition image.h:220
@ ORIENTATION_ROTATE_180_DEG
Definition image.h:226
@ ORIENTATION_FLIP_VERTICALLY
Definition image.h:225
@ ORIENTATION_FLIP_HORIZONTALLY
Definition image.h:224
static dt_image_orientation_t dt_image_orientation(const dt_image_t *img)
Definition image.h:692
int bpp
__DT_CLONE_TARGETS__ void dt_imageio_flip_buffers(char *out, const char *in, const size_t bpp, const int wd, const int ht, const int fwd, const int fht, const int stride, const dt_image_orientation_t orientation)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
Definition imageop.c:1893
@ IOP_FLAGS_ALLOW_TILING
Definition imageop.h:188
@ IOP_FLAGS_UNSAFE_COPY
Definition imageop.h:196
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_FLAGS_TILING_FULL_ROI
Definition imageop.h:190
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
@ IOP_TAG_DISTORT
Definition imageop.h:170
GtkWidget * dt_iop_button_new(dt_iop_module_t *self, const gchar *label, GCallback callback, gboolean local, guint accel_key, GdkModifierType mods, DTGTKCairoPaintIconFunc paint, gint paintflags, GtkWidget *box)
GtkWidget * dt_iop_gui_reset_label_new(const gchar *label, dt_iop_module_t *module, void *param, int param_size)
void *const ovoid
@ 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.
float *const restrict const size_t k
#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
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
Definition mem_alloc.h:184
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2554
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2448
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2491
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
Definition opencl.c:2545
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_image_t image_storage
Definition develop.h:225
One module instance's contribution, as data.
Definition geometry.h:99
dt_iop_roi_t in
Definition geometry.h:117
const dt_geometry_vtable_t * vtable
Definition geometry.h:110
void(* free_data)(void *data)
Definition geometry.h:112
A module's geometry, evaluated. Pure functions of the record's own data.
Definition geometry.h:75
void(* map_size)(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
Full-resolution input rect -> output rect. Mirrors modify_roi_out() at scale 1.
Definition geometry.h:77
dt_image_raw_parameters_t legacy_flip
Definition image.h:431
int32_t id
Definition image.h:401
unsigned int channels
Definition format.h:83
dt_image_orientation_t orientation
Definition flip.c:463
dt_image_orientation_t orientation
Definition lightroom.c:84
dt_iop_gui_data_t * gui_data
Definition imageop_gui.h:42
GtkWidget * widget
Definition imageop_gui.h:47
dt_dev_operation_t op
Definition imageop.h:235
dt_iop_global_data_t * data
Definition imageop.h:238
dt_iop_params_t * default_params
Definition imageop.h:333
struct dt_iop_module_gui_t * gui
Definition imageop.h:346
struct dt_develop_t * dev
Definition imageop.h:311
gboolean default_enabled
Definition imageop.h:318
dt_iop_global_data_t * global_data
Definition imageop.h:337
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
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
#define DT_GUI_BOX_SPACING
void dtgtk_cairo_paint_refresh(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_flip(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)