1 /**
2  * qrencode - QR Code encoder
3  *
4  * QR Code encoding tool
5  * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <getopt.h>
29 #include <errno.h>
30 #if HAVE_PNG
31 #include <png.h>
32 #endif
33 
34 #include "qrencode.h"
35 
36 #define INCHES_PER_METER (100.0/2.54)
37 
38 static int casesensitive = 1;
39 static int eightbit = 0;
40 static int version = 0;
41 static int size = 3;
42 static int margin = -1;
43 static int dpi = 72;
44 static int structured = 0;
45 static int rle = 0;
46 static int svg_path = 0;
47 static int micro = 0;
48 static int inline_svg = 0;
49 static int strict_versioning = 0;
50 static QRecLevel level = QR_ECLEVEL_L;
51 static QRencodeMode hint = QR_MODE_8;
52 static unsigned char fg_color[4] = {0, 0, 0, 255};
53 static unsigned char bg_color[4] = {255, 255, 255, 255};
54 
55 static int verbose = 0;
56 
57 enum imageType {
58 	PNG_TYPE,
59 	PNG32_TYPE,
60 	EPS_TYPE,
61 	SVG_TYPE,
62 	XPM_TYPE,
63 	ANSI_TYPE,
64 	ANSI256_TYPE,
65 	ASCII_TYPE,
66 	ASCIIi_TYPE,
67 	UTF8_TYPE,
68 	ANSIUTF8_TYPE,
69 	ANSI256UTF8_TYPE,
70 	UTF8i_TYPE,
71 	ANSIUTF8i_TYPE
72 };
73 
74 static enum imageType image_type = PNG_TYPE;
75 
76 static const struct option options[] = {
77 	{"help"          , no_argument      , NULL, 'h'},
78 	{"output"        , required_argument, NULL, 'o'},
79 	{"read-from"     , required_argument, NULL, 'r'},
80 	{"level"         , required_argument, NULL, 'l'},
81 	{"size"          , required_argument, NULL, 's'},
82 	{"symversion"    , required_argument, NULL, 'v'},
83 	{"margin"        , required_argument, NULL, 'm'},
84 	{"dpi"           , required_argument, NULL, 'd'},
85 	{"type"          , required_argument, NULL, 't'},
86 	{"structured"    , no_argument      , NULL, 'S'},
87 	{"kanji"         , no_argument      , NULL, 'k'},
88 	{"casesensitive" , no_argument      , NULL, 'c'},
89 	{"ignorecase"    , no_argument      , NULL, 'i'},
90 	{"8bit"          , no_argument      , NULL, '8'},
91 	{"micro"         , no_argument      , NULL, 'M'},
92 	{"rle"           , no_argument      , &rle,   1},
93 	{"svg-path"      , no_argument      , &svg_path, 1},
94 	{"inline"        , no_argument      , &inline_svg, 1},
95 	{"strict-version", no_argument      , &strict_versioning, 1},
96 	{"foreground"    , required_argument, NULL, 'f'},
97 	{"background"    , required_argument, NULL, 'b'},
98 	{"version"       , no_argument      , NULL, 'V'},
99 	{"verbose"       , no_argument      , &verbose, 1},
100 	{NULL, 0, NULL, 0}
101 };
102 
103 static char *optstring = "ho:r:l:s:v:m:d:t:Skci8MV";
104 
usage(int help,int longopt,int status)105 static void usage(int help, int longopt, int status)
106 {
107 	FILE *out = status ? stderr : stdout;
108 	fprintf(out,
109 "qrencode version %s\n"
110 "Copyright (C) 2006-2017 Kentaro Fukuchi\n", QRcode_APIVersionString());
111 	if(help) {
112 		if(longopt) {
113 			fprintf(out,
114 "Usage: qrencode [-o FILENAME] [OPTION]... [STRING]\n"
115 "Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
116 "  -h, --help   display the help message. -h displays only the help of short\n"
117 "               options.\n\n"
118 "  -o FILENAME, --output=FILENAME\n"
119 "               write image to FILENAME. If '-' is specified, the result\n"
120 "               will be output to standard output. If -S is given, structured\n"
121 "               symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
122 "               (suffix is removed from FILENAME, if specified)\n\n"
123 "  -r FILENAME, --read-from=FILENAME\n"
124 "               read input data from FILENAME.\n\n"
125 "  -s NUMBER, --size=NUMBER\n"
126 "               specify module size in dots (pixels). (default=3)\n\n"
127 "  -l {LMQH}, --level={LMQH}\n"
128 "               specify error correction level from L (lowest) to H (highest).\n"
129 "               (default=L)\n\n"
130 "  -v NUMBER, --symversion=NUMBER\n"
131 "               specify the minimum version of the symbol. See SYMBOL VERSIONS\n"
132 "               for more information. (default=auto)\n\n"
133 "  -m NUMBER, --margin=NUMBER\n"
134 "               specify the width of the margins. (default=4 (2 for Micro QR)))\n\n"
135 "  -d NUMBER, --dpi=NUMBER\n"
136 "               specify the DPI of the generated PNG. (default=72)\n\n"
137 "  -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8},\n"
138 "  --type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}\n"
139 "               specify the type of the generated image. (default=PNG)\n\n"
140 "  -S, --structured\n"
141 "               make structured symbols. Version must be specified with '-v'.\n\n"
142 "  -k, --kanji  assume that the input text contains kanji (shift-jis).\n\n"
143 "  -c, --casesensitive\n"
144 "               encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
145 "  -i, --ignorecase\n"
146 "               ignore case distinctions and use only upper-case characters.\n\n"
147 "  -8, --8bit   encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
148 "  -M, --micro  encode in a Micro QR Code.\n\n"
149 "      --rle    enable run-length encoding for SVG.\n\n"
150 "      --svg-path\n"
151 "               use single path to draw modules for SVG.\n\n"
152 "      --inline only useful for SVG output, generates an SVG without the XML tag.\n\n"
153 "      --foreground=RRGGBB[AA]\n"
154 "      --background=RRGGBB[AA]\n"
155 "               specify foreground/background color in hexadecimal notation.\n"
156 "               6-digit (RGB) or 8-digit (RGBA) form are supported.\n"
157 "               Color output support available only in PNG, EPS and SVG.\n\n"
158 "      --strict-version\n"
159 "               disable automatic version number adjustment. If the input data is\n"
160 "               too large for the specified version, the program exits with the\n"
161 "               code of 1.\n\n"
162 "  -V, --version\n"
163 "               display the version number and copyrights of the qrencode.\n\n"
164 "      --verbose\n"
165 "               display verbose information to stderr.\n\n"
166 "  [STRING]     input data. If it is not specified, data will be taken from\n"
167 "               standard input.\n\n"
168 "SYMBOL VERSIONS\n"
169 "               The symbol versions of QR Code range from Version 1 to Version\n"
170 "               40. Each version has a different module configuration or number\n"
171 "               of modules, ranging from Version 1 (21 x 21 modules) up to\n"
172 "               Version 40 (177 x 177 modules). Each higher version number\n"
173 "               comprises 4 additional modules per side by default. See\n"
174 "               http://www.qrcode.com/en/about/version.html for a detailed\n"
175 "               version list.\n"
176 
177 			);
178 		} else {
179 			fprintf(out,
180 "Usage: qrencode [-o FILENAME] [OPTION]... [STRING]\n"
181 "Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
182 "  -h           display this message.\n"
183 "  --help       display the usage of long options.\n"
184 "  -o FILENAME  write image to FILENAME. If '-' is specified, the result\n"
185 "               will be output to standard output. If -S is given, structured\n"
186 "               symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
187 "               (suffix is removed from FILENAME, if specified)\n"
188 "  -r FILENAME  read input data from FILENAME.\n"
189 "  -s NUMBER    specify module size in dots (pixels). (default=3)\n"
190 "  -l {LMQH}    specify error correction level from L (lowest) to H (highest).\n"
191 "               (default=L)\n"
192 "  -v NUMBER    specify the minimum version of the symbol. (default=auto)\n"
193 "  -m NUMBER    specify the width of the margins. (default=4 (2 for Micro))\n"
194 "  -d NUMBER    specify the DPI of the generated PNG. (default=72)\n"
195 "  -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}\n"
196 "               specify the type of the generated image. (default=PNG)\n"
197 "  -S           make structured symbols. Version number must be specified with '-v'.\n"
198 "  -k           assume that the input text contains kanji (shift-jis).\n"
199 "  -c           encode lower-case alphabet characters in 8-bit mode. (default)\n"
200 "  -i           ignore case distinctions and use only upper-case characters.\n"
201 "  -8           encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
202 "  -M           encode in a Micro QR Code.\n"
203 "  -V           display the version number and copyrights of the qrencode.\n"
204 "  [STRING]     input data. If it is not specified, data will be taken from\n"
205 "               standard input.\n\n"
206 "  Try \"qrencode --help\" for more options.\n"
207 			);
208 		}
209 	}
210 }
211 
color_set(unsigned char color[4],const char * value)212 static int color_set(unsigned char color[4], const char *value)
213 {
214 	int len = strlen(value);
215 	int i, count;
216 	unsigned int col[4];
217 	if(len == 6) {
218 		count = sscanf(value, "%02x%02x%02x%n", &col[0], &col[1], &col[2], &len);
219 		if(count < 3 || len != 6) {
220 			return -1;
221 		}
222 		for(i = 0; i < 3; i++) {
223 			color[i] = col[i];
224 		}
225 		color[3] = 255;
226 	} else if(len == 8) {
227 		count = sscanf(value, "%02x%02x%02x%02x%n", &col[0], &col[1], &col[2], &col[3], &len);
228 		if(count < 4 || len != 8) {
229 			return -1;
230 		}
231 		for(i = 0; i < 4; i++) {
232 			color[i] = col[i];
233 		}
234 	} else {
235 		return -1;
236 	}
237 	return 0;
238 }
239 
240 #define MAX_DATA_SIZE (7090 * 2) /* timed by the safty factor 2 */
241 static unsigned char data_buffer[MAX_DATA_SIZE];
readFile(FILE * fp,int * length)242 static unsigned char *readFile(FILE *fp, int *length)
243 {
244 	int ret;
245 
246 	ret = fread(data_buffer, 1, MAX_DATA_SIZE, fp);
247 	if(ret == 0) {
248 		fprintf(stderr, "No input data.\n");
249 		exit(EXIT_FAILURE);
250 	}
251 	if(feof(fp) == 0) {
252 		fprintf(stderr, "Input data is too large.\n");
253 		exit(EXIT_FAILURE);
254 	}
255 
256 	data_buffer[ret] = '\0';
257 	*length = ret;
258 
259 	return data_buffer;
260 }
261 
openFile(const char * outfile)262 static FILE *openFile(const char *outfile)
263 {
264 	FILE *fp;
265 
266 	if(outfile == NULL || (outfile[0] == '-' && outfile[1] == '\0')) {
267 		fp = stdout;
268 	} else {
269 		fp = fopen(outfile, "wb");
270 		if(fp == NULL) {
271 			fprintf(stderr, "Failed to create file: %s\n", outfile);
272 			perror(NULL);
273 			exit(EXIT_FAILURE);
274 		}
275 	}
276 
277 	return fp;
278 }
279 
280 #if HAVE_PNG
fillRow(unsigned char * row,int num,const unsigned char color[])281 static void fillRow(unsigned char *row, int num, const unsigned char color[])
282 {
283 	int i;
284 
285 	for(i = 0; i < num; i++) {
286 		memcpy(row, color, 4);
287 		row += 4;
288 	}
289 }
290 #endif
291 
writePNG(const QRcode * qrcode,const char * outfile,enum imageType type)292 static int writePNG(const QRcode *qrcode, const char *outfile, enum imageType type)
293 {
294 #if HAVE_PNG
295 	static FILE *fp; // avoid clobbering by setjmp.
296 	png_structp png_ptr;
297 	png_infop info_ptr;
298 	png_colorp palette = NULL;
299 	png_byte alpha_values[2];
300 	unsigned char *row, *p, *q;
301 	int x, y, xx, yy, bit;
302 	int realwidth;
303 
304 	realwidth = (qrcode->width + margin * 2) * size;
305 	if(type == PNG_TYPE) {
306 		row = (unsigned char *)malloc((size_t)((realwidth + 7) / 8));
307 	} else if(type == PNG32_TYPE) {
308 		row = (unsigned char *)malloc((size_t)realwidth * 4);
309 	} else {
310 		fprintf(stderr, "Internal error.\n");
311 		exit(EXIT_FAILURE);
312 	}
313 	if(row == NULL) {
314 		fprintf(stderr, "Failed to allocate memory.\n");
315 		exit(EXIT_FAILURE);
316 	}
317 
318 	if(outfile[0] == '-' && outfile[1] == '\0') {
319 		fp = stdout;
320 	} else {
321 		fp = fopen(outfile, "wb");
322 		if(fp == NULL) {
323 			fprintf(stderr, "Failed to create file: %s\n", outfile);
324 			perror(NULL);
325 			exit(EXIT_FAILURE);
326 		}
327 	}
328 
329 	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
330 	if(png_ptr == NULL) {
331 		fprintf(stderr, "Failed to initialize PNG writer.\n");
332 		exit(EXIT_FAILURE);
333 	}
334 
335 	info_ptr = png_create_info_struct(png_ptr);
336 	if(info_ptr == NULL) {
337 		fprintf(stderr, "Failed to initialize PNG write.\n");
338 		exit(EXIT_FAILURE);
339 	}
340 
341 	if(setjmp(png_jmpbuf(png_ptr))) {
342 		png_destroy_write_struct(&png_ptr, &info_ptr);
343 		fprintf(stderr, "Failed to write PNG image.\n");
344 		exit(EXIT_FAILURE);
345 	}
346 
347 	if(type == PNG_TYPE) {
348 		palette = (png_colorp) malloc(sizeof(png_color) * 2);
349 		if(palette == NULL) {
350 			fprintf(stderr, "Failed to allocate memory.\n");
351 			exit(EXIT_FAILURE);
352 		}
353 		palette[0].red   = fg_color[0];
354 		palette[0].green = fg_color[1];
355 		palette[0].blue  = fg_color[2];
356 		palette[1].red   = bg_color[0];
357 		palette[1].green = bg_color[1];
358 		palette[1].blue  = bg_color[2];
359 		alpha_values[0] = fg_color[3];
360 		alpha_values[1] = bg_color[3];
361 		png_set_PLTE(png_ptr, info_ptr, palette, 2);
362 		png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);
363 	}
364 
365 	png_init_io(png_ptr, fp);
366 	if(type == PNG_TYPE) {
367 		png_set_IHDR(png_ptr, info_ptr,
368 				(unsigned int)realwidth, (unsigned int)realwidth,
369 				1,
370 				PNG_COLOR_TYPE_PALETTE,
371 				PNG_INTERLACE_NONE,
372 				PNG_COMPRESSION_TYPE_DEFAULT,
373 				PNG_FILTER_TYPE_DEFAULT);
374 	} else {
375 		png_set_IHDR(png_ptr, info_ptr,
376 				(unsigned int)realwidth, (unsigned int)realwidth,
377 				8,
378 				PNG_COLOR_TYPE_RGB_ALPHA,
379 				PNG_INTERLACE_NONE,
380 				PNG_COMPRESSION_TYPE_DEFAULT,
381 				PNG_FILTER_TYPE_DEFAULT);
382 	}
383 	png_set_pHYs(png_ptr, info_ptr,
384 			dpi * INCHES_PER_METER,
385 			dpi * INCHES_PER_METER,
386 			PNG_RESOLUTION_METER);
387 	png_write_info(png_ptr, info_ptr);
388 
389 	if(type == PNG_TYPE) {
390 	/* top margin */
391 		memset(row, 0xff, (size_t)((realwidth + 7) / 8));
392 		for(y = 0; y < margin * size; y++) {
393 			png_write_row(png_ptr, row);
394 		}
395 
396 		/* data */
397 		p = qrcode->data;
398 		for(y = 0; y < qrcode->width; y++) {
399 			memset(row, 0xff, (size_t)((realwidth + 7) / 8));
400 			q = row;
401 			q += margin * size / 8;
402 			bit = 7 - (margin * size % 8);
403 			for(x = 0; x < qrcode->width; x++) {
404 				for(xx = 0; xx < size; xx++) {
405 					*q ^= (*p & 1) << bit;
406 					bit--;
407 					if(bit < 0) {
408 						q++;
409 						bit = 7;
410 					}
411 				}
412 				p++;
413 			}
414 			for(yy = 0; yy < size; yy++) {
415 				png_write_row(png_ptr, row);
416 			}
417 		}
418 		/* bottom margin */
419 		memset(row, 0xff, (size_t)((realwidth + 7) / 8));
420 		for(y = 0; y < margin * size; y++) {
421 			png_write_row(png_ptr, row);
422 		}
423 	} else {
424 	/* top margin */
425 		fillRow(row, realwidth, bg_color);
426 		for(y = 0; y < margin * size; y++) {
427 			png_write_row(png_ptr, row);
428 		}
429 
430 		/* data */
431 		p = qrcode->data;
432 		for(y = 0; y < qrcode->width; y++) {
433 			fillRow(row, realwidth, bg_color);
434 			for(x = 0; x < qrcode->width; x++) {
435 				for(xx = 0; xx < size; xx++) {
436 					if(*p & 1) {
437 						memcpy(&row[((margin + x) * size + xx) * 4], fg_color, 4);
438 					}
439 				}
440 				p++;
441 			}
442 			for(yy = 0; yy < size; yy++) {
443 				png_write_row(png_ptr, row);
444 			}
445 		}
446 		/* bottom margin */
447 		fillRow(row, realwidth, bg_color);
448 		for(y = 0; y < margin * size; y++) {
449 			png_write_row(png_ptr, row);
450 		}
451 	}
452 
453 	png_write_end(png_ptr, info_ptr);
454 	png_destroy_write_struct(&png_ptr, &info_ptr);
455 
456 	fclose(fp);
457 	free(row);
458 	free(palette);
459 
460 	return 0;
461 #else
462 	fputs("PNG output is disabled at compile time. No output generated.\n", stderr);
463 	return 0;
464 #endif
465 }
466 
writeEPS(const QRcode * qrcode,const char * outfile)467 static int writeEPS(const QRcode *qrcode, const char *outfile)
468 {
469 	FILE *fp;
470 	unsigned char *row, *p;
471 	int x, y, yy;
472 	int realwidth;
473 
474 	fp = openFile(outfile);
475 
476 	realwidth = (qrcode->width + margin * 2) * size;
477 	/* EPS file header */
478 	fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n"
479 				"%%%%BoundingBox: 0 0 %d %d\n"
480 				"%%%%Pages: 1 1\n"
481 				"%%%%EndComments\n", realwidth, realwidth);
482 	/* draw point */
483 	fprintf(fp, "/p { "
484 				"moveto "
485 				"0 1 rlineto "
486 				"1 0 rlineto "
487 				"0 -1 rlineto "
488 				"fill "
489 				"} bind def\n");
490 	/* set color */
491 	fprintf(fp, "gsave\n");
492 	fprintf(fp, "%f %f %f setrgbcolor\n",
493 			(float)bg_color[0] / 255,
494 			(float)bg_color[1] / 255,
495 			(float)bg_color[2] / 255);
496 	fprintf(fp, "%d %d scale\n", realwidth, realwidth);
497 	fprintf(fp, "0 0 p\ngrestore\n");
498 	fprintf(fp, "%f %f %f setrgbcolor\n",
499 			(float)fg_color[0] / 255,
500 			(float)fg_color[1] / 255,
501 			(float)fg_color[2] / 255);
502 	fprintf(fp, "%d %d scale\n", size, size);
503 
504 	/* data */
505 	p = qrcode->data;
506 	for(y = 0; y < qrcode->width; y++) {
507 		row = (p+(y*qrcode->width));
508 		yy = (margin + qrcode->width - y - 1);
509 
510 		for(x = 0; x < qrcode->width; x++) {
511 			if(*(row+x)&0x1) {
512 				fprintf(fp, "%d %d p ", margin + x,  yy);
513 			}
514 		}
515 	}
516 
517 	fprintf(fp, "\n%%%%EOF\n");
518 	fclose(fp);
519 
520 	return 0;
521 }
522 
writeSVG_drawModules(FILE * fp,int x,int y,int width,const char * col,float opacity)523 static void writeSVG_drawModules(FILE *fp, int x, int y, int width, const char* col, float opacity)
524 {
525 	if(svg_path) {
526 		fprintf(fp, "M%d,%dh%d", x, y, width);
527 	} else {
528 		if(fg_color[3] != 255) {
529 			fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
530 					"fill=\"#%s\" fill-opacity=\"%f\"/>\n",
531 					x, y, width, col, opacity );
532 		} else {
533 			fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
534 					"fill=\"#%s\"/>\n",
535 					x, y, width, col );
536 		}
537 	}
538 }
539 
writeSVG(const QRcode * qrcode,const char * outfile)540 static int writeSVG(const QRcode *qrcode, const char *outfile)
541 {
542 	FILE *fp;
543 	unsigned char *row, *p;
544 	int x, y, x0, pen;
545 	int symwidth, realwidth;
546 	float scale;
547 	char fg[7], bg[7];
548 	float fg_opacity;
549 	float bg_opacity;
550 
551 	fp = openFile(outfile);
552 
553 	scale = dpi * INCHES_PER_METER / 100.0;
554 
555 	symwidth = qrcode->width + margin * 2;
556 	realwidth = symwidth * size;
557 
558 	snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1],  fg_color[2]);
559 	snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1],  bg_color[2]);
560 	fg_opacity = (float)fg_color[3] / 255;
561 	bg_opacity = (float)bg_color[3] / 255;
562 
563 	/* XML declaration */
564 	if (!inline_svg)
565 		fputs( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", fp );
566 
567 	/* DTD
568 	   No document type specified because "while a DTD is provided in [the SVG]
569 	   specification, the use of DTDs for validating XML documents is known to
570 	   be problematic. In particular, DTDs do not handle namespaces gracefully.
571 	   It is *not* recommended that a DOCTYPE declaration be included in SVG
572 	   documents."
573 	   http://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace
574 	*/
575 
576 	/* Vanity remark */
577 	fprintf(fp, "<!-- Created with qrencode %s (https://fukuchi.org/works/qrencode/index.html) -->\n", QRcode_APIVersionString());
578 
579 	/* SVG code start */
580 	fprintf(fp,
581 			"<svg width=\"%.2fcm\" height=\"%.2fcm\" viewBox=\"0 0 %d %d\""\
582 			" preserveAspectRatio=\"none\" version=\"1.1\""\
583 			" xmlns=\"http://www.w3.org/2000/svg\">\n",
584 			realwidth / scale, realwidth / scale, symwidth, symwidth
585 		   );
586 
587 	/* Make named group */
588 	fputs("\t<g id=\"QRcode\">\n", fp);
589 
590 	/* Make solid background */
591 	if(bg_color[3] != 255) {
592 		fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" fill-opacity=\"%f\"/>\n", symwidth, symwidth, bg, bg_opacity);
593 	} else {
594 		fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\"/>\n", symwidth, symwidth, bg);
595 	}
596 
597 	if(svg_path) {
598 		if(fg_color[3] != 255) {
599 			fprintf(fp, "\t\t<path style=\"stroke:#%s;stroke-opacity:%f\" transform=\"translate(%d,%d.5)\" d=\"", fg, fg_opacity, margin, margin);
600 		} else {
601 			fprintf(fp, "\t\t<path style=\"stroke:#%s\" transform=\"translate(%d,%d.5)\" d=\"", fg, margin, margin);
602 		}
603 	} else {
604 		/* Create new viewbox for QR data */
605 		fprintf(fp, "\t\t<g id=\"Pattern\" transform=\"translate(%d,%d)\">\n", margin, margin);
606 	}
607 
608 	/* Write data */
609 	p = qrcode->data;
610 	for(y = 0; y < qrcode->width; y++) {
611 		row = (p+(y*qrcode->width));
612 
613 		if( !rle ) {
614 			/* no RLE */
615 			for(x = 0; x < qrcode->width; x++) {
616 				if(*(row+x)&0x1) {
617 					writeSVG_drawModules(fp, x, y, 1, fg, fg_opacity);
618 				}
619 			}
620 		} else {
621 			/* simple RLE */
622 			pen = 0;
623 			x0  = 0;
624 			for(x = 0; x < qrcode->width; x++) {
625 				if( !pen ) {
626 					pen = *(row+x)&0x1;
627 					x0 = x;
628 				} else if(!(*(row+x)&0x1)) {
629 					writeSVG_drawModules(fp, x0, y, x-x0, fg, fg_opacity);
630 					pen = 0;
631 				}
632 			}
633 			if( pen ) {
634 				writeSVG_drawModules(fp, x0, y, qrcode->width - x0, fg, fg_opacity);
635 			}
636 		}
637 	}
638 
639 	if(svg_path) {
640 		fputs("\"/>\n", fp);
641 	} else {
642 		/* Close QR data viewbox */
643 		fputs("\t\t</g>\n", fp);
644 	}
645 
646 	/* Close group */
647 	fputs("\t</g>\n", fp);
648 
649 	/* Close SVG code */
650 	fputs("</svg>\n", fp);
651 	fclose(fp);
652 
653 	return 0;
654 }
655 
writeXPM(const QRcode * qrcode,const char * outfile)656 static int writeXPM(const QRcode *qrcode, const char *outfile)
657 {
658 	FILE *fp;
659 	int x, xx, y, yy, realwidth, realmargin;
660 	char *row;
661 	char fg[7], bg[7];
662 	unsigned char *p;
663 
664 	fp = openFile(outfile);
665 
666 	realwidth = (qrcode->width + margin * 2) * size;
667 	realmargin = margin * size;
668 
669 	row = malloc((size_t)realwidth + 1);
670 	if (!row ) {
671 		fprintf(stderr, "Failed to allocate memory.\n");
672 		exit(EXIT_FAILURE);
673 	}
674 
675 	snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1],  fg_color[2]);
676 	snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1],  bg_color[2]);
677 
678 	fputs("/* XPM */\n", fp);
679 	fputs("static const char *const qrcode_xpm[] = {\n", fp);
680 	fputs("/* width height ncolors chars_per_pixel */\n", fp);
681 	fprintf(fp, "\"%d %d 2 1\",\n", realwidth, realwidth);
682 
683 	fputs("/* colors */\n", fp);
684 	fprintf(fp, "\"F c #%s\",\n", fg);
685 	fprintf(fp, "\"B c #%s\",\n", bg);
686 
687 	fputs("/* pixels */\n", fp);
688 	memset(row, 'B', (size_t)realwidth);
689 	row[realwidth] = '\0';
690 
691 	for (y = 0; y < realmargin; y++) {
692 		fprintf(fp, "\"%s\",\n", row);
693 	}
694 
695 	p = qrcode->data;
696 	for (y = 0; y < qrcode->width; y++) {
697 		for (yy = 0; yy < size; yy++) {
698 			fputs("\"", fp);
699 
700 			for (x = 0; x < margin; x++) {
701 				for (xx = 0; xx < size; xx++) {
702 					fputs("B", fp);
703 				}
704 			}
705 
706 			for (x = 0; x < qrcode->width; x++) {
707 				for (xx = 0; xx < size; xx++) {
708 					if (p[(y * qrcode->width) + x] & 0x1) {
709 						fputs("F", fp);
710 					} else {
711 						fputs("B", fp);
712 					}
713 				}
714 			}
715 
716 			for (x = 0; x < margin; x++) {
717 				for (xx = 0; xx < size; xx++) {
718 					fputs("B", fp);
719 				}
720 			}
721 
722 			fputs("\",\n", fp);
723 		}
724 	}
725 
726 	for (y = 0; y < realmargin; y++) {
727 		fprintf(fp, "\"%s\"%s\n", row, y < (size - 1) ? "," : "};");
728 	}
729 
730 	free(row);
731 	fclose(fp);
732 
733 	return 0;
734 }
735 
writeANSI_margin(FILE * fp,int realwidth,char * buffer,const char * white,int white_s)736 static void writeANSI_margin(FILE* fp, int realwidth,
737                              char* buffer, const char* white, int white_s )
738 {
739 	int y;
740 
741 	strncpy(buffer, white, (size_t)white_s);
742 	memset(buffer + white_s, ' ', (size_t)realwidth * 2);
743 	strcpy(buffer + white_s + realwidth * 2, "\033[0m\n"); // reset to default colors
744 	for(y = 0; y < margin; y++ ){
745 		fputs(buffer, fp);
746 	}
747 }
748 
writeANSI(const QRcode * qrcode,const char * outfile)749 static int writeANSI(const QRcode *qrcode, const char *outfile)
750 {
751 	FILE *fp;
752 	unsigned char *row, *p;
753 	int x, y;
754 	int realwidth;
755 	int last;
756 
757 	const char *white, *black;
758 	char *buffer;
759 	int white_s, black_s, buffer_s;
760 
761 	if(image_type == ANSI256_TYPE){
762 		/* codes for 256 color compatible terminals */
763 		white = "\033[48;5;231m";
764 		white_s = 11;
765 		black = "\033[48;5;16m";
766 		black_s = 10;
767 	} else {
768 		white = "\033[47m";
769 		white_s = 5;
770 		black = "\033[40m";
771 		black_s = 5;
772 	}
773 
774 	size = 1;
775 
776 	fp = openFile(outfile);
777 
778 	realwidth = (qrcode->width + margin * 2) * size;
779 	buffer_s = (realwidth * white_s) * 2;
780 	buffer = (char *)malloc((size_t)buffer_s);
781 	if(buffer == NULL) {
782 		fprintf(stderr, "Failed to allocate memory.\n");
783 		exit(EXIT_FAILURE);
784 	}
785 
786 	/* top margin */
787 	writeANSI_margin(fp, realwidth, buffer, white, white_s);
788 
789 	/* data */
790 	p = qrcode->data;
791 	for(y = 0; y < qrcode->width; y++) {
792 		row = (p+(y*qrcode->width));
793 
794 		memset(buffer, 0, (size_t)buffer_s);
795 		strncpy(buffer, white, (size_t)white_s);
796 		for(x = 0; x < margin; x++ ){
797 			strncat(buffer, "  ", 2);
798 		}
799 		last = 0;
800 
801 		for(x = 0; x < qrcode->width; x++) {
802 			if(*(row+x)&0x1) {
803 				if( last != 1 ){
804 					strncat(buffer, black, (size_t)black_s);
805 					last = 1;
806 				}
807 			} else if( last != 0 ){
808 				strncat(buffer, white, (size_t)white_s);
809 				last = 0;
810 			}
811 			strncat(buffer, "  ", 2);
812 		}
813 
814 		if( last != 0 ){
815 			strncat(buffer, white, (size_t)white_s);
816 		}
817 		for(x = 0; x < margin; x++ ){
818 			strncat(buffer, "  ", 2);
819 		}
820 		strncat(buffer, "\033[0m\n", 5);
821 		fputs(buffer, fp);
822 	}
823 
824 	/* bottom margin */
825 	writeANSI_margin(fp, realwidth, buffer, white, white_s);
826 
827 	fclose(fp);
828 	free(buffer);
829 
830 	return 0;
831 }
832 
writeUTF8_margin(FILE * fp,int realwidth,const char * white,const char * reset,const char * full)833 static void writeUTF8_margin(FILE* fp, int realwidth, const char* white,
834                              const char *reset, const char* full)
835 {
836 	int x, y;
837 
838 	for (y = 0; y < margin/2; y++) {
839 		fputs(white, fp);
840 		for (x = 0; x < realwidth; x++)
841 			fputs(full, fp);
842 		fputs(reset, fp);
843 		fputc('\n', fp);
844 	}
845 }
846 
writeUTF8(const QRcode * qrcode,const char * outfile,int use_ansi,int invert)847 static int writeUTF8(const QRcode *qrcode, const char *outfile, int use_ansi, int invert)
848 {
849 	FILE *fp;
850 	int x, y;
851 	int realwidth;
852 	const char *white, *reset;
853 	const char *empty, *lowhalf, *uphalf, *full;
854 
855 	empty = " ";
856 	lowhalf = "\342\226\204";
857 	uphalf = "\342\226\200";
858 	full = "\342\226\210";
859 
860 	if (invert) {
861 		const char *tmp;
862 
863 		tmp = empty;
864 		empty = full;
865 		full = tmp;
866 
867 		tmp = lowhalf;
868 		lowhalf = uphalf;
869 		uphalf = tmp;
870 	}
871 
872 	if (use_ansi){
873 		if (use_ansi == 2) {
874 			white = "\033[38;5;231m\033[48;5;16m";
875 		} else {
876 			white = "\033[40;37;1m";
877 		}
878 		reset = "\033[0m";
879 	} else {
880 		white = "";
881 		reset = "";
882 	}
883 
884 	fp = openFile(outfile);
885 
886 	realwidth = (qrcode->width + margin * 2);
887 
888 	/* top margin */
889 	writeUTF8_margin(fp, realwidth, white, reset, full);
890 
891 	/* data */
892 	for(y = 0; y < qrcode->width; y += 2) {
893 		unsigned char *row1, *row2;
894 		row1 = qrcode->data + y*qrcode->width;
895 		row2 = row1 + qrcode->width;
896 
897 		fputs(white, fp);
898 
899 		for (x = 0; x < margin; x++) {
900 			fputs(full, fp);
901 		}
902 
903 		for (x = 0; x < qrcode->width; x++) {
904 			if(row1[x] & 1) {
905 				if(y < qrcode->width - 1 && row2[x] & 1) {
906 					fputs(empty, fp);
907 				} else {
908 					fputs(lowhalf, fp);
909 				}
910 			} else if(y < qrcode->width - 1 && row2[x] & 1) {
911 				fputs(uphalf, fp);
912 			} else {
913 				fputs(full, fp);
914 			}
915 		}
916 
917 		for (x = 0; x < margin; x++)
918 			fputs(full, fp);
919 
920 		fputs(reset, fp);
921 		fputc('\n', fp);
922 	}
923 
924 	/* bottom margin */
925 	writeUTF8_margin(fp, realwidth, white, reset, full);
926 
927 	fclose(fp);
928 
929 	return 0;
930 }
931 
writeASCII_margin(FILE * fp,int realwidth,char * buffer,int invert)932 static void writeASCII_margin(FILE* fp, int realwidth, char* buffer, int invert)
933 {
934 	int y, h;
935 
936 	h = margin;
937 
938 	memset(buffer, (invert?'#':' '), (size_t)realwidth);
939 	buffer[realwidth] = '\n';
940 	buffer[realwidth + 1] = '\0';
941 	for(y = 0; y < h; y++ ){
942 		fputs(buffer, fp);
943 	}
944 }
945 
writeASCII(const QRcode * qrcode,const char * outfile,int invert)946 static int writeASCII(const QRcode *qrcode, const char *outfile, int invert)
947 {
948 	FILE *fp;
949 	unsigned char *row;
950 	int x, y;
951 	int realwidth;
952 	char *buffer, *p;
953 	int buffer_s;
954 	char black = '#';
955 	char white = ' ';
956 
957 	if(invert) {
958 		black = ' ';
959 		white = '#';
960 	}
961 
962 	size = 1;
963 
964 	fp = openFile(outfile);
965 
966 	realwidth = (qrcode->width + margin * 2) * 2;
967 	buffer_s = realwidth + 2;
968 	buffer = (char *)malloc((size_t)buffer_s);
969 	if(buffer == NULL) {
970 		fprintf(stderr, "Failed to allocate memory.\n");
971 		exit(EXIT_FAILURE);
972 	}
973 
974 	/* top margin */
975 	writeASCII_margin(fp, realwidth, buffer, invert);
976 
977 	/* data */
978 	for(y = 0; y < qrcode->width; y++) {
979 		row = qrcode->data+(y*qrcode->width);
980 		p = buffer;
981 
982 		memset(p, white, (size_t)margin * 2);
983 		p += margin * 2;
984 
985 		for(x = 0; x < qrcode->width; x++) {
986 			if(row[x]&0x1) {
987 				*p++ = black;
988 				*p++ = black;
989 			} else {
990 				*p++ = white;
991 				*p++ = white;
992 			}
993 		}
994 
995 		memset(p, white, (size_t)margin * 2);
996 		p += margin * 2;
997 		*p++ = '\n';
998 		*p++ = '\0';
999 		fputs( buffer, fp );
1000 	}
1001 
1002 	/* bottom margin */
1003 	writeASCII_margin(fp, realwidth, buffer, invert);
1004 
1005 	fclose(fp);
1006 	free(buffer);
1007 
1008 	return 0;
1009 }
1010 
encode(const unsigned char * intext,int length)1011 static QRcode *encode(const unsigned char *intext, int length)
1012 {
1013 	QRcode *code;
1014 
1015 	if(micro) {
1016 		if(eightbit) {
1017 			code = QRcode_encodeDataMQR(length, intext, version, level);
1018 		} else {
1019 			code = QRcode_encodeStringMQR((char *)intext, version, level, hint, casesensitive);
1020 		}
1021 	} else if(eightbit) {
1022 		code = QRcode_encodeData(length, intext, version, level);
1023 	} else {
1024 		code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive);
1025 	}
1026 
1027 	return code;
1028 }
1029 
qrencode(const unsigned char * intext,int length,const char * outfile)1030 static void qrencode(const unsigned char *intext, int length, const char *outfile)
1031 {
1032 	QRcode *qrcode;
1033 
1034 	qrcode = encode(intext, length);
1035 	if(qrcode == NULL) {
1036 		if(errno == ERANGE) {
1037 			fprintf(stderr, "Failed to encode the input data: Input data too large\n");
1038 		} else {
1039 			perror("Failed to encode the input data");
1040 		}
1041 		exit(EXIT_FAILURE);
1042 	}
1043 	if(strict_versioning && version > 0 && qrcode->version != version) {
1044 		fprintf(stderr, "Failed to encode the input data: Input data too large\n");
1045 		exit(EXIT_FAILURE);
1046 	}
1047 
1048 	if(verbose) {
1049 		fprintf(stderr, "File: %s, Version: %d\n", (outfile!=NULL)?outfile:"(stdout)", qrcode->version);
1050 	}
1051 
1052 	switch(image_type) {
1053 		case PNG_TYPE:
1054 		case PNG32_TYPE:
1055 			writePNG(qrcode, outfile, image_type);
1056 			break;
1057 		case EPS_TYPE:
1058 			writeEPS(qrcode, outfile);
1059 			break;
1060 		case SVG_TYPE:
1061 			writeSVG(qrcode, outfile);
1062 			break;
1063 		case XPM_TYPE:
1064 			writeXPM(qrcode, outfile);
1065 			break;
1066 		case ANSI_TYPE:
1067 		case ANSI256_TYPE:
1068 			writeANSI(qrcode, outfile);
1069 			break;
1070 		case ASCIIi_TYPE:
1071 			writeASCII(qrcode, outfile,  1);
1072 			break;
1073 		case ASCII_TYPE:
1074 			writeASCII(qrcode, outfile,  0);
1075 			break;
1076 		case UTF8_TYPE:
1077 			writeUTF8(qrcode, outfile, 0, 0);
1078 			break;
1079 		case ANSIUTF8_TYPE:
1080 			writeUTF8(qrcode, outfile, 1, 0);
1081 			break;
1082 		case ANSI256UTF8_TYPE:
1083 			writeUTF8(qrcode, outfile, 2, 0);
1084 			break;
1085 		case UTF8i_TYPE:
1086 			writeUTF8(qrcode, outfile, 0, 1);
1087 			break;
1088 		case ANSIUTF8i_TYPE:
1089 			writeUTF8(qrcode, outfile, 1, 1);
1090 			break;
1091 		default:
1092 			fprintf(stderr, "Unknown image type.\n");
1093 			exit(EXIT_FAILURE);
1094 	}
1095 
1096 	QRcode_free(qrcode);
1097 }
1098 
encodeStructured(const unsigned char * intext,int length)1099 static QRcode_List *encodeStructured(const unsigned char *intext, int length)
1100 {
1101 	QRcode_List *list;
1102 
1103 	if(eightbit) {
1104 		list = QRcode_encodeDataStructured(length, intext, version, level);
1105 	} else {
1106 		list = QRcode_encodeStringStructured((char *)intext, version, level, hint, casesensitive);
1107 	}
1108 
1109 	return list;
1110 }
1111 
qrencodeStructured(const unsigned char * intext,int length,const char * outfile)1112 static void qrencodeStructured(const unsigned char *intext, int length, const char *outfile)
1113 {
1114 	QRcode_List *qrlist, *p;
1115 	char filename[FILENAME_MAX];
1116 	char *base, *q, *suffix = NULL;
1117 	const char *type_suffix;
1118 	int i = 1;
1119 	size_t suffix_size;
1120 
1121 	switch(image_type) {
1122 		case PNG_TYPE:
1123 			type_suffix = ".png";
1124 			break;
1125 		case EPS_TYPE:
1126 			type_suffix = ".eps";
1127 			break;
1128 		case SVG_TYPE:
1129 			type_suffix = ".svg";
1130 			break;
1131 		case XPM_TYPE:
1132 			type_suffix = ".xpm";
1133 			break;
1134 		case ANSI_TYPE:
1135 		case ANSI256_TYPE:
1136 		case ASCII_TYPE:
1137 		case UTF8_TYPE:
1138 		case ANSIUTF8_TYPE:
1139 		case UTF8i_TYPE:
1140 		case ANSIUTF8i_TYPE:
1141 			type_suffix = ".txt";
1142 			break;
1143 		default:
1144 			fprintf(stderr, "Unknown image type.\n");
1145 			exit(EXIT_FAILURE);
1146 	}
1147 
1148 	if(outfile == NULL) {
1149 		fprintf(stderr, "An output filename must be specified to store the structured images.\n");
1150 		exit(EXIT_FAILURE);
1151 	}
1152 	base = strdup(outfile);
1153 	if(base == NULL) {
1154 		fprintf(stderr, "Failed to allocate memory.\n");
1155 		exit(EXIT_FAILURE);
1156 	}
1157 	suffix_size = strlen(type_suffix);
1158 	if(strlen(base) > suffix_size) {
1159 		q = base + strlen(base) - suffix_size;
1160 		if(strcasecmp(type_suffix, q) == 0) {
1161 			suffix = strdup(q);
1162 			*q = '\0';
1163 		}
1164 	}
1165 
1166 	qrlist = encodeStructured(intext, length);
1167 	if(qrlist == NULL) {
1168 		if(errno == ERANGE) {
1169 			fprintf(stderr, "Failed to encode the input data: Input data too large\n");
1170 		} else {
1171 			perror("Failed to encode the input data");
1172 		}
1173 		exit(EXIT_FAILURE);
1174 	}
1175 
1176 	for(p = qrlist; p != NULL; p = p->next) {
1177 		if(p->code == NULL) {
1178 			fprintf(stderr, "Failed to encode the input data.\n");
1179 			exit(EXIT_FAILURE);
1180 		}
1181 		if(suffix) {
1182 			snprintf(filename, FILENAME_MAX, "%s-%02d%s", base, i, suffix);
1183 		} else {
1184 			snprintf(filename, FILENAME_MAX, "%s-%02d", base, i);
1185 		}
1186 
1187 		if(verbose) {
1188 			fprintf(stderr, "File: %s, Version: %d\n", filename, p->code->version);
1189 		}
1190 
1191 		switch(image_type) {
1192 			case PNG_TYPE:
1193 			case PNG32_TYPE:
1194 				writePNG(p->code, filename, image_type);
1195 				break;
1196 			case EPS_TYPE:
1197 				writeEPS(p->code, filename);
1198 				break;
1199 			case SVG_TYPE:
1200 				writeSVG(p->code, filename);
1201 				break;
1202 			case XPM_TYPE:
1203 				writeXPM(p->code, filename);
1204 				break;
1205 			case ANSI_TYPE:
1206 			case ANSI256_TYPE:
1207 				writeANSI(p->code, filename);
1208 				break;
1209 			case ASCIIi_TYPE:
1210 				writeASCII(p->code, filename, 1);
1211 				break;
1212 			case ASCII_TYPE:
1213 				writeASCII(p->code, filename, 0);
1214 				break;
1215 			case UTF8_TYPE:
1216 				writeUTF8(p->code, filename, 0, 0);
1217 				break;
1218 			case ANSIUTF8_TYPE:
1219 				writeUTF8(p->code, filename, 0, 0);
1220 				break;
1221 			case ANSI256UTF8_TYPE:
1222 				writeUTF8(p->code, filename, 0, 0);
1223 				break;
1224 			case UTF8i_TYPE:
1225 				writeUTF8(p->code, filename, 0, 1);
1226 				break;
1227 			case ANSIUTF8i_TYPE:
1228 				writeUTF8(p->code, filename, 0, 1);
1229 				break;
1230 
1231 			default:
1232 				fprintf(stderr, "Unknown image type.\n");
1233 				exit(EXIT_FAILURE);
1234 		}
1235 		i++;
1236 	}
1237 
1238 	free(base);
1239 	if(suffix) {
1240 		free(suffix);
1241 	}
1242 
1243 	QRcode_List_free(qrlist);
1244 }
1245 
main(int argc,char ** argv)1246 int main(int argc, char **argv)
1247 {
1248 	int opt, lindex = -1;
1249 	char *outfile = NULL, *infile = NULL;
1250 	unsigned char *intext = NULL;
1251 	int length = 0;
1252 	FILE *fp;
1253 
1254 	while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
1255 		switch(opt) {
1256 			case 'h':
1257 				if(lindex == 0) {
1258 					usage(1, 1, EXIT_SUCCESS);
1259 				} else {
1260 					usage(1, 0, EXIT_SUCCESS);
1261 				}
1262 				exit(EXIT_SUCCESS);
1263 			case 'o':
1264 				outfile = optarg;
1265 				break;
1266 			case 'r':
1267 				infile = optarg;
1268 				break;
1269 			case 's':
1270 				size = atoi(optarg);
1271 				if(size <= 0) {
1272 					fprintf(stderr, "Invalid size: %d\n", size);
1273 					exit(EXIT_FAILURE);
1274 				}
1275 				break;
1276 			case 'v':
1277 				version = atoi(optarg);
1278 				if(version < 0) {
1279 					fprintf(stderr, "Invalid version: %d\n", version);
1280 					exit(EXIT_FAILURE);
1281 				}
1282 				break;
1283 			case 'l':
1284 				switch(*optarg) {
1285 					case 'l':
1286 					case 'L':
1287 						level = QR_ECLEVEL_L;
1288 						break;
1289 					case 'm':
1290 					case 'M':
1291 						level = QR_ECLEVEL_M;
1292 						break;
1293 					case 'q':
1294 					case 'Q':
1295 						level = QR_ECLEVEL_Q;
1296 						break;
1297 					case 'h':
1298 					case 'H':
1299 						level = QR_ECLEVEL_H;
1300 						break;
1301 					default:
1302 						fprintf(stderr, "Invalid level: %s\n", optarg);
1303 						exit(EXIT_FAILURE);
1304 				}
1305 				break;
1306 			case 'm':
1307 				margin = atoi(optarg);
1308 				if(margin < 0) {
1309 					fprintf(stderr, "Invalid margin: %d\n", margin);
1310 					exit(EXIT_FAILURE);
1311 				}
1312 				break;
1313 			case 'd':
1314 				dpi = atoi(optarg);
1315 				if( dpi < 0 ) {
1316 					fprintf(stderr, "Invalid DPI: %d\n", dpi);
1317 					exit(EXIT_FAILURE);
1318 				}
1319 				break;
1320 			case 't':
1321 				if(strcasecmp(optarg, "png32") == 0) {
1322 					image_type = PNG32_TYPE;
1323 				} else if(strcasecmp(optarg, "png") == 0) {
1324 					image_type = PNG_TYPE;
1325 				} else if(strcasecmp(optarg, "eps") == 0) {
1326 					image_type = EPS_TYPE;
1327 				} else if(strcasecmp(optarg, "svg") == 0) {
1328 					image_type = SVG_TYPE;
1329 				} else if(strcasecmp(optarg, "xpm") == 0) {
1330 					image_type = XPM_TYPE;
1331 				} else if(strcasecmp(optarg, "ansi") == 0) {
1332 					image_type = ANSI_TYPE;
1333 				} else if(strcasecmp(optarg, "ansi256") == 0) {
1334 					image_type = ANSI256_TYPE;
1335 				} else if(strcasecmp(optarg, "asciii") == 0) {
1336 					image_type = ASCIIi_TYPE;
1337 				} else if(strcasecmp(optarg, "ascii") == 0) {
1338 					image_type = ASCII_TYPE;
1339 				} else if(strcasecmp(optarg, "utf8") == 0) {
1340 					image_type = UTF8_TYPE;
1341 				} else if(strcasecmp(optarg, "ansiutf8") == 0) {
1342 					image_type = ANSIUTF8_TYPE;
1343 				} else if(strcasecmp(optarg, "ansi256utf8") == 0) {
1344 					image_type = ANSI256UTF8_TYPE;
1345 				} else if(strcasecmp(optarg, "utf8i") == 0) {
1346 					image_type = UTF8i_TYPE;
1347 				} else if(strcasecmp(optarg, "ansiutf8i") == 0) {
1348 					image_type = ANSIUTF8i_TYPE;
1349 				} else {
1350 					fprintf(stderr, "Invalid image type: %s\n", optarg);
1351 					exit(EXIT_FAILURE);
1352 				}
1353 				break;
1354 			case 'S':
1355 				structured = 1;
1356 				break;
1357 			case 'k':
1358 				hint = QR_MODE_KANJI;
1359 				break;
1360 			case 'c':
1361 				casesensitive = 1;
1362 				break;
1363 			case 'i':
1364 				casesensitive = 0;
1365 				break;
1366 			case '8':
1367 				eightbit = 1;
1368 				break;
1369 			case 'M':
1370 				micro = 1;
1371 				break;
1372 			case 'f':
1373 				if(color_set(fg_color, optarg)) {
1374 					fprintf(stderr, "Invalid foreground color value.\n");
1375 					exit(EXIT_FAILURE);
1376 				}
1377 				break;
1378 			case 'b':
1379 				if(color_set(bg_color, optarg)) {
1380 					fprintf(stderr, "Invalid background color value.\n");
1381 					exit(EXIT_FAILURE);
1382 				}
1383 				break;
1384 			case 'V':
1385 				usage(0, 0, EXIT_SUCCESS);
1386 				exit(EXIT_SUCCESS);
1387 			case 0:
1388 				break;
1389 			default:
1390 				fprintf(stderr, "Try \"qrencode --help\" for more information.\n");
1391 				exit(EXIT_FAILURE);
1392 		}
1393 	}
1394 
1395 	if(argc == 1) {
1396 		usage(1, 0, EXIT_FAILURE);
1397 		exit(EXIT_FAILURE);
1398 	}
1399 
1400 	if(outfile == NULL && image_type == PNG_TYPE) {
1401 		fprintf(stderr, "No output filename is given.\n");
1402 		exit(EXIT_FAILURE);
1403 	}
1404 
1405 	if(optind < argc) {
1406 		intext = (unsigned char *)argv[optind];
1407 		length = strlen((char *)intext);
1408 	}
1409 	if(intext == NULL) {
1410 		fp = infile == NULL ? stdin : fopen(infile,"r");
1411 		if(fp == 0) {
1412 			fprintf(stderr, "Cannot read input file %s.\n", infile);
1413 			exit(EXIT_FAILURE);
1414 		}
1415 		intext = readFile(fp,&length);
1416 
1417 	}
1418 
1419 	if(micro && version > MQRSPEC_VERSION_MAX) {
1420 		fprintf(stderr, "Version number should be less or equal to %d.\n", MQRSPEC_VERSION_MAX);
1421 		exit(EXIT_FAILURE);
1422 	} else if(!micro && version > QRSPEC_VERSION_MAX) {
1423 		fprintf(stderr, "Version number should be less or equal to %d.\n", QRSPEC_VERSION_MAX);
1424 		exit(EXIT_FAILURE);
1425 	}
1426 
1427 	if(margin < 0) {
1428 		if(micro) {
1429 			margin = 2;
1430 		} else {
1431 			margin = 4;
1432 		}
1433 	}
1434 
1435 	if(micro) {
1436 		if(structured) {
1437 			fprintf(stderr, "Micro QR Code does not support structured symbols.\n");
1438 			exit(EXIT_FAILURE);
1439 		}
1440 	}
1441 
1442 	if(structured) {
1443 		if(version == 0) {
1444 			fprintf(stderr, "Version number must be specified to encode structured symbols.\n");
1445 			exit(EXIT_FAILURE);
1446 		}
1447 		qrencodeStructured(intext, length, outfile);
1448 	} else {
1449 		qrencode(intext, length, outfile);
1450 	}
1451 
1452 	return 0;
1453 }
1454