1 #include <debug.h>
2 #include <cmdline.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <getopt.h>
6 #include <string.h>
7 #include <ctype.h>
8
9 extern char *optarg;
10 extern int optind, opterr, optopt;
11
12 static struct option long_options[] = {
13 {"output", required_argument, 0, 'o'},
14 {"height", required_argument, 0, 'h'},
15 {"width", required_argument, 0, 'w'},
16 {"gray", no_argument, 0, 'g'},
17 {"type", required_argument, 0, 't'},
18 {"rotate", required_argument, 0, 'r'},
19 {"verbose", no_argument, 0, 'V'},
20 {"help", no_argument, 0, 1},
21 {0, 0, 0, 0},
22 };
23
24 /* This array must parallel long_options[] */
25 static const char *descriptions[] = {
26 "output file",
27 "image height in pixels",
28 "image width in pixels",
29 "process the luma plane only",
30 "encode as one of { 'ppm', 'rgb', or 'argb' }",
31 "rotate (90, -90, 180 degrees)",
32 "print verbose output",
33 "print this help screen",
34 };
35
print_help(const char * name)36 void print_help(const char *name) {
37 fprintf(stdout,
38 "Converts yuv 4:2:0 to rgb24 and generates a PPM file.\n"
39 "invokation:\n"
40 "\t%s infile --height <height> --width <width> --output <outfile> -t <ppm|grb|argb> [ --gray ] [ --rotate <degrees> ] [ --verbose ]\n"
41 "\t%s infile --help\n",
42 name, name);
43 fprintf(stdout, "options:\n");
44 struct option *opt = long_options;
45 const char **desc = descriptions;
46 while (opt->name) {
47 fprintf(stdout, "\t-%c/--%s%s: %s\n",
48 isprint(opt->val) ? opt->val : ' ',
49 opt->name,
50 (opt->has_arg ? " (argument)" : ""),
51 *desc);
52 opt++;
53 desc++;
54 }
55 }
56
get_options(int argc,char ** argv,char ** outfile,int * height,int * width,int * gray,char ** type,int * rotate,int * verbose)57 int get_options(int argc, char **argv,
58 char **outfile,
59 int *height,
60 int *width,
61 int *gray,
62 char **type,
63 int *rotate,
64 int *verbose) {
65 int c;
66
67 ASSERT(outfile); *outfile = NULL;
68 ASSERT(height); *height = -1;
69 ASSERT(width); *width = -1;
70 ASSERT(gray); *gray = 0;
71 ASSERT(rotate); *rotate = 0;
72 ASSERT(verbose); *verbose = 0;
73 ASSERT(type); *type = NULL;
74
75 while (1) {
76 /* getopt_long stores the option index here. */
77 int option_index = 0;
78
79 c = getopt_long (argc, argv,
80 "Vgo:h:w:r:t:",
81 long_options,
82 &option_index);
83 /* Detect the end of the options. */
84 if (c == -1) break;
85
86 if (isgraph(c)) {
87 INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)"));
88 }
89
90 #define SET_STRING_OPTION(name) do { \
91 ASSERT(optarg); \
92 (*name) = strdup(optarg); \
93 } while(0)
94
95 #define SET_INT_OPTION(val) do { \
96 ASSERT(optarg); \
97 if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \
98 FAILIF(1 != sscanf(optarg+2, "%x", val), \
99 "Expecting a hexadecimal argument!\n"); \
100 } else { \
101 FAILIF(1 != sscanf(optarg, "%d", val), \
102 "Expecting a decimal argument!\n"); \
103 } \
104 } while(0)
105
106 switch (c) {
107 case 0:
108 /* If this option set a flag, do nothing else now. */
109 if (long_options[option_index].flag != 0)
110 break;
111 INFO ("option %s", long_options[option_index].name);
112 if (optarg)
113 INFO (" with arg %s", optarg);
114 INFO ("\n");
115 break;
116 case 1: print_help(argv[0]); exit(1); break;
117 case 'o':
118 SET_STRING_OPTION(outfile);
119 break;
120 case 't':
121 SET_STRING_OPTION(type);
122 break;
123 case 'h':
124 SET_INT_OPTION(height);
125 break;
126 case 'w':
127 SET_INT_OPTION(width);
128 break;
129 case 'r':
130 SET_INT_OPTION(rotate);
131 break;
132 case 'g': *gray = 1; break;
133 case 'V': *verbose = 1; break;
134 case '?':
135 /* getopt_long already printed an error message. */
136 break;
137
138 #undef SET_STRING_OPTION
139 #undef SET_INT_OPTION
140
141 default:
142 FAILIF(1, "Unknown option");
143 }
144 }
145
146 return optind;
147 }
148