ncplayer: add -n option for noninterpolative scaling #1738

This commit is contained in:
nick black 2021-06-09 03:21:39 -04:00 committed by Nick Black
parent 99bb6e6f70
commit c967028fbe
3 changed files with 30 additions and 11 deletions

View File

@ -16,6 +16,7 @@ rearrangements of Notcurses.
here, but `ncdirect_renderf()` was introduced pretty recently (2.3.1).
As a result, `ncdirect_renderf()` and `ncdirect_stream()` now honor
`NCVISUAL_OPTION_BLEND` and `NCVISUAL_OPTION_NOINTERPOLATE`.
* `ncplayer` now accepts `-n` to force non-interpolative scaling.
* 2.3.2 (2021-06-03)
* Fixed a bug affecting certain scalings of `ncvisual` objects created from

View File

@ -8,7 +8,7 @@ ncplayer - Render images and video to a terminal
# SYNOPSIS
**ncplayer** [**-h**] [**-V**] [**-q**] [**-d** ***delaymult***] [**-l** ***loglevel***] [**-b** ***blitter***] [**-s** ***scalemode***] [**-k**] [**-L**] [**-t** ***seconds***] [**-a**] files
**ncplayer** [**-h**] [**-V**] [**-q**] [**-d** ***delaymult***] [**-l** ***loglevel***] [**-b** ***blitter***] [**-s** ***scalemode***] [**-k**] [**-L**] [**-t** ***seconds***] [**-n**] [**-a**] files
# DESCRIPTION
@ -43,6 +43,8 @@ be any non-negative number.
**-a**: Treat color 0x000000 as if it were transparent.
**-n**: Use non-interpolative scaling. The result is usually less pleasing to the eye, but it doesn't introduce new colors.
**-V**: Print the program name and version, and exit with success.
**-h**: Print help information, and exit with success.

View File

