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:
parent
cd67aca62d
commit
498c35c288
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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>::
|
||||||
|
|
29
src/imv.c
29
src/imv.c
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue