| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: t -*-*/ | 
 | 2 |  | 
 | 3 | /** | 
 | 4 |  * qrencode - QR Code encoder | 
 | 5 |  * | 
 | 6 |  * QR Code encoding tool | 
 | 7 |  * Copyright (C) 2006-2012 Kentaro Fukuchi <kentaro@fukuchi.org> | 
 | 8 |  * | 
 | 9 |  * This library is free software; you can redistribute it and/or | 
 | 10 |  * modify it under the terms of the GNU Lesser General Public | 
 | 11 |  * License as published by the Free Software Foundation; either | 
 | 12 |  * version 2.1 of the License, or any later version. | 
 | 13 |  * | 
 | 14 |  * This library is distributed in the hope that it will be useful, | 
 | 15 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 
 | 17 |  * Lesser General Public License for more details. | 
 | 18 |  * | 
 | 19 |  * You should have received a copy of the GNU Lesser General Public | 
 | 20 |  * License along with this library; if not, write to the Free Software | 
 | 21 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
 | 22 |  */ | 
 | 23 |  | 
 | 24 | #if HAVE_CONFIG_H | 
 | 25 | # include "config.h" | 
 | 26 | #endif | 
 | 27 | #include <stdio.h> | 
 | 28 | #include <stdlib.h> | 
 | 29 | #include <string.h> | 
 | 30 | #include <png.h> | 
 | 31 | #include <getopt.h> | 
 | 32 |  | 
 | 33 | #include "qrencode.h" | 
 | 34 |  | 
 | 35 | #define INCHES_PER_METER (100.0/2.54) | 
 | 36 |  | 
 | 37 | static int casesensitive = 1; | 
 | 38 | static int eightbit = 0; | 
 | 39 | static int version = 0; | 
 | 40 | static int size = 3; | 
 | 41 | static int margin = -1; | 
 | 42 | static int dpi = 72; | 
 | 43 | static int structured = 0; | 
 | 44 | static int micro = 0; | 
 | 45 | static QRecLevel level = QR_ECLEVEL_L; | 
 | 46 | static QRencodeMode hint = QR_MODE_8; | 
 | 47 | static unsigned int fg_color[4] = {0, 0, 0, 255}; | 
 | 48 | static unsigned int bg_color[4] = {255, 255, 255, 255}; | 
 | 49 |  | 
 | 50 | enum imageType { | 
 | 51 | 	PNG_TYPE, | 
 | 52 | 	EPS_TYPE, | 
 | 53 | 	SVG_TYPE, | 
 | 54 | 	ANSI_TYPE, | 
 | 55 | 	ANSI256_TYPE, | 
 | 56 | 	ASCII_TYPE, | 
 | 57 | 	ASCIIi_TYPE, | 
 | 58 | 	UTF8_TYPE, | 
 | 59 | 	ANSIUTF8_TYPE | 
 | 60 | }; | 
 | 61 |  | 
 | 62 | static enum imageType image_type = PNG_TYPE; | 
 | 63 |  | 
 | 64 | static const struct option options[] = { | 
 | 65 | 	{"help"         , no_argument      , NULL, 'h'}, | 
 | 66 | 	{"output"       , required_argument, NULL, 'o'}, | 
 | 67 | 	{"level"        , required_argument, NULL, 'l'}, | 
 | 68 | 	{"size"         , required_argument, NULL, 's'}, | 
 | 69 | 	{"symversion"   , required_argument, NULL, 'v'}, | 
 | 70 | 	{"margin"       , required_argument, NULL, 'm'}, | 
 | 71 | 	{"dpi"          , required_argument, NULL, 'd'}, | 
 | 72 | 	{"type"         , required_argument, NULL, 't'}, | 
 | 73 | 	{"structured"   , no_argument      , NULL, 'S'}, | 
 | 74 | 	{"kanji"        , no_argument      , NULL, 'k'}, | 
 | 75 | 	{"casesensitive", no_argument      , NULL, 'c'}, | 
 | 76 | 	{"ignorecase"   , no_argument      , NULL, 'i'}, | 
 | 77 | 	{"8bit"         , no_argument      , NULL, '8'}, | 
 | 78 | 	{"micro"        , no_argument      , NULL, 'M'}, | 
 | 79 | 	{"foreground"	, required_argument, NULL, 'f'}, | 
 | 80 | 	{"background"	, required_argument, NULL, 'b'}, | 
 | 81 | 	{"version"      , no_argument      , NULL, 'V'}, | 
 | 82 | 	{NULL, 0, NULL, 0} | 
 | 83 | }; | 
 | 84 |  | 
 | 85 | static char* optstring = "ho:l:s:v:m:d:t:Skci8MV"; | 
 | 86 |  | 
 | 87 | static void usage(int help, int longopt) | 
 | 88 | { | 
 | 89 | 	fprintf(stderr, | 
 | 90 | "qrencode version %s\n" | 
 | 91 | "Copyright (C) 2006-2012 Kentaro Fukuchi\n", QRcode_APIVersionString()); | 
 | 92 | 	if(help) { | 
 | 93 | 		if(longopt) { | 
 | 94 | 			fprintf(stderr, | 
 | 95 | "Usage: qrencode [OPTION]... [STRING]\n" | 
 | 96 | "Encode input data in a QR Code and save as a PNG or EPS image.\n\n" | 
 | 97 | "  -h, --help   display the help message. -h displays only the help of short\n" | 
 | 98 | "               options.\n\n" | 
 | 99 | "  -o FILENAME, --output=FILENAME\n" | 
 | 100 | "               write image to FILENAME. If '-' is specified, the result\n" | 
 | 101 | "               will be output to standard output. If -S is given, structured\n" | 
 | 102 | "               symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n" | 
 | 103 | "               (suffix is removed from FILENAME, if specified)\n" | 
 | 104 | "  -s NUMBER, --size=NUMBER\n" | 
 | 105 | "               specify module size in dots (pixels). (default=3)\n\n" | 
 | 106 | "  -l {LMQH}, --level={LMQH}\n" | 
 | 107 | "               specify error correction level from L (lowest) to H (highest).\n" | 
 | 108 | "               (default=L)\n\n" | 
 | 109 | "  -v NUMBER, --symversion=NUMBER\n" | 
 | 110 | "               specify the version of the symbol. (default=auto)\n\n" | 
 | 111 | "  -m NUMBER, --margin=NUMBER\n" | 
 | 112 | "               specify the width of the margins. (default=4 (2 for Micro)))\n\n" | 
 | 113 | "  -d NUMBER, --dpi=NUMBER\n" | 
 | 114 | "               specify the DPI of the generated PNG. (default=72)\n\n" | 
 | 115 | "  -t {PNG,EPS,SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}, --type={PNG,EPS,\n" | 
 | 116 | "               SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}\n" | 
 | 117 | "               specify the type of the generated image. (default=PNG)\n\n" | 
 | 118 | "  -S, --structured\n" | 
 | 119 | "               make structured symbols. Version must be specified.\n\n" | 
 | 120 | "  -k, --kanji  assume that the input text contains kanji (shift-jis).\n\n" | 
 | 121 | "  -c, --casesensitive\n" | 
 | 122 | "               encode lower-case alphabet characters in 8-bit mode. (default)\n\n" | 
 | 123 | "  -i, --ignorecase\n" | 
 | 124 | "               ignore case distinctions and use only upper-case characters.\n\n" | 
 | 125 | "  -8, --8bit   encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n" | 
 | 126 | "  -M, --micro  encode in a Micro QR Code. (experimental)\n\n" | 
 | 127 | "  --foreground=RRGGBB[AA]\n" | 
 | 128 | "  --background=RRGGBB[AA]\n" | 
 | 129 | "               specify foreground/background color in hexadecimal notation.\n" | 
 | 130 | "               6-digit (RGB) or 8-digit (RGBA) form are supported.\n" | 
 | 131 | "               Color output support available only in PNG and SVG.\n" | 
 | 132 | "  -V, --version\n" | 
 | 133 | "               display the version number and copyrights of the qrencode.\n\n" | 
 | 134 | "  [STRING]     input data. If it is not specified, data will be taken from\n" | 
 | 135 | "               standard input.\n" | 
 | 136 | 			); | 
 | 137 | 		} else { | 
 | 138 | 			fprintf(stderr, | 
 | 139 | "Usage: qrencode [OPTION]... [STRING]\n" | 
 | 140 | "Encode input data in a QR Code and save as a PNG or EPS image.\n\n" | 
 | 141 | "  -h           display this message.\n" | 
 | 142 | "  --help       display the usage of long options.\n" | 
 | 143 | "  -o FILENAME  write image to FILENAME. If '-' is specified, the result\n" | 
 | 144 | "               will be output to standard output. If -S is given, structured\n" | 
 | 145 | "               symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n" | 
 | 146 | "               (suffix is removed from FILENAME, if specified)\n" | 
 | 147 | "  -s NUMBER    specify module size in dots (pixels). (default=3)\n" | 
 | 148 | "  -l {LMQH}    specify error correction level from L (lowest) to H (highest).\n" | 
 | 149 | "               (default=L)\n" | 
 | 150 | "  -v NUMBER    specify the version of the symbol. (default=auto)\n" | 
 | 151 | "  -m NUMBER    specify the width of the margins. (default=4 (2 for Micro))\n" | 
 | 152 | "  -d NUMBER    specify the DPI of the generated PNG. (default=72)\n" | 
 | 153 | "  -t {PNG,EPS,SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}\n" | 
 | 154 | "               specify the type of the generated image. (default=PNG)\n" | 
 | 155 | "  -S           make structured symbols. Version must be specified.\n" | 
 | 156 | "  -k           assume that the input text contains kanji (shift-jis).\n" | 
 | 157 | "  -c           encode lower-case alphabet characters in 8-bit mode. (default)\n" | 
 | 158 | "  -i           ignore case distinctions and use only upper-case characters.\n" | 
 | 159 | "  -8           encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n" | 
 | 160 | "  -M           encode in a Micro QR Code.\n" | 
 | 161 | "  --foreground=RRGGBB[AA]\n" | 
 | 162 | "  --background=RRGGBB[AA]\n" | 
 | 163 | "               specify foreground/background color in hexadecimal notation.\n" | 
 | 164 | "               6-digit (RGB) or 8-digit (RGBA) form are supported.\n" | 
 | 165 | "               Color output support available only in PNG and SVG.\n" | 
 | 166 | "  -V           display the version number and copyrights of the qrencode.\n" | 
 | 167 | "  [STRING]     input data. If it is not specified, data will be taken from\n" | 
 | 168 | "               standard input.\n" | 
 | 169 | 			); | 
 | 170 | 		} | 
 | 171 | 	} | 
 | 172 | } | 
 | 173 |  | 
 | 174 | static int color_set(unsigned int color[4], const char *value) | 
 | 175 | { | 
 | 176 | 	int len = strlen(value); | 
 | 177 | 	int count; | 
 | 178 | 	if(len == 6) { | 
 | 179 | 		count = sscanf(value, "%02x%02x%02x%n", &color[0], &color[1], &color[2], &len); | 
 | 180 | 		if(count < 3 || len != 6) { | 
 | 181 | 			return -1; | 
 | 182 | 		} | 
 | 183 | 		color[3] = 255; | 
 | 184 | 	} else if(len == 8) { | 
 | 185 | 		count = sscanf(value, "%02x%02x%02x%02x%n", &color[0], &color[1], &color[2], &color[3], &len); | 
 | 186 | 		if(count < 4 || len != 8) { | 
 | 187 | 			return -1; | 
 | 188 | 		} | 
 | 189 | 	} else { | 
 | 190 | 		return -1; | 
 | 191 | 	} | 
 | 192 | 	return 0; | 
 | 193 | } | 
 | 194 |  | 
 | 195 | #define MAX_DATA_SIZE (7090 * 16) /* from the specification */ | 
 | 196 | static unsigned char *readStdin(int *length) | 
 | 197 | { | 
 | 198 | 	unsigned char *buffer; | 
 | 199 | 	int ret; | 
 | 200 |  | 
 | 201 | 	buffer = (unsigned char *)malloc(MAX_DATA_SIZE + 1); | 
 | 202 | 	if(buffer == NULL) { | 
 | 203 | 		fprintf(stderr, "Memory allocation failed.\n"); | 
 | 204 | 		exit(EXIT_FAILURE); | 
 | 205 | 	} | 
 | 206 | 	ret = fread(buffer, 1, MAX_DATA_SIZE, stdin); | 
 | 207 | 	if(ret == 0) { | 
 | 208 | 		fprintf(stderr, "No input data.\n"); | 
 | 209 | 		exit(EXIT_FAILURE); | 
 | 210 | 	} | 
 | 211 | 	if(feof(stdin) == 0) { | 
 | 212 | 		fprintf(stderr, "Input data is too large.\n"); | 
 | 213 | 		exit(EXIT_FAILURE); | 
 | 214 | 	} | 
 | 215 |  | 
 | 216 | 	buffer[ret] = '\0'; | 
 | 217 | 	*length = ret; | 
 | 218 |  | 
 | 219 | 	return buffer; | 
 | 220 | } | 
 | 221 |  | 
 | 222 | static FILE *openFile(const char *outfile) | 
 | 223 | { | 
 | 224 | 	FILE *fp; | 
 | 225 |  | 
 | 226 | 	if(outfile == NULL || (outfile[0] == '-' && outfile[1] == '\0')) { | 
 | 227 | 		fp = stdout; | 
 | 228 | 	} else { | 
 | 229 | 		fp = fopen(outfile, "wb"); | 
 | 230 | 		if(fp == NULL) { | 
 | 231 | 			fprintf(stderr, "Failed to create file: %s\n", outfile); | 
 | 232 | 			perror(NULL); | 
 | 233 | 			exit(EXIT_FAILURE); | 
 | 234 | 		} | 
 | 235 | 	} | 
 | 236 |  | 
 | 237 | 	return fp; | 
 | 238 | } | 
 | 239 |  | 
 | 240 | static int writePNG(QRcode *qrcode, const char *outfile) | 
 | 241 | { | 
 | 242 | 	static FILE *fp; // avoid clobbering by setjmp. | 
 | 243 | 	png_structp png_ptr; | 
 | 244 | 	png_infop info_ptr; | 
 | 245 | 	png_colorp palette; | 
 | 246 | 	png_byte alpha_values[2]; | 
 | 247 | 	unsigned char *row, *p, *q; | 
 | 248 | 	int x, y, xx, yy, bit; | 
 | 249 | 	int realwidth; | 
 | 250 |  | 
 | 251 | 	realwidth = (qrcode->width + margin * 2) * size; | 
 | 252 | 	row = (unsigned char *)malloc((realwidth + 7) / 8); | 
 | 253 | 	if(row == NULL) { | 
 | 254 | 		fprintf(stderr, "Failed to allocate memory.\n"); | 
 | 255 | 		exit(EXIT_FAILURE); | 
 | 256 | 	} | 
 | 257 |  | 
 | 258 | 	if(outfile[0] == '-' && outfile[1] == '\0') { | 
 | 259 | 		fp = stdout; | 
 | 260 | 	} else { | 
 | 261 | 		fp = fopen(outfile, "wb"); | 
 | 262 | 		if(fp == NULL) { | 
 | 263 | 			fprintf(stderr, "Failed to create file: %s\n", outfile); | 
 | 264 | 			perror(NULL); | 
 | 265 | 			exit(EXIT_FAILURE); | 
 | 266 | 		} | 
 | 267 | 	} | 
 | 268 |  | 
 | 269 | 	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | 
 | 270 | 	if(png_ptr == NULL) { | 
 | 271 | 		fprintf(stderr, "Failed to initialize PNG writer.\n"); | 
 | 272 | 		exit(EXIT_FAILURE); | 
 | 273 | 	} | 
 | 274 |  | 
 | 275 | 	info_ptr = png_create_info_struct(png_ptr); | 
 | 276 | 	if(info_ptr == NULL) { | 
 | 277 | 		fprintf(stderr, "Failed to initialize PNG write.\n"); | 
 | 278 | 		exit(EXIT_FAILURE); | 
 | 279 | 	} | 
 | 280 |  | 
 | 281 | 	if(setjmp(png_jmpbuf(png_ptr))) { | 
 | 282 | 		png_destroy_write_struct(&png_ptr, &info_ptr); | 
 | 283 | 		fprintf(stderr, "Failed to write PNG image.\n"); | 
 | 284 | 		exit(EXIT_FAILURE); | 
 | 285 | 	} | 
 | 286 |  | 
 | 287 | 	palette = (png_colorp) malloc(sizeof(png_color) * 2); | 
 | 288 | 	palette[0].red   = fg_color[0]; | 
 | 289 | 	palette[0].green = fg_color[1]; | 
 | 290 | 	palette[0].blue  = fg_color[2]; | 
 | 291 | 	palette[1].red   = bg_color[0]; | 
 | 292 | 	palette[1].green = bg_color[1]; | 
 | 293 | 	palette[1].blue  = bg_color[2]; | 
 | 294 | 	alpha_values[0] = fg_color[3]; | 
 | 295 | 	alpha_values[1] = bg_color[3]; | 
 | 296 | 	png_set_PLTE(png_ptr, info_ptr, palette, 2); | 
 | 297 | 	png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL); | 
 | 298 |  | 
 | 299 | 	png_init_io(png_ptr, fp); | 
 | 300 | 	png_set_IHDR(png_ptr, info_ptr, | 
 | 301 | 			realwidth, realwidth, | 
 | 302 | 			1, | 
 | 303 | 			PNG_COLOR_TYPE_PALETTE, | 
 | 304 | 			PNG_INTERLACE_NONE, | 
 | 305 | 			PNG_COMPRESSION_TYPE_DEFAULT, | 
 | 306 | 			PNG_FILTER_TYPE_DEFAULT); | 
 | 307 | 	png_set_pHYs(png_ptr, info_ptr, | 
 | 308 | 			dpi * INCHES_PER_METER, | 
 | 309 | 			dpi * INCHES_PER_METER, | 
 | 310 | 			PNG_RESOLUTION_METER); | 
 | 311 | 	png_write_info(png_ptr, info_ptr); | 
 | 312 |  | 
 | 313 | 	/* top margin */ | 
 | 314 | 	memset(row, 0xff, (realwidth + 7) / 8); | 
 | 315 | 	for(y=0; y<margin * size; y++) { | 
 | 316 | 		png_write_row(png_ptr, row); | 
 | 317 | 	} | 
 | 318 |  | 
 | 319 | 	/* data */ | 
 | 320 | 	p = qrcode->data; | 
 | 321 | 	for(y=0; y<qrcode->width; y++) { | 
 | 322 | 		bit = 7; | 
 | 323 | 		memset(row, 0xff, (realwidth + 7) / 8); | 
 | 324 | 		q = row; | 
 | 325 | 		q += margin * size / 8; | 
 | 326 | 		bit = 7 - (margin * size % 8); | 
 | 327 | 		for(x=0; x<qrcode->width; x++) { | 
 | 328 | 			for(xx=0; xx<size; xx++) { | 
 | 329 | 				*q ^= (*p & 1) << bit; | 
 | 330 | 				bit--; | 
 | 331 | 				if(bit < 0) { | 
 | 332 | 					q++; | 
 | 333 | 					bit = 7; | 
 | 334 | 				} | 
 | 335 | 			} | 
 | 336 | 			p++; | 
 | 337 | 		} | 
 | 338 | 		for(yy=0; yy<size; yy++) { | 
 | 339 | 			png_write_row(png_ptr, row); | 
 | 340 | 		} | 
 | 341 | 	} | 
 | 342 | 	/* bottom margin */ | 
 | 343 | 	memset(row, 0xff, (realwidth + 7) / 8); | 
 | 344 | 	for(y=0; y<margin * size; y++) { | 
 | 345 | 		png_write_row(png_ptr, row); | 
 | 346 | 	} | 
 | 347 |  | 
 | 348 | 	png_write_end(png_ptr, info_ptr); | 
 | 349 | 	png_destroy_write_struct(&png_ptr, &info_ptr); | 
 | 350 |  | 
 | 351 | 	fclose(fp); | 
 | 352 | 	free(row); | 
 | 353 | 	if(palette != NULL) | 
 | 354 | 	{ | 
 | 355 | 		free(palette); | 
 | 356 | 	} | 
 | 357 | 	return 0; | 
 | 358 | } | 
 | 359 |  | 
 | 360 | static int writeEPS(QRcode *qrcode, const char *outfile) | 
 | 361 | { | 
 | 362 | 	FILE *fp; | 
 | 363 | 	unsigned char *row, *p; | 
 | 364 | 	int x, y, yy; | 
 | 365 | 	int realwidth; | 
 | 366 |  | 
 | 367 | 	fp = openFile(outfile); | 
 | 368 |     | 
 | 369 | 	realwidth = (qrcode->width + margin * 2) * size; | 
 | 370 | 	/* EPS file header */ | 
 | 371 | 	fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n" | 
 | 372 | 				"%%%%BoundingBox: 0 0 %d %d\n" | 
 | 373 | 				"%%%%Pages: 1 1\n" | 
 | 374 | 				"%%%%EndComments\n", realwidth, realwidth); | 
 | 375 | 	/* draw point */ | 
 | 376 | 	fprintf(fp, "/p { " | 
 | 377 | 				"moveto " | 
 | 378 | 				"0 1 rlineto " | 
 | 379 | 				"1 0 rlineto " | 
 | 380 | 				"0 -1 rlineto " | 
 | 381 | 				"fill " | 
 | 382 | 				"} bind def " | 
 | 383 | 				"%d %d scale ", size, size); | 
 | 384 | 	 | 
 | 385 | 	/* data */ | 
 | 386 | 	p = qrcode->data; | 
 | 387 | 	for(y=0; y<qrcode->width; y++) { | 
 | 388 | 		row = (p+(y*qrcode->width)); | 
 | 389 | 		yy = (margin + qrcode->width - y - 1); | 
 | 390 | 		 | 
 | 391 | 		for(x=0; x<qrcode->width; x++) { | 
 | 392 | 			if(*(row+x)&0x1) { | 
 | 393 | 				fprintf(fp, "%d %d p ", margin + x,  yy); | 
 | 394 | 			} | 
 | 395 | 		} | 
 | 396 | 	} | 
 | 397 |  | 
 | 398 | 	fprintf(fp, "\n%%%%EOF\n"); | 
 | 399 | 	fclose(fp); | 
 | 400 |  | 
 | 401 | 	return 0; | 
 | 402 | } | 
 | 403 |  | 
 | 404 | static void writeSVG_writeRect(FILE *fp, int x, int y, int width, char* col, float opacity) | 
 | 405 | { | 
 | 406 | 	if(fg_color[3] != 255) { | 
 | 407 | 		fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\ | 
 | 408 | 				"fill=\"#%s\" fill-opacity=\"%f\" />\n",  | 
 | 409 | 				x, y, width, col, opacity ); | 
 | 410 | 	} else { | 
 | 411 | 		fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\ | 
 | 412 | 				"fill=\"#%s\" />\n",  | 
 | 413 | 				x, y, width, col ); | 
 | 414 | 	} | 
 | 415 | } | 
 | 416 |  | 
 | 417 | static int writeSVG( QRcode *qrcode, const char *outfile ) | 
 | 418 | { | 
 | 419 | 	FILE *fp; | 
 | 420 | 	unsigned char *row, *p; | 
 | 421 | 	int x, y, x0, pen; | 
 | 422 | 	int symwidth, realwidth; | 
 | 423 | 	float scale; | 
 | 424 | 	char fg[7], bg[7]; | 
 | 425 | 	float fg_opacity; | 
 | 426 | 	float bg_opacity; | 
 | 427 |  | 
 | 428 | 	fp = openFile(outfile); | 
 | 429 |  | 
 | 430 | 	scale = dpi * INCHES_PER_METER / 100.0; | 
 | 431 |  | 
 | 432 | 	symwidth = qrcode->width + margin * 2; | 
 | 433 | 	realwidth = symwidth * size; | 
 | 434 |  | 
 | 435 | 	snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1],  fg_color[2]); | 
 | 436 | 	snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1],  bg_color[2]); | 
 | 437 | 	fg_opacity = (float)fg_color[3] / 255; | 
 | 438 | 	bg_opacity = (float)bg_color[3] / 255; | 
 | 439 |  | 
 | 440 | 	/* XML declaration */ | 
 | 441 | 	fputs( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", fp ); | 
 | 442 |  | 
 | 443 | 	/* DTD  | 
 | 444 | 	   No document type specified because "while a DTD is provided in [the SVG]  | 
 | 445 | 	   specification, the use of DTDs for validating XML documents is known to be  | 
 | 446 | 	   problematic. In particular, DTDs do not handle namespaces gracefully. It  | 
 | 447 | 	   is *not* recommended that a DOCTYPE declaration be included in SVG  | 
 | 448 | 	   documents."  | 
 | 449 | 	   http://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace | 
 | 450 | 	*/ | 
 | 451 |  | 
 | 452 | 	/* Vanity remark */ | 
 | 453 | 	fprintf( fp, "<!-- Created with qrencode %s (http://fukuchi.org/works/qrencode/index.html.en) -->\n",  | 
 | 454 | 			QRcode_APIVersionString() ); | 
 | 455 |  | 
 | 456 | 	/* SVG code start */ | 
 | 457 | 	fprintf( fp, "<svg width=\"%0.2fcm\" height=\"%0.2fcm\" viewBox=\"0 0 %d %d\""\ | 
 | 458 | 			" preserveAspectRatio=\"none\" version=\"1.1\""\ | 
 | 459 | 			" xmlns=\"http://www.w3.org/2000/svg\">\n",  | 
 | 460 | 			realwidth / scale, realwidth / scale, symwidth, symwidth | 
 | 461 | 		   ); | 
 | 462 |  | 
 | 463 | 	/* Make named group */ | 
 | 464 | 	fputs( "\t<g id=\"QRcode\">\n", fp ); | 
 | 465 |  | 
 | 466 | 	/* Make solid background */ | 
 | 467 | 	if(bg_color[3] != 255) { | 
 | 468 | 		fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" fill-opacity=\"%f\" />\n", symwidth, symwidth, bg, bg_opacity); | 
 | 469 | 	} else { | 
 | 470 | 		fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", symwidth, symwidth, bg); | 
 | 471 | 	} | 
 | 472 |  | 
 | 473 | 	/* Create new viewbox for QR data */ | 
 | 474 | 	fputs( "\t\t<g id=\"Pattern\">\n", fp); | 
 | 475 |  | 
 | 476 | 	/* Write data */ | 
 | 477 | 	p = qrcode->data; | 
 | 478 | 	for(y=0; y<qrcode->width; y++) { | 
 | 479 | 		row = (p+(y*qrcode->width)); | 
 | 480 |  | 
 | 481 | 		/* simple RLE */ | 
 | 482 | 		pen = 0; | 
 | 483 | 		x0  = 0; | 
 | 484 | 		for(x=0; x<qrcode->width; x++) { | 
 | 485 | 			if( !pen ) { | 
 | 486 | 				pen = *(row+x)&0x1; | 
 | 487 | 				x0 = x; | 
 | 488 | 			} else { | 
 | 489 | 				if(!(*(row+x)&0x1)) { | 
 | 490 | 					writeSVG_writeRect(fp, x0 + margin, y + margin, x-x0, fg, fg_opacity); | 
 | 491 | 					pen = 0; | 
 | 492 | 				} | 
 | 493 | 			} | 
 | 494 | 		} | 
 | 495 | 		if( pen ) { | 
 | 496 | 			writeSVG_writeRect(fp, x0 + margin, y + margin, qrcode->width - x0, fg, fg_opacity); | 
 | 497 | 		} | 
 | 498 | 	} | 
 | 499 |  | 
 | 500 | 	/* Close QR data viewbox */ | 
 | 501 | 	fputs( "\t\t</g>\n", fp ); | 
 | 502 |  | 
 | 503 | 	/* Close group */ | 
 | 504 | 	fputs( "\t</g>\n", fp ); | 
 | 505 |  | 
 | 506 | 	/* Close SVG code */ | 
 | 507 | 	fputs( "</svg>\n", fp ); | 
 | 508 | 	fclose( fp ); | 
 | 509 |  | 
 | 510 | 	return 0; | 
 | 511 | } | 
 | 512 |  | 
 | 513 | static void writeANSI_margin(FILE* fp, int realwidth, | 
 | 514 |                              char* buffer, int buffer_s, | 
 | 515 |                              char* white, int white_s ) | 
 | 516 | { | 
 | 517 | 	int y; | 
 | 518 |  | 
 | 519 | 	strncpy(buffer, white, white_s); | 
 | 520 | 	memset(buffer + white_s, ' ', realwidth * 2); | 
 | 521 | 	strcpy(buffer + white_s + realwidth * 2, "\033[0m\n"); // reset to default colors | 
 | 522 | 	for(y=0; y<margin; y++ ){ | 
 | 523 | 		fputs(buffer, fp); | 
 | 524 | 	} | 
 | 525 | } | 
 | 526 |  | 
 | 527 | static int writeANSI(QRcode *qrcode, const char *outfile) | 
 | 528 | { | 
 | 529 | 	FILE *fp; | 
 | 530 | 	unsigned char *row, *p; | 
 | 531 | 	int x, y; | 
 | 532 | 	int realwidth; | 
 | 533 | 	int last; | 
 | 534 |  | 
 | 535 | 	char *white, *black, *buffer; | 
 | 536 | 	int white_s, black_s, buffer_s; | 
 | 537 |  | 
 | 538 | 	if( image_type == ANSI256_TYPE ){ | 
 | 539 | 		/* codes for 256 color compatible terminals */ | 
 | 540 | 		white = "\033[48;5;231m"; | 
 | 541 | 		white_s = 11; | 
 | 542 | 		black = "\033[48;5;16m"; | 
 | 543 | 		black_s = 10; | 
 | 544 | 	} else { | 
 | 545 | 		white = "\033[47m"; | 
 | 546 | 		white_s = 5; | 
 | 547 | 		black = "\033[40m"; | 
 | 548 | 		black_s = 5; | 
 | 549 | 	} | 
 | 550 |  | 
 | 551 | 	size = 1; | 
 | 552 |  | 
 | 553 | 	fp = openFile(outfile); | 
 | 554 |  | 
 | 555 | 	realwidth = (qrcode->width + margin * 2) * size; | 
 | 556 | 	buffer_s = ( realwidth * white_s ) * 2; | 
 | 557 | 	buffer = (char *)malloc( buffer_s ); | 
 | 558 | 	if(buffer == NULL) { | 
 | 559 | 		fprintf(stderr, "Failed to allocate memory.\n"); | 
 | 560 | 		exit(EXIT_FAILURE); | 
 | 561 | 	} | 
 | 562 |  | 
 | 563 | 	/* top margin */ | 
 | 564 | 	writeANSI_margin(fp, realwidth, buffer, buffer_s, white, white_s); | 
 | 565 |  | 
 | 566 | 	/* data */ | 
 | 567 | 	p = qrcode->data; | 
 | 568 | 	for(y=0; y<qrcode->width; y++) { | 
 | 569 | 		row = (p+(y*qrcode->width)); | 
 | 570 |  | 
 | 571 | 		bzero( buffer, buffer_s ); | 
 | 572 | 		strncpy( buffer, white, white_s ); | 
 | 573 | 		for(x=0; x<margin; x++ ){ | 
 | 574 | 			strncat( buffer, "  ", 2 ); | 
 | 575 | 		} | 
 | 576 | 		last = 0; | 
 | 577 |  | 
 | 578 | 		for(x=0; x<qrcode->width; x++) { | 
 | 579 | 			if(*(row+x)&0x1) { | 
 | 580 | 				if( last != 1 ){ | 
 | 581 | 					strncat( buffer, black, black_s ); | 
 | 582 | 					last = 1; | 
 | 583 | 				} | 
 | 584 | 			} else { | 
 | 585 | 				if( last != 0 ){ | 
 | 586 | 					strncat( buffer, white, white_s ); | 
 | 587 | 					last = 0; | 
 | 588 | 				} | 
 | 589 | 			} | 
 | 590 | 			strncat( buffer, "  ", 2 ); | 
 | 591 | 		} | 
 | 592 |  | 
 | 593 | 		if( last != 0 ){ | 
 | 594 | 			strncat( buffer, white, white_s ); | 
 | 595 | 		} | 
 | 596 | 		for(x=0; x<margin; x++ ){ | 
 | 597 | 			strncat( buffer, "  ", 2 ); | 
 | 598 | 		} | 
 | 599 | 		strncat( buffer, "\033[0m\n", 5 ); | 
 | 600 | 		fputs( buffer, fp ); | 
 | 601 | 	} | 
 | 602 |  | 
 | 603 | 	/* bottom margin */ | 
 | 604 | 	writeANSI_margin(fp, realwidth, buffer, buffer_s, white, white_s); | 
 | 605 |  | 
 | 606 | 	fclose(fp); | 
 | 607 | 	free(buffer); | 
 | 608 |  | 
 | 609 | 	return 0; | 
 | 610 | } | 
 | 611 |  | 
 | 612 | static void writeUTF8_margin(FILE* fp, int realwidth, | 
 | 613 | 			     const char* white, const char *reset, | 
 | 614 | 			     int use_ansi) | 
 | 615 | { | 
 | 616 | 	int x, y; | 
 | 617 |  | 
 | 618 | 	for (y = 0; y < margin/2; y++) { | 
 | 619 | 		fputs(white, fp); | 
 | 620 | 		for (x = 0; x < realwidth; x++) | 
 | 621 | 			fputs("\342\226\210", fp); | 
 | 622 | 		fputs(reset, fp); | 
 | 623 | 		fputc('\n', fp); | 
 | 624 | 	} | 
 | 625 | } | 
 | 626 |  | 
 | 627 | static int writeUTF8(QRcode *qrcode, const char *outfile, int use_ansi) | 
 | 628 | { | 
 | 629 | 	FILE *fp; | 
 | 630 | 	int x, y; | 
 | 631 | 	int realwidth; | 
 | 632 | 	unsigned char *p; | 
 | 633 | 	const char *white, *reset; | 
 | 634 |  | 
 | 635 | 	if (use_ansi){ | 
 | 636 | 		white = "\033[40;37;1m"; | 
 | 637 | 		reset = "\033[0m"; | 
 | 638 | 	} else { | 
 | 639 | 		white = ""; | 
 | 640 | 		reset = ""; | 
 | 641 | 	} | 
 | 642 |  | 
 | 643 | 	fp = openFile(outfile); | 
 | 644 |  | 
 | 645 | 	realwidth = (qrcode->width + margin * 2); | 
 | 646 |  | 
 | 647 | 	/* top margin */ | 
 | 648 | 	writeUTF8_margin(fp, realwidth, white, reset, use_ansi); | 
 | 649 |  | 
 | 650 | 	/* data */ | 
 | 651 | 	p = qrcode->data; | 
 | 652 | 	for(y = 0; y < qrcode->width; y += 2) { | 
 | 653 | 		unsigned char *row1, *row2; | 
 | 654 | 		row1 = p + y*qrcode->width; | 
 | 655 | 		row2 = p + y*qrcode->width + qrcode->width; | 
 | 656 |  | 
 | 657 | 		fputs(white, fp); | 
 | 658 |  | 
 | 659 | 		for (x = 0; x < margin; x++) | 
 | 660 | 			fputs("\342\226\210", fp); | 
 | 661 |  | 
 | 662 | 		for (x = 0; x < qrcode->width; x++) { | 
 | 663 | 			if ((*(row1 + x) & 1) && (*(row2 + x) & 1)) | 
 | 664 | 				fputc(' ', fp); | 
 | 665 | 			else if (*(row1 + x) & 1) | 
 | 666 | 				fputs("\342\226\204", fp); | 
 | 667 | 			else if (*(row2 + x) & 1) | 
 | 668 | 				fputs("\342\226\200", fp); | 
 | 669 | 			else | 
 | 670 | 				fputs("\342\226\210", fp); | 
 | 671 | 		} | 
 | 672 |  | 
 | 673 | 		for (x = 0; x < margin; x++) | 
 | 674 | 			fputs("\342\226\210", fp); | 
 | 675 |  | 
 | 676 | 		fputs(reset, fp); | 
 | 677 | 		fputc('\n', fp); | 
 | 678 | 	} | 
 | 679 |  | 
 | 680 | 	/* bottom margin */ | 
 | 681 | 	writeUTF8_margin(fp, realwidth, white, reset, use_ansi); | 
 | 682 |  | 
 | 683 | 	fclose(fp); | 
 | 684 |  | 
 | 685 | 	return 0; | 
 | 686 | } | 
 | 687 |  | 
 | 688 | static void writeASCII_margin(FILE* fp, int realwidth, char* buffer, int buffer_s, int invert) | 
 | 689 | { | 
 | 690 | 	int y, h; | 
 | 691 |  | 
 | 692 | 	h = margin; | 
 | 693 |  | 
 | 694 | 	memset(buffer, (invert?'#':' '), realwidth); | 
 | 695 | 	buffer[realwidth] = '\n'; | 
 | 696 | 	buffer[realwidth + 1] = '\0'; | 
 | 697 | 	for(y=0; y<h; y++ ){ | 
 | 698 | 		fputs(buffer, fp); | 
 | 699 | 	} | 
 | 700 | } | 
 | 701 |  | 
 | 702 | static int writeASCII(QRcode *qrcode, const char *outfile, int invert) | 
 | 703 | { | 
 | 704 | 	FILE *fp; | 
 | 705 | 	unsigned char *row; | 
 | 706 | 	int x, y; | 
 | 707 | 	int realwidth; | 
 | 708 | 	char *buffer, *p; | 
 | 709 | 	int buffer_s; | 
 | 710 | 	char black = '#'; | 
 | 711 | 	char white = ' '; | 
 | 712 |  | 
 | 713 | 	if(invert) { | 
 | 714 | 		black = ' '; | 
 | 715 | 		white = '#'; | 
 | 716 | 	} | 
 | 717 |  | 
 | 718 | 	size = 1; | 
 | 719 |  | 
 | 720 | 	fp = openFile(outfile); | 
 | 721 |  | 
 | 722 | 	realwidth = (qrcode->width + margin * 2) * 2; | 
 | 723 | 	buffer_s = realwidth + 1; | 
 | 724 | 	buffer = (char *)malloc( buffer_s ); | 
 | 725 | 	if(buffer == NULL) { | 
 | 726 | 		fprintf(stderr, "Failed to allocate memory.\n"); | 
 | 727 | 		exit(EXIT_FAILURE); | 
 | 728 | 	} | 
 | 729 |  | 
 | 730 | 	/* top margin */ | 
 | 731 | 	writeASCII_margin(fp, realwidth, buffer, buffer_s, invert); | 
 | 732 |  | 
 | 733 | 	/* data */ | 
 | 734 | 	for(y=0; y<qrcode->width; y++) { | 
 | 735 | 		row = qrcode->data+(y*qrcode->width); | 
 | 736 | 		p = buffer; | 
 | 737 |  | 
 | 738 | 		memset(p, white, margin * 2); | 
 | 739 | 		p += margin * 2; | 
 | 740 |  | 
 | 741 | 		for(x=0; x<qrcode->width; x++) { | 
 | 742 | 			if(row[x]&0x1) { | 
 | 743 | 				*p++ = black; | 
 | 744 | 				*p++ = black; | 
 | 745 | 			} else { | 
 | 746 | 				*p++ = white; | 
 | 747 | 				*p++ = white; | 
 | 748 | 			} | 
 | 749 | 		} | 
 | 750 |  | 
 | 751 | 		memset(p, white, margin * 2); | 
 | 752 | 		p += margin * 2; | 
 | 753 | 		*p++ = '\n'; | 
 | 754 | 		*p++ = '\0'; | 
 | 755 | 		fputs( buffer, fp ); | 
 | 756 | 	} | 
 | 757 |  | 
 | 758 | 	/* bottom margin */ | 
 | 759 | 	writeASCII_margin(fp, realwidth, buffer, buffer_s, invert); | 
 | 760 |  | 
 | 761 | 	fclose(fp); | 
 | 762 | 	free(buffer); | 
 | 763 |  | 
 | 764 | 	return 0; | 
 | 765 | } | 
 | 766 |  | 
 | 767 | static QRcode *encode(const unsigned char *intext, int length) | 
 | 768 | { | 
 | 769 | 	QRcode *code; | 
 | 770 |  | 
 | 771 | 	if(micro) { | 
 | 772 | 		if(eightbit) { | 
 | 773 | 			code = QRcode_encodeDataMQR(length, intext, version, level); | 
 | 774 | 		} else { | 
 | 775 | 			code = QRcode_encodeStringMQR((char *)intext, version, level, hint, casesensitive); | 
 | 776 | 		} | 
 | 777 | 	} else { | 
 | 778 | 		if(eightbit) { | 
 | 779 | 			code = QRcode_encodeData(length, intext, version, level); | 
 | 780 | 		} else { | 
 | 781 | 			code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive); | 
 | 782 | 		} | 
 | 783 | 	} | 
 | 784 |  | 
 | 785 | 	return code; | 
 | 786 | } | 
 | 787 |  | 
 | 788 | static void qrencode(const unsigned char *intext, int length, const char *outfile) | 
 | 789 | { | 
 | 790 | 	QRcode *qrcode; | 
 | 791 | 	 | 
 | 792 | 	qrcode = encode(intext, length); | 
 | 793 | 	if(qrcode == NULL) { | 
 | 794 | 		perror("Failed to encode the input data"); | 
 | 795 | 		exit(EXIT_FAILURE); | 
 | 796 | 	} | 
 | 797 | 	switch(image_type) { | 
 | 798 | 		case PNG_TYPE: | 
 | 799 | 			writePNG(qrcode, outfile); | 
 | 800 | 			break; | 
 | 801 | 		case EPS_TYPE: | 
 | 802 | 			writeEPS(qrcode, outfile); | 
 | 803 | 			break; | 
 | 804 | 		case SVG_TYPE: | 
 | 805 | 			writeSVG(qrcode, outfile); | 
 | 806 | 			break; | 
 | 807 | 		case ANSI_TYPE: | 
 | 808 | 		case ANSI256_TYPE: | 
 | 809 | 			writeANSI(qrcode, outfile); | 
 | 810 | 			break; | 
 | 811 | 		case ASCIIi_TYPE: | 
 | 812 | 			writeASCII(qrcode, outfile,  1); | 
 | 813 | 			break; | 
 | 814 | 		case ASCII_TYPE: | 
 | 815 | 			writeASCII(qrcode, outfile,  0); | 
 | 816 | 			break; | 
 | 817 | 		case UTF8_TYPE: | 
 | 818 | 			writeUTF8(qrcode, outfile, 0); | 
 | 819 | 			break; | 
 | 820 | 		case ANSIUTF8_TYPE: | 
 | 821 | 			writeUTF8(qrcode, outfile, 1); | 
 | 822 | 			break; | 
 | 823 | 		default: | 
 | 824 | 			fprintf(stderr, "Unknown image type.\n"); | 
 | 825 | 			exit(EXIT_FAILURE); | 
 | 826 | 	} | 
 | 827 | 	QRcode_free(qrcode); | 
 | 828 | } | 
 | 829 |  | 
 | 830 | static QRcode_List *encodeStructured(const unsigned char *intext, int length) | 
 | 831 | { | 
 | 832 | 	QRcode_List *list; | 
 | 833 |  | 
 | 834 | 	if(eightbit) { | 
 | 835 | 		list = QRcode_encodeDataStructured(length, intext, version, level); | 
 | 836 | 	} else { | 
 | 837 | 		list = QRcode_encodeStringStructured((char *)intext, version, level, hint, casesensitive); | 
 | 838 | 	} | 
 | 839 |  | 
 | 840 | 	return list; | 
 | 841 | } | 
 | 842 |  | 
 | 843 | static void qrencodeStructured(const unsigned char *intext, int length, const char *outfile) | 
 | 844 | { | 
 | 845 | 	QRcode_List *qrlist, *p; | 
 | 846 | 	char filename[FILENAME_MAX]; | 
 | 847 | 	char *base, *q, *suffix = NULL; | 
 | 848 | 	const char *type_suffix; | 
 | 849 | 	int i = 1; | 
 | 850 | 	size_t suffix_size; | 
 | 851 |  | 
 | 852 | 	switch(image_type) { | 
 | 853 | 		case PNG_TYPE: | 
 | 854 | 			type_suffix = ".png"; | 
 | 855 | 			break; | 
 | 856 | 		case EPS_TYPE: | 
 | 857 | 			type_suffix = ".eps"; | 
 | 858 | 			break; | 
 | 859 | 		case SVG_TYPE: | 
 | 860 | 			type_suffix = ".svg"; | 
 | 861 | 			break; | 
 | 862 | 		case ANSI_TYPE: | 
 | 863 | 		case ANSI256_TYPE: | 
 | 864 | 		case ASCII_TYPE: | 
 | 865 | 		case UTF8_TYPE: | 
 | 866 | 		case ANSIUTF8_TYPE: | 
 | 867 | 			type_suffix = ".txt"; | 
 | 868 | 			break; | 
 | 869 | 		default: | 
 | 870 | 			fprintf(stderr, "Unknown image type.\n"); | 
 | 871 | 			exit(EXIT_FAILURE); | 
 | 872 | 	} | 
 | 873 |  | 
 | 874 | 	if(outfile == NULL) { | 
 | 875 | 		fprintf(stderr, "An output filename must be specified to store the structured images.\n"); | 
 | 876 | 		exit(EXIT_FAILURE); | 
 | 877 | 	} | 
 | 878 | 	base = strdup(outfile); | 
 | 879 | 	if(base == NULL) { | 
 | 880 | 		fprintf(stderr, "Failed to allocate memory.\n"); | 
 | 881 | 		exit(EXIT_FAILURE); | 
 | 882 | 	} | 
 | 883 | 	suffix_size = strlen(type_suffix); | 
 | 884 | 	if(strlen(base) > suffix_size) { | 
 | 885 | 		q = base + strlen(base) - suffix_size; | 
 | 886 | 		if(strcasecmp(type_suffix, q) == 0) { | 
 | 887 | 			suffix = strdup(q); | 
 | 888 | 			*q = '\0'; | 
 | 889 | 		} | 
 | 890 | 	} | 
 | 891 | 	 | 
 | 892 | 	qrlist = encodeStructured(intext, length); | 
 | 893 | 	if(qrlist == NULL) { | 
 | 894 | 		perror("Failed to encode the input data"); | 
 | 895 | 		exit(EXIT_FAILURE); | 
 | 896 | 	} | 
 | 897 |  | 
 | 898 | 	for(p = qrlist; p != NULL; p = p->next) { | 
 | 899 | 		if(p->code == NULL) { | 
 | 900 | 			fprintf(stderr, "Failed to encode the input data.\n"); | 
 | 901 | 			exit(EXIT_FAILURE); | 
 | 902 | 		} | 
 | 903 | 		if(suffix) { | 
 | 904 | 			snprintf(filename, FILENAME_MAX, "%s-%02d%s", base, i, suffix); | 
 | 905 | 		} else { | 
 | 906 | 			snprintf(filename, FILENAME_MAX, "%s-%02d", base, i); | 
 | 907 | 		} | 
 | 908 | 		switch(image_type) { | 
 | 909 | 			case PNG_TYPE:  | 
 | 910 | 				writePNG(p->code, filename); | 
 | 911 | 				break; | 
 | 912 | 			case EPS_TYPE:  | 
 | 913 | 				writeEPS(p->code, filename); | 
 | 914 | 				break; | 
 | 915 | 			case SVG_TYPE:  | 
 | 916 | 				writeSVG(p->code, filename); | 
 | 917 | 				break; | 
 | 918 | 			case ANSI_TYPE: | 
 | 919 | 			case ANSI256_TYPE: | 
 | 920 | 				writeANSI(p->code, filename); | 
 | 921 | 				break; | 
 | 922 | 			case ASCIIi_TYPE: | 
 | 923 | 				writeASCII(p->code, filename, 1); | 
 | 924 | 				break; | 
 | 925 | 			case ASCII_TYPE: | 
 | 926 | 				writeASCII(p->code, filename, 0); | 
 | 927 | 				break; | 
 | 928 | 			case UTF8_TYPE: | 
 | 929 | 				writeUTF8(p->code, filename, 0); | 
 | 930 | 				break; | 
 | 931 | 			case ANSIUTF8_TYPE: | 
 | 932 | 				writeUTF8(p->code, filename, 0); | 
 | 933 | 				break; | 
 | 934 |  | 
 | 935 | 			default: | 
 | 936 | 				fprintf(stderr, "Unknown image type.\n"); | 
 | 937 | 				exit(EXIT_FAILURE); | 
 | 938 | 		} | 
 | 939 | 		i++; | 
 | 940 | 	} | 
 | 941 |  | 
 | 942 | 	free(base); | 
 | 943 | 	if(suffix) { | 
 | 944 | 		free(suffix); | 
 | 945 | 	} | 
 | 946 |  | 
 | 947 | 	QRcode_List_free(qrlist); | 
 | 948 | } | 
 | 949 |  | 
 | 950 | int main(int argc, char **argv) | 
 | 951 | { | 
 | 952 | 	int opt, lindex = -1; | 
 | 953 | 	char *outfile = NULL; | 
 | 954 | 	unsigned char *intext = NULL; | 
 | 955 | 	int length = 0; | 
 | 956 |  | 
 | 957 | 	while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) { | 
 | 958 | 		switch(opt) { | 
 | 959 | 			case 'h': | 
 | 960 | 				if(lindex == 0) { | 
 | 961 | 					usage(1, 1); | 
 | 962 | 				} else { | 
 | 963 | 					usage(1, 0); | 
 | 964 | 				} | 
 | 965 | 				exit(EXIT_SUCCESS); | 
 | 966 | 				break; | 
 | 967 | 			case 'o': | 
 | 968 | 				outfile = optarg; | 
 | 969 | 				break; | 
 | 970 | 			case 's': | 
 | 971 | 				size = atoi(optarg); | 
 | 972 | 				if(size <= 0) { | 
 | 973 | 					fprintf(stderr, "Invalid size: %d\n", size); | 
 | 974 | 					exit(EXIT_FAILURE); | 
 | 975 | 				} | 
 | 976 | 				break; | 
 | 977 | 			case 'v': | 
 | 978 | 				version = atoi(optarg); | 
 | 979 | 				if(version < 0) { | 
 | 980 | 					fprintf(stderr, "Invalid version: %d\n", version); | 
 | 981 | 					exit(EXIT_FAILURE); | 
 | 982 | 				} | 
 | 983 | 				break; | 
 | 984 | 			case 'l': | 
 | 985 | 				switch(*optarg) { | 
 | 986 | 					case 'l': | 
 | 987 | 					case 'L': | 
 | 988 | 						level = QR_ECLEVEL_L; | 
 | 989 | 						break; | 
 | 990 | 					case 'm': | 
 | 991 | 					case 'M': | 
 | 992 | 						level = QR_ECLEVEL_M; | 
 | 993 | 						break; | 
 | 994 | 					case 'q': | 
 | 995 | 					case 'Q': | 
 | 996 | 						level = QR_ECLEVEL_Q; | 
 | 997 | 						break; | 
 | 998 | 					case 'h': | 
 | 999 | 					case 'H': | 
 | 1000 | 						level = QR_ECLEVEL_H; | 
 | 1001 | 						break; | 
 | 1002 | 					default: | 
 | 1003 | 						fprintf(stderr, "Invalid level: %s\n", optarg); | 
 | 1004 | 						exit(EXIT_FAILURE); | 
 | 1005 | 						break; | 
 | 1006 | 				} | 
 | 1007 | 				break; | 
 | 1008 | 			case 'm': | 
 | 1009 | 				margin = atoi(optarg); | 
 | 1010 | 				if(margin < 0) { | 
 | 1011 | 					fprintf(stderr, "Invalid margin: %d\n", margin); | 
 | 1012 | 					exit(EXIT_FAILURE); | 
 | 1013 | 				} | 
 | 1014 | 				break; | 
 | 1015 | 			case 'd': | 
 | 1016 | 				dpi = atoi(optarg); | 
 | 1017 | 				if( dpi < 0 ) { | 
 | 1018 | 					fprintf(stderr, "Invalid DPI: %d\n", dpi); | 
 | 1019 | 					exit(EXIT_FAILURE); | 
 | 1020 | 				} | 
 | 1021 | 				break; | 
 | 1022 | 			case 't': | 
 | 1023 | 				if(strcasecmp(optarg, "png") == 0) { | 
 | 1024 | 					image_type = PNG_TYPE; | 
 | 1025 | 				} else if(strcasecmp(optarg, "eps") == 0) { | 
 | 1026 | 					image_type = EPS_TYPE; | 
 | 1027 | 				} else if(strcasecmp(optarg, "svg") == 0) { | 
 | 1028 | 					image_type = SVG_TYPE; | 
 | 1029 | 				} else if(strcasecmp(optarg, "ansi") == 0) { | 
 | 1030 | 					image_type = ANSI_TYPE; | 
 | 1031 | 				} else if(strcasecmp(optarg, "ansi256") == 0) { | 
 | 1032 | 					image_type = ANSI256_TYPE; | 
 | 1033 | 				} else if(strcasecmp(optarg, "asciii") == 0) { | 
 | 1034 | 					image_type = ASCIIi_TYPE; | 
 | 1035 | 				} else if(strcasecmp(optarg, "ascii") == 0) { | 
 | 1036 | 					image_type = ASCII_TYPE; | 
 | 1037 | 				} else if(strcasecmp(optarg, "utf8") == 0) { | 
 | 1038 | 					image_type = UTF8_TYPE; | 
 | 1039 | 				} else if(strcasecmp(optarg, "ansiutf8") == 0) { | 
 | 1040 | 					image_type = ANSIUTF8_TYPE; | 
 | 1041 | 				} else { | 
 | 1042 | 					fprintf(stderr, "Invalid image type: %s\n", optarg); | 
 | 1043 | 					exit(EXIT_FAILURE); | 
 | 1044 | 				} | 
 | 1045 | 				break; | 
 | 1046 | 			case 'S': | 
 | 1047 | 				structured = 1; | 
 | 1048 | 			case 'k': | 
 | 1049 | 				hint = QR_MODE_KANJI; | 
 | 1050 | 				break; | 
 | 1051 | 			case 'c': | 
 | 1052 | 				casesensitive = 1; | 
 | 1053 | 				break; | 
 | 1054 | 			case 'i': | 
 | 1055 | 				casesensitive = 0; | 
 | 1056 | 				break; | 
 | 1057 | 			case '8': | 
 | 1058 | 				eightbit = 1; | 
 | 1059 | 				break; | 
 | 1060 | 			case 'M': | 
 | 1061 | 				micro = 1; | 
 | 1062 | 				break; | 
 | 1063 | 			case 'f': | 
 | 1064 | 				if(color_set(fg_color, optarg)) { | 
 | 1065 | 					fprintf(stderr, "Invalid foreground color value.\n"); | 
 | 1066 | 					exit(EXIT_FAILURE); | 
 | 1067 | 				} | 
 | 1068 | 				break; | 
 | 1069 | 			case 'b': | 
 | 1070 | 				if(color_set(bg_color, optarg)) { | 
 | 1071 | 					fprintf(stderr, "Invalid background color value.\n"); | 
 | 1072 | 					exit(EXIT_FAILURE); | 
 | 1073 | 				} | 
 | 1074 | 				break; | 
 | 1075 | 			case 'V': | 
 | 1076 | 				usage(0, 0); | 
 | 1077 | 				exit(EXIT_SUCCESS); | 
 | 1078 | 				break; | 
 | 1079 | 			default: | 
 | 1080 | 				fprintf(stderr, "Try `qrencode --help' for more information.\n"); | 
 | 1081 | 				exit(EXIT_FAILURE); | 
 | 1082 | 				break; | 
 | 1083 | 		} | 
 | 1084 | 	} | 
 | 1085 |  | 
 | 1086 | 	if(argc == 1) { | 
 | 1087 | 		usage(1, 0); | 
 | 1088 | 		exit(EXIT_SUCCESS); | 
 | 1089 | 	} | 
 | 1090 |  | 
 | 1091 | 	if(outfile == NULL && image_type == PNG_TYPE) { | 
 | 1092 | 		fprintf(stderr, "No output filename is given.\n"); | 
 | 1093 | 		exit(EXIT_FAILURE); | 
 | 1094 | 	} | 
 | 1095 |  | 
 | 1096 | 	if(optind < argc) { | 
 | 1097 | 		intext = (unsigned char *)argv[optind]; | 
 | 1098 | 		length = strlen((char *)intext); | 
 | 1099 | 	} | 
 | 1100 | 	if(intext == NULL) { | 
 | 1101 | 		intext = readStdin(&length); | 
 | 1102 | 	} | 
 | 1103 |  | 
 | 1104 | 	if(micro && version > MQRSPEC_VERSION_MAX) { | 
 | 1105 | 		fprintf(stderr, "Version should be less or equal to %d.\n", MQRSPEC_VERSION_MAX); | 
 | 1106 | 		exit(EXIT_FAILURE); | 
 | 1107 | 	} else if(!micro && version > QRSPEC_VERSION_MAX) { | 
 | 1108 | 		fprintf(stderr, "Version should be less or equal to %d.\n", QRSPEC_VERSION_MAX); | 
 | 1109 | 		exit(EXIT_FAILURE); | 
 | 1110 | 	} | 
 | 1111 |  | 
 | 1112 | 	if(margin < 0) { | 
 | 1113 | 		if(micro) { | 
 | 1114 | 			margin = 2; | 
 | 1115 | 		} else { | 
 | 1116 | 			margin = 4; | 
 | 1117 | 		} | 
 | 1118 | 	} | 
 | 1119 |  | 
 | 1120 | 	if(micro) { | 
 | 1121 | 		if(version == 0) { | 
 | 1122 | 			fprintf(stderr, "Version must be specified to encode a Micro QR Code symbol.\n"); | 
 | 1123 | 			exit(EXIT_FAILURE); | 
 | 1124 | 		} | 
 | 1125 | 		if(structured) { | 
 | 1126 | 			fprintf(stderr, "Micro QR Code does not support structured symbols.\n"); | 
 | 1127 | 			exit(EXIT_FAILURE); | 
 | 1128 | 		} | 
 | 1129 | 	} | 
 | 1130 |  | 
 | 1131 | 	if(structured) { | 
 | 1132 | 		if(version == 0) { | 
 | 1133 | 			fprintf(stderr, "Version must be specified to encode structured symbols.\n"); | 
 | 1134 | 			exit(EXIT_FAILURE); | 
 | 1135 | 		} | 
 | 1136 | 		qrencodeStructured(intext, length, outfile); | 
 | 1137 | 	} else { | 
 | 1138 | 		qrencode(intext, length, outfile); | 
 | 1139 | 	} | 
 | 1140 |  | 
 | 1141 | 	return 0; | 
 | 1142 | } |