@ -19,7 +19,7 @@ static void usage(std::ostream& os, const char* name, int exitcode)
__attribute__ ((noreturn));
void usage(std::ostream& o, const char* name, int exitcode){
o << "usage: " << name << " [ -h ] [ -q ] [ -m margins ] [ -l loglevel ] [ -d mult ] [ -s scaletype ] [ -k ] [ -L ] [ -t seconds ] [ -a ] files" << '\n';
o << "usage: " << name << " [ -h ] [ -q ] [ -m margins ] [ -l loglevel ] [ -d mult ] [ -s scaletype ] [ -k ] [ -L ] [ -t seconds ] [ -n ] [ -a ] files" << '\n';
o << " -h: display help and exit with success\n";
o << " -V: print program name and version\n";
o << " -q: be quiet (no frame/timing information along top of screen)\n";
@ -31,6 +31,7 @@ void usage(std::ostream& o, const char* name, int exitcode){
o << " -b blitter: one of 'ascii', 'half', 'quad', 'sex', 'braille', or 'pixel'\n";
o << " -m margins: margin, or 4 comma-separated margins\n";
o << " -a: replace color 0x000000 with a transparent channel\n";
o << " -n: force non-interpolative scaling\n";
o << " -d mult: non-negative floating point scale for frame time" << std::endl;
exit(exitcode);
}
@ -184,13 +185,14 @@ auto perframe(struct ncvisual* ncv, struct ncvisual_options* vopts,
// can exit() directly. returns index in argv of first non-option param.
auto handle_opts(int argc, char** argv, notcurses_options& opts, bool* quiet,
float* timescale, ncscale_e* scalemode, ncblitter_e* blitter,
float* displaytime, bool* loop, uint32_t* transcolor)
float* displaytime, bool* loop, bool* noninterp,
uint32_t* transcolor)
-> int {
*timescale = 1.0;
*scalemode = NCSCALE_STRETCH;
*displaytime = -1;
int c;
while((c = getopt(argc, argv, "Vhql:d:s:b:t:m:kLa")) != -1){
while((c = getopt(argc, argv, "Vhql:d:s:b:t:m:kLan")) != -1){
switch(c){
case 'h':
usage(std::cout, argv[0], EXIT_SUCCESS);
@ -198,6 +200,13 @@ auto handle_opts(int argc, char** argv, notcurses_options& opts, bool* quiet,
case 'V':
printf("ncplayer version %s\n", notcurses_version());
exit(EXIT_SUCCESS);
case 'n':
if(*noninterp){
std::cerr << "Provided -n twice!" << std::endl;
usage(std::cerr, argv[0], EXIT_FAILURE);
}
*noninterp = true;
break;
case 'a':
if(*transcolor){
std::cerr << "Provided -a twice!" << std::endl;
@ -311,7 +320,7 @@ int perframe_direct(struct ncvisual* ncv, struct ncvisual_options* vopts,
// argc/argv ought already be reduced to only the media arguments
int direct_mode_player(int argc, char** argv, ncscale_e scalemode,
ncblitter_e blitter, int lmargin,
unsigned transcolor){
bool noninterp, unsigned transcolor){
Direct dm{};
if(!dm.canopen_images()){
std::cerr << "Notcurses was compiled without multimedia support\n";
@ -341,6 +350,9 @@ int direct_mode_player(int argc, char** argv, ncscale_e scalemode,
vopts.scaling = scalemode;
vopts.x = static_cast<int>(a);
vopts.flags = NCVISUAL_OPTION_HORALIGNED;
if(noninterp){
vopts.flags |= NCVISUAL_OPTION_NOINTERPOLATE;
}
if(transcolor){
vopts.flags |= NCVISUAL_OPTION_ADDALPHA;
}
@ -362,7 +374,7 @@ int rendered_mode_player_inner(NotCurses& nc, int argc, char** argv,
ncscale_e scalemode, ncblitter_e blitter,
bool quiet, bool loop,
double timescale, double displaytime,
uint32_t transcolor){
bool noninterp, uint32_t transcolor){
int dimy, dimx;
std::unique_ptr<Plane> stdn(nc.get_stdplane(&dimy, &dimx));
uint64_t transchan = 0;
@ -389,6 +401,9 @@ int rendered_mode_player_inner(NotCurses& nc, int argc, char** argv,
struct ncvisual_options vopts{};
int r;
vopts.flags |= NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_VERALIGNED;
if(noninterp){
vopts.flags |= NCVISUAL_OPTION_NOINTERPOLATE;
}
if(transcolor){
vopts.flags |= NCVISUAL_OPTION_ADDALPHA;
}
@ -468,7 +483,7 @@ int rendered_mode_player(int argc, char** argv, ncscale_e scalemode,
ncblitter_e blitter, notcurses_options& ncopts,
bool quiet, bool loop,
double timescale, double displaytime,
uint32_t transcolor){
bool noninterp, uint32_t transcolor){
// no -k, we're using full rendered mode (and the alternate screen).
ncopts.flags |= NCOPTION_INHIBIT_SETLOCALE;
if(quiet){
@ -484,7 +499,7 @@ int rendered_mode_player(int argc, char** argv, ncscale_e scalemode,
}
r = rendered_mode_player_inner(nc, argc, argv, scalemode, blitter,
quiet, loop, timescale, displaytime,
transcolor);
noninterp, transcolor);
if(!nc.stop()){
return -1;
}
@ -515,17 +530,18 @@ auto main(int argc, char** argv) -> int {
uint32_t transcolor = 0;
bool quiet = false;
bool loop = false;
bool noninterp = false;
auto nonopt = handle_opts(argc, argv, ncopts, &quiet, &timescale, &scalemode,
&blitter, &displaytime, &loop, &transcolor);
&blitter, &displaytime, &loop, &noninterp, &transcolor);
int r;
// if -k was provided, we now use direct mode rather than simply not using the
// alternate screen, so that output is inline with the shell.
if(ncopts.flags & NCOPTION_NO_ALTERNATE_SCREEN){
r = direct_mode_player(argc - nonopt, argv + nonopt, scalemode, blitter,
ncopts.margin_l, transcolor);
ncopts.margin_l, noninterp, transcolor);
}else{
r = rendered_mode_player(argc - nonopt, argv + nonopt, scalemode, blitter, ncopts,
quiet, loop, timescale, displaytime, transcolor);
quiet, loop, timescale, displaytime, noninterp, transcolor);
}
if(r){
return EXIT_FAILURE;