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.
This commit is contained in:
Sebastian Parborg 2019-08-25 13:58:49 +02:00 committed by Harry Jeffery
parent cd67aca62d
commit 498c35c288
5 changed files with 65 additions and 26 deletions

View file

@ -132,7 +132,7 @@ Commands can be entered by pressing *:*. imv supports the following commands:
*toggle_playing*:: *toggle_playing*::
Toggle playback of the current image if it is an animated gif. Toggle playback of the current image if it is an animated gif.
*scaling* <none|shrink|full|next>:: *scaling* <none|shrink|full|crop|next>::
Set the current scaling mode. Setting the mode to 'next' advances it to the Set the current scaling mode. Setting the mode to 'next' advances it to the
next mode in the list. next mode in the list.

View file

@ -63,10 +63,11 @@ The *[options]* section accepts the following settings:
*recursively* = <true|false>:: *recursively* = <true|false>::
Load input paths recursively. Defaults to 'false'. Load input paths recursively. Defaults to 'false'.
*scaling_mode* = <none|shrink|full>:: *scaling_mode* = <none|shrink|full|crop>::
Set scaling mode to use. 'none' will show each image at its actual size. Set scaling mode to use. 'none' will show each image at its actual size.
'shrink' will scale down the image to fit inside the window. 'full' will 'shrink' will scale down the image to fit inside the window. 'full' will
both scale up and scale down the image to fit perfectly inside the window. both scale up and scale down the image to fit perfectly inside the window.
'crop' willl scale and crop the image to fill the window.
Defaults to 'full'. Defaults to 'full'.
*slideshow_duration* = <duration>:: *slideshow_duration* = <duration>::

View file

@ -29,17 +29,11 @@
#define PATH_MAX 4096 #define PATH_MAX 4096
#endif #endif
enum scaling_mode {
SCALING_NONE,
SCALING_DOWN,
SCALING_FULL,
SCALING_MODE_COUNT
};
static const char *scaling_label[] = { static const char *scaling_label[] = {
"actual size", "actual size",
"shrink to fit", "shrink to fit",
"scale to fit" "scale to fit",
"crop"
}; };
enum background_type { 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 wh = e->data.resize.height;
const int bw = e->data.resize.buffer_width; const int bw = e->data.resize.buffer_width;
const int bh = e->data.resize.buffer_height; 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); imv_canvas_resize(imv->canvas, bw, bh);
break; break;
} }
@ -651,6 +645,11 @@ static bool parse_scaling_mode(struct imv *imv, const char *mode)
return true; return true;
} }
if (!strcmp(mode, "crop")) {
imv->scaling_mode = SCALING_CROP;
return true;
}
if (!strcmp(mode, "none")) { if (!strcmp(mode, "none")) {
imv->scaling_mode = SCALING_NONE; imv->scaling_mode = SCALING_NONE;
return true; return true;
@ -960,18 +959,8 @@ int imv_run(struct imv *imv)
} }
if (imv->need_rescale) { if (imv->need_rescale) {
int ww, wh;
imv_window_get_size(imv->window, &ww, &wh);
imv->need_rescale = false; imv->need_rescale = false;
if (imv->scaling_mode == SCALING_NONE || imv_viewport_rescale(imv->view, imv->current_image, imv->scaling_mode);
(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);
}
} }
current_time = cur_time(); current_time = cur_time();

View file

@ -220,15 +220,48 @@ void imv_viewport_scale_to_window(struct imv_viewport *view, const struct imv_im
view->locked = 0; 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) void imv_viewport_set_redraw(struct imv_viewport *view)
{ {
view->redraw = 1; 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, void imv_viewport_update(struct imv_viewport *view,
int window_width, int window_height, int window_width, int window_height,
int buffer_width, int buffer_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.width = window_width;
view->window.height = window_height; view->window.height = window_height;
@ -241,7 +274,7 @@ void imv_viewport_update(struct imv_viewport *view,
} }
imv_viewport_center(view, image); 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) int imv_viewport_needs_redraw(struct imv_viewport *view)

View file

@ -6,6 +6,14 @@
struct imv_viewport; 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 */ /* Used to signify how a a user requested a zoom */
enum imv_zoom_source { enum imv_zoom_source {
IMV_ZOOM_MOUSE, 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, void imv_viewport_scale_to_actual(struct imv_viewport *view,
const struct imv_image *image); 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, void imv_viewport_scale_to_window(struct imv_viewport *view,
const struct imv_image *image); 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 */ /* Tell the viewport that it needs to be redrawn */
void imv_viewport_set_redraw(struct imv_viewport *view); 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, void imv_viewport_update(struct imv_viewport *view,
int window_width, int window_height, int window_width, int window_height,
int buffer_width, int buffer_height, int buffer_width, int buffer_height,
struct imv_image *image); struct imv_image *image, enum scaling_mode);
/* Poll whether we need to redraw */ /* Poll whether we need to redraw */
int imv_viewport_needs_redraw(struct imv_viewport *view); int imv_viewport_needs_redraw(struct imv_viewport *view);