Add third scaling mode: best fit

* Add new switches: "-S" to force (default) "perfect fit" mode and "-s" to force
  "best fit" mode.
* Add new control key: "s" to switch scaling mode.
This commit is contained in:
Dmitrij D. Czarkoff 2016-01-16 02:54:31 +01:00
parent c92edff1d0
commit 1013c0cd8b
2 changed files with 94 additions and 37 deletions

View file

@ -6,7 +6,7 @@
.Nd view images
.Sh SYNOPSIS
.Nm
.Op Fl adfhlru
.Op Fl adfhlrSsu
.Op Fl b Ar color
.Op Fl e Ar font:size
.Op Fl n Ar position
@ -25,7 +25,8 @@ reloads the current image if it detects changes to the file.
accepts following flags:
.Bl -tag -width Ds
.It Fl a
Default to showing images at actual size.
.Dq actual size
mode: show images at actual size.
.It Fl b Ar color
Set the background color.
Either
@ -55,12 +56,21 @@ Start at specific position in image list.
may be expressed as a number or as a path of an image.
.It Fl r
Recursively search input paths for files.
.It Fl S
.Dq perfect fit
mode: upscale or downscale image to fit window.
This is the default.
.It Fl s
.Dq best fit
mode: downscale image to fit window.
Images that are smaller then window are shown in actual size.
.It Fl t Ar seconds
Set the slideshow delay in seconds.
Fractional numbers are accepted.
Setting this to zero disables slideshow mode, which is the default.
.It Fl u
Use nearest neighbour resampling. Recommended for pixel art.
Use nearest neighbour resampling.
Recommended for pixel art.
.El
.Ss Reading from standard input
When run with argument
@ -113,6 +123,17 @@ Toggle gif playback.
Step forward one frame (when playing gifs).
.It Cm p
Print current image path to stdout
.It Cm s
Switch scaling mode.
Available modes are:
.Dq actual size
.Pq don't scale images ,
.Dq best fit
.Pq downscale images to fit window, but don't scale smaller images ,
.Dq perfect fit
.Pq upscale or downscale images to fit window
.Pq default ,
in this order.
.It Cm t
Increase slideshow delay by one second
.It Cm T

View file

