From 498c35c28831cf89cc60a773a5c2513c97bc08a3 Mon Sep 17 00:00:00 2001 From: Sebastian Parborg Date: Sun, 25 Aug 2019 13:58:49 +0200 Subject: Added crop scaling method Added a method that scales and crop the image so that the image will fill the whole window. Also made viewport update respect the current scaling mode. --- src/imv.c | 29 +++++++++-------------------- src/viewport.c | 37 +++++++++++++++++++++++++++++++++++-- src/viewport.h | 20 ++++++++++++++++++-- 3 files changed, 62 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/imv.c b/src/imv.c index b12ed98..2c22f24 100644 --- a/src/imv.c +++ b/src/imv.c @@ -29,17 +29,11 @@ #define PATH_MAX 4096 #endif -enum scaling_mode { - SCALING_NONE, - SCALING_DOWN, - SCALING_FULL, - SCALING_MODE_COUNT -}; - static const char *scaling_label[] = { "actual size", "shrink to fit", - "scale to fit" + "scale to fit", + "crop" }; enum background_type { @@ -435,7 +429,7 @@ static void event_handler(void *data, const struct imv_event *e) const int wh = e->data.resize.height; const int bw = e->data.resize.buffer_width; const int bh = e->data.resize.buffer_height; - imv_viewport_update(imv->view, ww, wh, bw, bh, imv->current_image); + imv_viewport_update(imv->view, ww, wh, bw, bh, imv->current_image, imv->scaling_mode); imv_canvas_resize(imv->canvas, bw, bh); break; } @@ -651,6 +645,11 @@ static bool parse_scaling_mode(struct imv *imv, const char *mode) return true; } + if (!strcmp(mode, "crop")) { + imv->scaling_mode = SCALING_CROP; + return true; + } + if (!strcmp(mode, "none")) { imv->scaling_mode = SCALING_NONE; return true; @@ -960,18 +959,8 @@ int imv_run(struct imv *imv) } if (imv->need_rescale) { - int ww, wh; - imv_window_get_size(imv->window, &ww, &wh); - imv->need_rescale = false; - if (imv->scaling_mode == SCALING_NONE || - (imv->scaling_mode == SCALING_DOWN - && ww > imv_image_width(imv->current_image) - && wh > imv_image_height(imv->current_image))) { - imv_viewport_scale_to_actual(imv->view, imv->current_image); - } else { - imv_viewport_scale_to_window(imv->view, imv->current_image); - } + imv_viewport_rescale(imv->view, imv->current_image, imv->scaling_mode); } current_time = cur_time(); diff --git a/src/viewport.c b/src/viewport.c index ce9fa54..5b8b3c7 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -220,15 +220,48 @@ void imv_viewport_scale_to_window(struct imv_viewport *view, const struct imv_im view->locked = 0; } +void imv_viewport_crop_to_window(struct imv_viewport *view, const struct imv_image *image) +{ + const int image_width = imv_image_width(image); + const int image_height = imv_image_height(image); + const double window_aspect = (double)view->buffer.width / (double)view->buffer.height; + const double image_aspect = (double)image_width / (double)image_height; + + /* Scale the image so that it fills the whole window */ + if(window_aspect > image_aspect) { + view->scale = (double)view->buffer.width / (double)image_width; + } else { + view->scale = (double)view->buffer.height / (double)image_height; + } + + imv_viewport_center(view, image); + view->locked = 0; +} + void imv_viewport_set_redraw(struct imv_viewport *view) { view->redraw = 1; } +void imv_viewport_rescale(struct imv_viewport *view, const struct imv_image *image, + enum scaling_mode scaling_mode) { + if (scaling_mode == SCALING_NONE || + (scaling_mode == SCALING_DOWN + && view->buffer.width > imv_image_width(image) + && view->buffer.height > imv_image_height(image))) { + imv_viewport_scale_to_actual(view, image); + } else if (scaling_mode == SCALING_CROP) { + imv_viewport_crop_to_window(view, image); + } else { + imv_viewport_scale_to_window(view, image); + } +} + void imv_viewport_update(struct imv_viewport *view, int window_width, int window_height, int buffer_width, int buffer_height, - struct imv_image *image) + struct imv_image *image, + enum scaling_mode scaling_mode) { view->window.width = window_width; view->window.height = window_height; @@ -241,7 +274,7 @@ void imv_viewport_update(struct imv_viewport *view, } imv_viewport_center(view, image); - imv_viewport_scale_to_window(view, image); + imv_viewport_rescale(view, image, scaling_mode); } int imv_viewport_needs_redraw(struct imv_viewport *view) diff --git a/src/viewport.h b/src/viewport.h index 0b9519f..5e5bc24 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -6,6 +6,14 @@ struct imv_viewport; +enum scaling_mode { + SCALING_NONE, + SCALING_DOWN, + SCALING_FULL, + SCALING_CROP, + SCALING_MODE_COUNT +}; + /* Used to signify how a a user requested a zoom */ enum imv_zoom_source { IMV_ZOOM_MOUSE, @@ -55,10 +63,18 @@ void imv_viewport_center(struct imv_viewport *view, void imv_viewport_scale_to_actual(struct imv_viewport *view, const struct imv_image *image); -/* Scale the view so that the image fills the window */ +/* Scale the view so that the image fits in the window */ void imv_viewport_scale_to_window(struct imv_viewport *view, const struct imv_image *image); +/* Scale the view so that the image fills the window */ +void imv_viewport_crop_to_window(struct imv_viewport *view, + const struct imv_image *image); + +/* Rescale the view with the chosen scaling method */ +void imv_viewport_rescale(struct imv_viewport *view, const struct imv_image *image, + enum scaling_mode); + /* Tell the viewport that it needs to be redrawn */ void imv_viewport_set_redraw(struct imv_viewport *view); @@ -66,7 +82,7 @@ void imv_viewport_set_redraw(struct imv_viewport *view); void imv_viewport_update(struct imv_viewport *view, int window_width, int window_height, int buffer_width, int buffer_height, - struct imv_image *image); + struct imv_image *image, enum scaling_mode); /* Poll whether we need to redraw */ int imv_viewport_needs_redraw(struct imv_viewport *view); -- cgit v1.2.3