Skip to content

Commit

Permalink
Crop module gets orientation proxy support
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
jenshannoschwalm committed Dec 1, 2024
1 parent e5b855c commit 1c8140a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 9 deletions.
7 changes: 6 additions & 1 deletion src/develop/develop.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,16 @@ typedef struct dt_develop_t

dt_dev_chroma_t chroma;

// for exposing the crop
// for exposing and handling the crop
struct
{
// set by dt_dev_pixelpipe_synch() if an enabled crop module is included in history
struct dt_iop_module_t *exposer;

// proxy to change crop settings via flip module
struct dt_iop_module_t *flip_handler;
void (*flip_callback)(struct dt_iop_module_t *crop,
const dt_image_orientation_t flipmode);
} cropping;

// for the overexposure indicator
Expand Down
26 changes: 22 additions & 4 deletions src/iop/crop.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,7 @@ static gboolean _set_max_clip(dt_iop_module_t *self)

// we want to know the size of the actual buffer
dt_dev_pixelpipe_t *fpipe = self->dev->full.pipe;
dt_dev_pixelpipe_iop_t *piece =
dt_dev_distort_get_iop_pipe(self->dev, fpipe, self);
const dt_dev_pixelpipe_iop_t *piece = dt_dev_distort_get_iop_pipe(self->dev, fpipe, self);
if(!piece) return FALSE;

const float wp = piece->buf_out.width;
Expand Down Expand Up @@ -536,8 +535,7 @@ static float _aspect_ratio_get(dt_iop_module_t *self, GtkWidget *combo)
}

// we want to know the size of the actual buffer
dt_dev_pixelpipe_iop_t *piece =
dt_dev_distort_get_iop_pipe(self->dev, self->dev->preview_pipe, self);
const dt_dev_pixelpipe_iop_t *piece = dt_dev_distort_get_iop_pipe(self->dev, self->dev->preview_pipe, self);
if(!piece) return 0.0f;

const int iwd = piece->buf_in.width, iht = piece->buf_in.height;
Expand Down Expand Up @@ -1117,6 +1115,23 @@ static gchar *_aspect_format(gchar *original,
return g_strdup_printf("%s %4.2f", original, (float)adim / (float)bdim);
}

static void _crop_handle_flip(dt_iop_module_t *self, const dt_image_orientation_t mode)
{
dt_iop_crop_params_t *p = self ? self->params : NULL;
if(!p || (p->cx == 0.f && p->cy == 0.f && p->cw == 1.f && p->ch == 1.f))
return;

const float ocx = p->cx;
const float ocy = p->cy;
if(mode == ORIENTATION_FLIP_HORIZONTALLY) {p->cx = 1.f-p->cw; p->cw = 1.f-ocx;}
else if(mode == ORIENTATION_FLIP_VERTICALLY) {p->cy = 1.f-p->ch; p->ch = 1.f-ocy;}
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;}
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;}

dt_iop_gui_update(self);
dt_dev_add_history_item(darktable.develop, self, self->enabled);
}

void gui_init(dt_iop_module_t *self)
{
dt_iop_crop_gui_data_t *g = IOP_GUI_ALLOC(crop);
Expand Down Expand Up @@ -1308,6 +1323,9 @@ void gui_init(dt_iop_module_t *self)
_("the bottom margin cannot overlap with the top margin"));

self->widget = box_enabled;

darktable.develop->cropping.flip_handler = self;
darktable.develop->cropping.flip_callback = _crop_handle_flip;
}

static void _aspect_free(gpointer data)
Expand Down
22 changes: 18 additions & 4 deletions src/iop/flip.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ void commit_params(dt_iop_module_t *self,
d->orientation = p->orientation;

if(d->orientation == ORIENTATION_NONE)
piece->enabled = 0;
piece->enabled = FALSE;
}

void init_pipe(dt_iop_module_t *self,
Expand Down Expand Up @@ -518,6 +518,20 @@ void reload_defaults(dt_iop_module_t *self)
}
}

static void _crop_callback(dt_iop_module_t *self,
const dt_image_orientation_t mode)
{
dt_develop_t *dev = darktable.develop;
dt_iop_module_t *cropper = dev->cropping.flip_handler;

// FIXME: can we "compress" history here by checking for a flip/crop pair on top of history
// and a) drop the crop on top of history and b) compress flip in one step

dt_dev_add_history_item(dev, self, TRUE);
if(cropper && dev->cropping.flip_callback)
dev->cropping.flip_callback(cropper, mode);
}

static void do_rotate(dt_iop_module_t *self, uint32_t cw)
{
dt_iop_flip_params_t *p = self->params;
Expand All @@ -543,7 +557,7 @@ static void do_rotate(dt_iop_module_t *self, uint32_t cw)
orientation ^= ORIENTATION_SWAP_XY;

p->orientation = orientation;
dt_dev_add_history_item(darktable.develop, self, TRUE);
_crop_callback(self, cw ? ORIENTATION_ROTATE_CW_90_DEG : ORIENTATION_ROTATE_CCW_90_DEG);
}

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

dt_dev_add_history_item(darktable.develop, self, TRUE);
_crop_callback(self, ORIENTATION_FLIP_HORIZONTALLY);
}

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

dt_dev_add_history_item(darktable.develop, self, TRUE);
_crop_callback(self, ORIENTATION_FLIP_VERTICALLY);
}

void gui_init(dt_iop_module_t *self)
Expand Down

0 comments on commit 1c8140a

Please sign in to comment.