Skip to content

Commit b1f0ad2

Browse files
Crop module gets orientation proxy support
While developing an image in darkroom we might have set a cropping area, this commit implements functionality to keep the cropped area if we change orientation via the flip module. Three parts in the codebase required additions without changing existing code. 1. `dt_develop_t` got two additions in cropping proxy, `struct dt_iop_module_t *flip_handler` points to the crop module and is setup there. We can't use `exposer` as the proxy because that is dynamically set in pixelpipe code only if enabled and we want to change crop parameters even if crop is disabled. `void (*flip_callback)` is the callback function changing crop parameters, defined in crop. 2. Orientation module uses the `flip_callback(self, orientation)` requesting changes in crop. 3. In crop we have `_crop_handle_flip()` as proxy `flip_callback` with proper logs about action. - It gets the data from self `dt_iop_crop_params_t`, - does the requested action, - updates gui from parameters - adds a new history stack entry (respecting the current `crop->enabled` status).
1 parent 6fe9931 commit b1f0ad2

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

src/develop/develop.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,16 @@ typedef struct dt_develop_t
289289

290290
dt_dev_chroma_t chroma;
291291

292-
// for exposing the crop
292+
// for exposing and handling the crop
293293
struct
294294
{
295295
// set by dt_dev_pixelpipe_synch() if an enabled crop module is included in history
296296
struct dt_iop_module_t *exposer;
297+
298+
// proxy to change crop settings via flip module
299+
struct dt_iop_module_t *flip_handler;
300+
void (*flip_callback)(struct dt_iop_module_t *crop,
301+
const dt_image_orientation_t flipmode);
297302
} cropping;
298303

299304
// for the overexposure indicator

src/iop/crop.c

+34
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,37 @@ static gchar *_aspect_format(gchar *original,
11171117
return g_strdup_printf("%s %4.2f", original, (float)adim / (float)bdim);
11181118
}
11191119

1120+
static void _crop_handle_flip(dt_iop_module_t *self, const dt_image_orientation_t mode)
1121+
{
1122+
dt_iop_crop_params_t *p = self ? self->params : NULL;
1123+
if(!p) return;
1124+
1125+
// we avoid action if default or fully symmetrical
1126+
const gboolean no_action = (p->cx == 1.f - p->ch) && (p->cy == 1.f - p->cw);
1127+
1128+
dt_print(DT_DEBUG_PIPE, "[crop_handle_flip] origin: %1.3f %1.3f %1.3f %1.3f mode=%s%s%s",
1129+
p->cx, 1.0f - p->cw, p->cy, 1.0f - p->ch,
1130+
mode == ORIENTATION_ROTATE_CW_90_DEG ? "ROTATE_CW_90_DEG"
1131+
: mode == ORIENTATION_ROTATE_CCW_90_DEG ? "ROTATE_CCW_90_DEG"
1132+
: mode == ORIENTATION_FLIP_HORIZONTALLY ? "FLIP_HORIZONTALLY"
1133+
: mode == ORIENTATION_FLIP_VERTICALLY ? "FLIP_VERTICALLY"
1134+
: "UNKNOWN",
1135+
self->enabled ? "" : ", crop disabled",
1136+
no_action ? ", no action": "");
1137+
1138+
if(no_action) return;
1139+
1140+
const float ocx = p->cx;
1141+
const float ocy = p->cy;
1142+
if(mode == ORIENTATION_FLIP_HORIZONTALLY) {p->cx = 1.f-p->cw; p->cw = 1.f-ocx;}
1143+
else if(mode == ORIENTATION_FLIP_VERTICALLY) {p->cy = 1.f-p->ch; p->ch = 1.f-ocy;}
1144+
else if(mode == ORIENTATION_ROTATE_CW_90_DEG) {p->cx = 1.f-p->ch; p->ch = p->cw; p->cw = 1.f-p->cy; p->cy = ocx;}
1145+
else if(mode == ORIENTATION_ROTATE_CCW_90_DEG) {p->cx = p->cy; p->cy = 1.f-p->cw; p->cw = p->ch; p->ch = 1.f-ocx;}
1146+
1147+
dt_iop_gui_update(self);
1148+
dt_dev_add_history_item(darktable.develop, self, self->enabled);
1149+
}
1150+
11201151
void gui_init(dt_iop_module_t *self)
11211152
{
11221153
dt_iop_crop_gui_data_t *g = IOP_GUI_ALLOC(crop);
@@ -1308,6 +1339,9 @@ void gui_init(dt_iop_module_t *self)
13081339
_("the bottom margin cannot overlap with the top margin"));
13091340

13101341
self->widget = box_enabled;
1342+
1343+
darktable.develop->cropping.flip_handler = self;
1344+
darktable.develop->cropping.flip_callback = _crop_handle_flip;
13111345
}
13121346

13131347
static void _aspect_free(gpointer data)

src/iop/flip.c

+18-4
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ void commit_params(dt_iop_module_t *self,
431431
d->orientation = p->orientation;
432432

433433
if(d->orientation == ORIENTATION_NONE)
434-
piece->enabled = 0;
434+
piece->enabled = FALSE;
435435
}
436436

437437
void init_pipe(dt_iop_module_t *self,
@@ -518,6 +518,20 @@ void reload_defaults(dt_iop_module_t *self)
518518
}
519519
}
520520

521+
static void _crop_callback(dt_iop_module_t *self,
522+
const dt_image_orientation_t mode)
523+
{
524+
dt_develop_t *dev = darktable.develop;
525+
dt_iop_module_t *cropper = dev->cropping.flip_handler;
526+
527+
// FIXME: can we "compress" history here by checking for a flip/crop pair on top of history
528+
// and a) drop the crop on top of history and b) compress flip in one step
529+
530+
dt_dev_add_history_item(dev, self, TRUE);
531+
if(cropper && dev->cropping.flip_callback)
532+
dev->cropping.flip_callback(cropper, mode);
533+
}
534+
521535
static void do_rotate(dt_iop_module_t *self, uint32_t cw)
522536
{
523537
dt_iop_flip_params_t *p = self->params;
@@ -543,7 +557,7 @@ static void do_rotate(dt_iop_module_t *self, uint32_t cw)
543557
orientation ^= ORIENTATION_SWAP_XY;
544558

545559
p->orientation = orientation;
546-
dt_dev_add_history_item(darktable.develop, self, TRUE);
560+
_crop_callback(self, cw ? ORIENTATION_ROTATE_CW_90_DEG : ORIENTATION_ROTATE_CCW_90_DEG);
547561
}
548562

549563
static void rotate_cw(GtkWidget *widget, dt_iop_module_t *self)
@@ -569,7 +583,7 @@ static void _flip_h(GtkWidget *widget, dt_iop_module_t *self)
569583
else
570584
p->orientation = orientation ^ ORIENTATION_FLIP_HORIZONTALLY;
571585

572-
dt_dev_add_history_item(darktable.develop, self, TRUE);
586+
_crop_callback(self, ORIENTATION_FLIP_HORIZONTALLY);
573587
}
574588

575589
static void _flip_v(GtkWidget *widget, dt_iop_module_t *self)
@@ -586,7 +600,7 @@ static void _flip_v(GtkWidget *widget, dt_iop_module_t *self)
586600
else
587601
p->orientation = orientation ^ ORIENTATION_FLIP_VERTICALLY;
588602

589-
dt_dev_add_history_item(darktable.develop, self, TRUE);
603+
_crop_callback(self, ORIENTATION_FLIP_VERTICALLY);
590604
}
591605

592606
void gui_init(dt_iop_module_t *self)

0 commit comments

Comments
 (0)