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:
parent
c92edff1d0
commit
1013c0cd8b
27
doc/imv.1
27
doc/imv.1
|
@ -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
|
||||||
|
|
98
src/main.c
98
src/main.c
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue