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 .Nd view images
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl adfhlru .Op Fl adfhlrSsu
.Op Fl b Ar color .Op Fl b Ar color
.Op Fl e Ar font:size .Op Fl e Ar font:size
.Op Fl n Ar position .Op Fl n Ar position
@ -25,7 +25,8 @@ reloads the current image if it detects changes to the file.
accepts following flags: accepts following flags:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl a .It Fl a
Default to showing images at actual size. .Dq actual size
mode: show images at actual size.
.It Fl b Ar color .It Fl b Ar color
Set the background color. Set the background color.
Either 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. may be expressed as a number or as a path of an image.
.It Fl r .It Fl r
Recursively search input paths for files. 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 .It Fl t Ar seconds
Set the slideshow delay in seconds. Set the slideshow delay in seconds.
Fractional numbers are accepted. Fractional numbers are accepted.
Setting this to zero disables slideshow mode, which is the default. Setting this to zero disables slideshow mode, which is the default.
.It Fl u .It Fl u
Use nearest neighbour resampling. Recommended for pixel art. Use nearest neighbour resampling.
Recommended for pixel art.
.El .El
.Ss Reading from standard input .Ss Reading from standard input
When run with argument When run with argument
@ -113,6 +123,17 @@ Toggle gif playback.
Step forward one frame (when playing gifs). Step forward one frame (when playing gifs).
.It Cm p .It Cm p
Print current image path to stdout 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 .It Cm t
Increase slideshow delay by one second Increase slideshow delay by one second
.It Cm T .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 "viewport.h"
#include "util.h" #include "util.h"
enum scaling_mode {
NONE,
DOWN,
FULL
};
static char *scaling_label[] = {
"actual size",
"best fit",
"perfect fit"
};
struct { struct {
int fullscreen; int fullscreen;
int stdin_list; int stdin_list;
int recursive; int recursive;
int actual; int scaling;
int nearest_neighbour; int nearest_neighbour;
int solid_bg; int solid_bg;
int list; int list;
@ -52,7 +64,7 @@ struct {
.fullscreen = 0, .fullscreen = 0,
.stdin_list = 0, .stdin_list = 0,
.recursive = 0, .recursive = 0,
.actual = 0, .scaling = FULL,
.nearest_neighbour = 0, .nearest_neighbour = 0,
.solid_bg = 1, .solid_bg = 1,
.list = 0, .list = 0,
@ -91,7 +103,7 @@ static void parse_args(int argc, char** argv)
char *argp, o; 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) { switch(o) {
case 'f': g_options.fullscreen = 1; break; case 'f': g_options.fullscreen = 1; break;
case 'i': 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"); fprintf(stderr, "Warning: '-i' is deprecated. No flag is needed.\n");
break; break;
case 'r': g_options.recursive = 1; 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 'u': g_options.nearest_neighbour = 1; break;
case 'd': g_options.overlay = 1; break; case 'd': g_options.overlay = 1; break;
case 'h': print_usage(); exit(0); 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? */ /* do we need to redraw the window? */
int need_redraw = 1; int need_redraw = 1;
int need_rescale = 0;
/* used to calculate when to skip to the next image in slideshow mode */ /* 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; int quit = 0;
while(!quit) { while(!quit) {
@ -315,13 +333,13 @@ int main(int argc, char** argv)
case SDLK_LEFT: case SDLK_LEFT:
imv_navigator_select_rel(&nav, -1); imv_navigator_select_rel(&nav, -1);
/* reset slideshow delay */ /* reset slideshow delay */
delay_mseconds_passed = 0; delay_msec = 0;
break; break;
case SDLK_RIGHTBRACKET: case SDLK_RIGHTBRACKET:
case SDLK_RIGHT: case SDLK_RIGHT:
imv_navigator_select_rel(&nav, 1); imv_navigator_select_rel(&nav, 1);
/* reset slideshow delay */ /* reset slideshow delay */
delay_mseconds_passed = 0; delay_msec = 0;
break; break;
case SDLK_EQUALS: case SDLK_EQUALS:
case SDLK_i: case SDLK_i:
@ -333,12 +351,18 @@ int main(int argc, char** argv)
case SDLK_DOWN: case SDLK_DOWN:
imv_viewport_zoom(&view, &tex, IMV_ZOOM_KEYBOARD, -1); imv_viewport_zoom(&view, &tex, IMV_ZOOM_KEYBOARD, -1);
break; 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: case SDLK_a:
imv_viewport_scale_to_actual(&view, &tex); imv_viewport_scale_to_actual(&view, &tex);
break; break;
case SDLK_r:
imv_viewport_scale_to_window(&view, &tex);
break;
case SDLK_c: case SDLK_c:
imv_viewport_center(&view, &tex); imv_viewport_center(&view, &tex);
break; break;
@ -431,29 +455,40 @@ int main(int argc, char** argv)
} }
char title[256]; char title[256];
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [LOADING] %s", snprintf(&title[0], sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]",
nav.cur_path + 1, nav.num_paths, current_path); nav.cur_path + 1, nav.num_paths, current_path,
scaling_label[g_options.scaling]);
imv_viewport_set_title(&view, title); imv_viewport_set_title(&view, title);
imv_loader_load(&ldr, current_path, stdin_buffer, stdin_buffer_size); imv_loader_load(&ldr, current_path, stdin_buffer, stdin_buffer_size);
view.playing = 1; 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 */ /* check if a new image is available to display */
FIBITMAP *bmp; FIBITMAP *bmp;
int is_new_image; int is_new_image;
if(imv_loader_get_image(&ldr, &bmp, &is_new_image)) { if(imv_loader_get_image(&ldr, &bmp, &is_new_image)) {
imv_texture_set_image(&tex, bmp); imv_texture_set_image(&tex, bmp);
iw = FreeImage_GetWidth(bmp);
ih = FreeImage_GetWidth(bmp);
FreeImage_Unload(bmp); FreeImage_Unload(bmp);
need_redraw = 1; need_redraw = 1;
if(is_new_image) { need_rescale += is_new_image;
if(g_options.actual) { }
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); imv_viewport_scale_to_actual(&view, &tex);
} else { } else {
imv_viewport_scale_to_window(&view, &tex); imv_viewport_scale_to_window(&view, &tex);
} }
} }
}
current_time = SDL_GetTicks(); current_time = SDL_GetTicks();
@ -468,11 +503,11 @@ int main(int argc, char** argv)
if(g_options.delay) { if(g_options.delay) {
unsigned int dt = current_time - last_time; unsigned int dt = current_time - last_time;
delay_mseconds_passed += dt; delay_msec += dt;
need_redraw = 1; need_redraw = 1;
if(delay_mseconds_passed >= g_options.delay) { if(delay_msec >= g_options.delay) {
imv_navigator_select_rel(&nav, 1); 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); const char *current_path = imv_navigator_selection(&nav);
char title[256]; char title[256];
if(g_options.delay > 1000) { if(g_options.delay > 1000) {
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%lu/%lus] [%ix%i] %s", snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%lu/%lus] [%ix%i] "
nav.cur_path + 1, nav.num_paths, delay_mseconds_passed / 1000 + 1, "%s [%s]", nav.cur_path + 1, nav.num_paths, delay_msec / 1000 + 1,
g_options.delay / 1000, tex.width, tex.height, current_path); g_options.delay / 1000, tex.width, tex.height, current_path,
scaling_label[g_options.scaling]);
} else { } else {
snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%ix%i] %s", snprintf(&title[0], sizeof(title), "imv - [%i/%i] [%ix%i] %s [%s]",
nav.cur_path + 1, nav.num_paths, nav.cur_path + 1, nav.num_paths, tex.width, tex.height,
tex.width, tex.height, current_path); current_path, scaling_label[g_options.scaling]);
} }
imv_viewport_set_title(&view, title); imv_viewport_set_title(&view, title);
/* update the overlay */ /* update the overlay */
if(font) { if(font) {
if(g_options.delay > 1000) { if(g_options.delay > 1000) {
snprintf(&title[0], sizeof(title), "[%i/%i] [%lu/%lus] %s", snprintf(&title[0], sizeof(title), "[%i/%i] [%lu/%lus] %s [%s]",
nav.cur_path + 1, nav.num_paths, delay_mseconds_passed / 1000 + 1, nav.cur_path + 1, nav.num_paths, delay_msec / 1000 + 1,
g_options.delay / 1000, current_path); g_options.delay / 1000, current_path,
scaling_label[g_options.scaling]);
} else { } else {
snprintf(&title[0], sizeof(title), "[%i/%i] %s", nav.cur_path + 1, snprintf(&title[0], sizeof(title), "[%i/%i] %s [%s]",
nav.num_paths, current_path); nav.cur_path + 1, nav.num_paths, current_path,
scaling_label[g_options.scaling]);
} }
if(g_options.overlay_str) { if(g_options.overlay_str) {
free(g_options.overlay_str); free(g_options.overlay_str);
@ -523,8 +561,6 @@ int main(int argc, char** argv)
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
} else { } else {
/* chequered background */ /* chequered background */
int ww, wh;
SDL_GetWindowSize(window, &ww, &wh);
int img_w, img_h; int img_w, img_h;
SDL_QueryTexture(chequered_tex, NULL, NULL, &img_w, &img_h); SDL_QueryTexture(chequered_tex, NULL, NULL, &img_w, &img_h);
/* tile the texture so it fills the window */ /* tile the texture so it fills the window */