@ -32,11 +32,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "viewport.h"
#include "util.h"
enum scaling_mode {
NONE,
DOWN,
FULL
};
static char *scaling_label[] = {
"actual size",
"best fit",
"perfect fit"
};
struct {
int fullscreen;
int stdin_list;
int recursive;
int actual;
int scaling;
int nearest_neighbour;
int solid_bg;
int list;
@ -52,7 +64,7 @@ struct {
.fullscreen = 0,
.stdin_list = 0,
.recursive = 0,
.actual = 0,
.scaling = FULL,
.nearest_neighbour = 0,
.solid_bg = 1,
.list = 0,
@ -91,7 +103,7 @@ static void parse_args(int argc, char** argv)
char *argp, o;
while((o = getopt(argc, argv, "firaudhln:b:e:t:")) != -1) {
while((o = getopt(argc, argv, "firasSudhln:b:e:t:")) != -1) {
switch(o) {
case 'f': g_options.fullscreen = 1; break;
case 'i':
@ -99,7 +111,9 @@ static void parse_args(int argc, char** argv)
fprintf(stderr, "Warning: '-i' is deprecated. No flag is needed.\n");
break;
case 'r': g_options.recursive = 1; break;
case 'a': g_options.actual = 1; break;
case 'a': g_options.scaling = NONE; break;
case 's': g_options.scaling = DOWN; break;
case 'S': g_options.scaling = FULL; break;
case 'u': g_options.nearest_neighbour = 1; break;
case 'd': g_options.overlay = 1; break;
case 'h': print_usage(); exit(0); break;
@ -292,9 +306,13 @@ int main(int argc, char** argv)
/* do we need to redraw the window? */
int need_redraw = 1;
int need_rescale = 0;
/* used to calculate when to skip to the next image in slideshow mode */
unsigned long delay_mseconds_passed = 0;
unsigned long delay_msec = 0;
/* initialize variables holding image dimentions */
int iw = 0, ih = 0;
int quit = 0;
while(!quit) {
@ -315,13 +333,13 @@ int main(int argc, char** argv)
case SDLK_LEFT:
imv_navigator_select_rel(&nav, -1);
/* reset slideshow delay */
delay_mseconds_passed = 0;
delay_msec = 0;
break;
case SDLK_RIGHTBRACKET:
case SDLK_RIGHT:
imv_navigator_select_rel(&nav, 1);
/* reset slideshow delay */
delay_mseconds_passed = 0;
delay_msec = 0;
break;
case SDLK_EQUALS:
case SDLK_i:
@ -333,12 +351,18 @@ int main(int argc, char** argv)
case SDLK_DOWN:
imv_viewport_zoom(&view, &tex, IMV_ZOOM_KEYBOARD, -1);
break;
case SDLK_s:
if((g_options.scaling += 1) > FULL) {
g_options.scaling = NONE;
}
/* FALLTHROUGH */
case SDLK_r:
need_rescale = 1;
need_redraw = 1;
break;
case SDLK_a:
imv_viewport_scale_to_actual(&view, &tex);
break;
case SDLK_r:
imv_viewport_scale_to_window(&view, &tex);
break;
case SDLK_c:
imv_viewport_center(&view, &tex);
break;
@ -431,27 +455,38 @@ int main(int argc, char** argv)
}
char title[256];
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [LOADING] %s",
nav.cur_path + 1, nav.num_paths, current_path);
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]",
nav.cur_path + 1, nav.num_paths, current_path,
scaling_label[g_options.scaling]);
imv_viewport_set_title(&view, title);
imv_loader_load(&ldr, current_path, stdin_buffer, stdin_buffer_size);
view.playing = 1;
}
/* get window height and width */
int ww, wh;
SDL_GetWindowSize(window, &ww, &wh);
/* check if a new image is available to display */
FIBITMAP *bmp;
int is_new_image;
if(imv_loader_get_image(&ldr, &bmp, &is_new_image)) {
imv_texture_set_image(&tex, bmp);
iw = FreeImage_GetWidth(bmp);
ih = FreeImage_GetWidth(bmp);
FreeImage_Unload(bmp);
need_redraw = 1;
if(is_new_image) {
if(g_options.actual) {
imv_viewport_scale_to_actual(&view, &tex);
} else {
imv_viewport_scale_to_window(&view, &tex);
}
need_rescale += is_new_image;
}
if(need_rescale) {
need_rescale = 0;
if(g_options.scaling == NONE ||
(g_options.scaling == DOWN && ww > iw && wh > ih)) {
imv_viewport_scale_to_actual(&view, &tex);
} else {
imv_viewport_scale_to_window(&view, &tex);
}
}
@ -468,11 +503,11 @@ int main(int argc, char** argv)
if(g_options.delay) {
unsigned int dt = current_time - last_time;
delay_mseconds_passed += dt;
delay_msec += dt;
need_redraw = 1;
if(delay_mseconds_passed >= g_options.delay) {
if(delay_msec >= g_options.delay) {
imv_navigator_select_rel(&nav, 1);
delay_mseconds_passed = 0;
delay_msec = 0;
}
}
@ -489,25 +524,28 @@ int main(int argc, char** argv)
const char *current_path = imv_navigator_selection(&nav);
char title[256];
if(g_options.delay > 1000) {
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%lu/%lus] [%ix%i] %s",
nav.cur_path + 1, nav.num_paths, delay_mseconds_passed / 1000 + 1,
g_options.delay / 1000, tex.width, tex.height, current_path);
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%lu/%lus] [%ix%i] "
"%s [%s]", nav.cur_path + 1, nav.num_paths, delay_msec / 1000 + 1,
g_options.delay / 1000, tex.width, tex.height, current_path,
scaling_label[g_options.scaling]);
} else {
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%ix%i] %s",
nav.cur_path + 1, nav.num_paths,
tex.width, tex.height, current_path);
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%ix%i] %s [%s]",
nav.cur_path + 1, nav.num_paths, tex.width, tex.height,
current_path, scaling_label[g_options.scaling]);
}
imv_viewport_set_title(&view, title);
/* update the overlay */
if(font) {
if(g_options.delay > 1000) {
snprintf(&title[0], sizeof(title), "[%i/%i] [%lu/%lus] %s",
nav.cur_path + 1, nav.num_paths, delay_mseconds_passed / 1000 + 1,
g_options.delay / 1000, current_path);
snprintf(&title[0], sizeof(title), "[%i/%i] [%lu/%lus] %s [%s]",
nav.cur_path + 1, nav.num_paths, delay_msec / 1000 + 1,
g_options.delay / 1000, current_path,
scaling_label[g_options.scaling]);
} else {
snprintf(&title[0], sizeof(title), "[%i/%i] %s", nav.cur_path + 1,
nav.num_paths, current_path);
snprintf(&title[0], sizeof(title), "[%i/%i] %s [%s]",
nav.cur_path + 1, nav.num_paths, current_path,
scaling_label[g_options.scaling]);
}
if(g_options.overlay_str) {
free(g_options.overlay_str);
@ -523,8 +561,6 @@ int main(int argc, char** argv)
SDL_RenderClear(renderer);
} else {
/* chequered background */
int ww, wh;
SDL_GetWindowSize(window, &ww, &wh);
int img_w, img_h;
SDL_QueryTexture(chequered_tex, NULL, NULL, &img_w, &img_h);
/* tile the texture so it fills the window */