148 lines
4.4 KiB
C
148 lines
4.4 KiB
C
|
#include <debug.h>
|
||
|
#include <cmdline.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <getopt.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
extern char *optarg;
|
||
|
extern int optind, opterr, optopt;
|
||
|
|
||
|
static struct option long_options[] = {
|
||
|
{"output", required_argument, 0, 'o'},
|
||
|
{"height", required_argument, 0, 'h'},
|
||
|
{"width", required_argument, 0, 'w'},
|
||
|
{"gray", no_argument, 0, 'g'},
|
||
|
{"type", required_argument, 0, 't'},
|
||
|
{"rotate", required_argument, 0, 'r'},
|
||
|
{"verbose", no_argument, 0, 'V'},
|
||
|
{"help", no_argument, 0, 1},
|
||
|
{0, 0, 0, 0},
|
||
|
};
|
||
|
|
||
|
/* This array must parallel long_options[] */
|
||
|
static const char *descriptions[] = {
|
||
|
"output file",
|
||
|
"image height in pixels",
|
||
|
"image width in pixels",
|
||
|
"process the luma plane only",
|
||
|
"encode as one of { 'ppm', 'rgb', or 'argb' }",
|
||
|
"rotate (90, -90, 180 degrees)",
|
||
|
"print verbose output",
|
||
|
"print this help screen",
|
||
|
};
|
||
|
|
||
|
void print_help(const char *name) {
|
||
|
fprintf(stdout,
|
||
|
"Converts yuv 4:2:0 to rgb24 and generates a PPM file.\n"
|
||
|
"invokation:\n"
|
||
|
"\t%s infile --height <height> --width <width> --output <outfile> [ --gray ] [ --rotate <degrees> ] [ --verbose ]\n"
|
||
|
"\t%s infile --help\n",
|
||
|
name, name);
|
||
|
fprintf(stdout, "options:\n");
|
||
|
struct option *opt = long_options;
|
||
|
const char **desc = descriptions;
|
||
|
while (opt->name) {
|
||
|
fprintf(stdout, "\t-%c/--%s%s: %s\n",
|
||
|
isprint(opt->val) ? opt->val : ' ',
|
||
|
opt->name,
|
||
|
(opt->has_arg ? " (argument)" : ""),
|
||
|
*desc);
|
||
|
opt++;
|
||
|
desc++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int get_options(int argc, char **argv,
|
||
|
char **outfile,
|
||
|
int *height,
|
||
|
int *width,
|
||
|
int *gray,
|
||
|
char **type,
|
||
|
int *rotate,
|
||
|
int *verbose) {
|
||
|
int c;
|
||
|
|
||
|
ASSERT(outfile); *outfile = NULL;
|
||
|
ASSERT(height); *height = -1;
|
||
|
ASSERT(width); *width = -1;
|
||
|
ASSERT(gray); *gray = 0;
|
||
|
ASSERT(rotate); *rotate = 0;
|
||
|
ASSERT(verbose); *verbose = 0;
|
||
|
ASSERT(type); *type = NULL;
|
||
|
|
||
|
while (1) {
|
||
|
/* getopt_long stores the option index here. */
|
||
|
int option_index = 0;
|
||
|
|
||
|
c = getopt_long (argc, argv,
|
||
|
"Vgo:h:w:r:t:",
|
||
|
long_options,
|
||
|
&option_index);
|
||
|
/* Detect the end of the options. */
|
||
|
if (c == -1) break;
|
||
|
|
||
|
if (isgraph(c)) {
|
||
|
INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
|
||
|
}
|
||
|
|
||
|
#define SET_STRING_OPTION(name) do { \
|
||
|
ASSERT(optarg); \
|
||
|
(*name) = strdup(optarg); \
|
||
|
} while(0)
|
||
|
|
||
|
#define SET_INT_OPTION(val) do { \
|
||
|
ASSERT(optarg); \
|
||
|
if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \
|
||
|
FAILIF(1 != sscanf(optarg+2, "%x", val), \
|
||
|
"Expecting a hexadecimal argument!\n"); \
|
||
|
} else { \
|
||
|
FAILIF(1 != sscanf(optarg, "%d", val), \
|
||
|
"Expecting a decimal argument!\n"); \
|
||
|
} \
|
||
|
} while(0)
|
||
|
|
||
|
switch (c) {
|
||
|
case 0:
|
||
|
/* If this option set a flag, do nothing else now. */
|
||
|
if (long_options[option_index].flag != 0)
|
||
|
break;
|
||
|
INFO ("option %s", long_options[option_index].name);
|
||
|
if (optarg)
|
||
|
INFO (" with arg %s", optarg);
|
||
|
INFO ("\n");
|
||
|
break;
|
||
|
case 1: print_help(argv[0]); exit(1); break;
|
||
|
case 'o':
|
||
|
SET_STRING_OPTION(outfile);
|
||
|
break;
|
||
|
case 't':
|
||
|
SET_STRING_OPTION(type);
|
||
|
break;
|
||
|
case 'h':
|
||
|
SET_INT_OPTION(height);
|
||
|
break;
|
||
|
case 'w':
|
||
|
SET_INT_OPTION(width);
|
||
|
break;
|
||
|
case 'r':
|
||
|
SET_INT_OPTION(rotate);
|
||
|
break;
|
||
|
case 'g': *gray = 1; break;
|
||
|
case 'V': *verbose = 1; break;
|
||
|
case '?':
|
||
|
/* getopt_long already printed an error message. */
|
||
|
break;
|
||
|
|
||
|
#undef SET_STRING_OPTION
|
||
|
#undef SET_INT_OPTION
|
||
|
|
||
|
default:
|
||
|
FAILIF(1, "Unknown option");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return optind;
|
||
|
}
|