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