2 * qrencode - QR Code encoder
4 * QR Code encoding tool
5 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
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.
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.
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
30 static int casesensitive = 1;
31 static int eightbit = 0;
32 static int version = 0;
34 static int margin = 4;
35 static int structured = 0;
36 static QRecLevel level = QR_ECLEVEL_L;
37 static QRencodeMode hint = QR_MODE_8;
39 static const struct option options[] = {
40 {"help" , no_argument , NULL, 'h'},
41 {"output" , required_argument, NULL, 'o'},
42 {"level" , required_argument, NULL, 'l'},
43 {"size" , required_argument, NULL, 's'},
44 {"symversion" , required_argument, NULL, 'v'},
45 {"margin" , required_argument, NULL, 'm'},
46 {"structured" , no_argument , NULL, 'S'},
47 {"kanji" , no_argument , NULL, 'k'},
48 {"casesensitive", no_argument , NULL, 'c'},
49 {"ignorecase" , no_argument , NULL, 'i'},
50 {"8bit" , no_argument , NULL, '8'},
51 {"version" , no_argument , NULL, 'V'},
55 static char *optstring = "ho:l:s:v:m:Skci8V";
57 static void usage(int help, int longopt)
60 "qrencode version %s\n"
61 "Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi\n", VERSION);
65 "Usage: qrencode [OPTION]... [STRING]\n"
66 "Encode input data in a QR Code and save as a PNG image.\n\n"
67 " -h, --help display the help message. -h displays only the help of short\n"
69 " -o FILENAME, --output=FILENAME\n"
70 " write PNG image to FILENAME. If '-' is specified, the result\n"
71 " will be output to standard output. If -S is given, structured\n"
72 " symbols are written to FILENAME-01.png, FILENAME-02.png, ...;\n"
73 " if specified, remove a trailing '.png' from FILENAME.\n\n"
74 " -s NUMBER, --size=NUMBER\n"
75 " specify the size of dot (pixel). (default=3)\n\n"
76 " -l {LMQH}, --level={LMQH}\n"
77 " specify error collectin level from L (lowest) to H (highest).\n"
79 " -v NUMBER, --symversion=NUMBER\n"
80 " specify the version of the symbol. (default=auto)\n\n"
81 " -m NUMBER, --margin=NUMBER\n"
82 " specify the width of margin. (default=4)\n\n"
84 " make structured symbols. Version must be specified.\n\n"
85 " -k, --kanji assume that the input text contains kanji (shift-jis).\n\n"
86 " -c, --casesensitive\n"
87 " encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
89 " ignore case distinctions and use only upper-case characters.\n\n"
90 " -8, -8bit encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
92 " display the version number and copyrights of the qrencode.\n\n"
93 " [STRING] input data. If it is not specified, data will be taken from\n"
98 "Usage: qrencode [OPTION]... [STRING]\n"
99 "Encode input data in a QR Code and save as a PNG image.\n\n"
100 " -h display this message.\n"
101 " --help display the usage of long options.\n"
102 " -o FILENAME write PNG image to FILENAME. If '-' is specified, the result\n"
103 " will be output to standard output. If -S is given, structured\n"
104 " symbols are written to FILENAME-01.png, FILENAME-02.png, ...;\n"
105 " if specified, remove a trailing '.png' from FILENAME.\n"
106 " -s NUMBER specify the size of dot (pixel). (default=3)\n"
107 " -l {LMQH} specify error collectin level from L (lowest) to H (highest).\n"
109 " -v NUMBER specify the version of the symbol. (default=auto)\n"
110 " -m NUMBER specify the width of margin. (default=4)\n"
111 " -S make structured symbols. Version must be specified.\n"
112 " -k assume that the input text contains kanji (shift-jis).\n"
113 " -c encode lower-case alphabet characters in 8-bit mode. (default)\n"
114 " -i ignore case distinctions and use only upper-case characters.\n"
115 " -8 encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
116 " -V display the version number and copyrights of the qrencode.\n"
117 " [STRING] input data. If it is not specified, data will be taken from\n"
124 #define MAX_DATA_SIZE (7090 * 16) /* from the specification */
125 static char *readStdin(void)
130 buffer = (char *)malloc(MAX_DATA_SIZE);
132 fprintf(stderr, "Memory allocation failed.\n");
135 ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
137 fprintf(stderr, "No input data.\n");
140 if(feof(stdin) == 0) {
141 fprintf(stderr, "Input data is too large.\n");
150 static int writePNG(QRcode *qrcode, const char *outfile)
152 static FILE *fp; // avoid clobbering by setjmp.
155 unsigned char *row, *p, *q;
156 int x, y, xx, yy, bit;
159 realwidth = (qrcode->width + margin * 2) * size;
160 row = (unsigned char *)malloc((realwidth + 7) / 8);
162 fprintf(stderr, "Failed to allocate memory.\n");
166 if(outfile[0] == '-' && outfile[1] == '\0') {
169 fp = fopen(outfile, "wb");
171 fprintf(stderr, "Failed to create file: %s\n", outfile);
177 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
178 if(png_ptr == NULL) {
179 fprintf(stderr, "Failed to initialize PNG writer.\n");
183 info_ptr = png_create_info_struct(png_ptr);
184 if(info_ptr == NULL) {
185 fprintf(stderr, "Failed to initialize PNG write.\n");
189 if(setjmp(png_jmpbuf(png_ptr))) {
190 png_destroy_write_struct(&png_ptr, &info_ptr);
191 fprintf(stderr, "Failed to write PNG image.\n");
195 png_init_io(png_ptr, fp);
196 png_set_IHDR(png_ptr, info_ptr,
197 realwidth, realwidth,
201 PNG_COMPRESSION_TYPE_DEFAULT,
202 PNG_FILTER_TYPE_DEFAULT);
203 png_write_info(png_ptr, info_ptr);
206 memset(row, 0xff, (realwidth + 7) / 8);
207 for(y=0; y<margin * size; y++) {
208 png_write_row(png_ptr, row);
213 for(y=0; y<qrcode->width; y++) {
215 memset(row, 0xff, (realwidth + 7) / 8);
217 q += margin * size / 8;
218 bit = 7 - (margin * size % 8);
219 for(x=0; x<qrcode->width; x++) {
220 for(xx=0; xx<size; xx++) {
221 *q ^= (*p & 1) << bit;
230 for(yy=0; yy<size; yy++) {
231 png_write_row(png_ptr, row);
235 memset(row, 0xff, (realwidth + 7) / 8);
236 for(y=0; y<margin * size; y++) {
237 png_write_row(png_ptr, row);
240 png_write_end(png_ptr, info_ptr);
241 png_destroy_write_struct(&png_ptr, &info_ptr);
249 static QRcode *encode(const char *intext)
254 code = QRcode_encodeString8bit(intext, version, level);
256 code = QRcode_encodeString(intext, version, level, hint, casesensitive);
262 static void qrencode(const char *intext, const char *outfile)
266 qrcode = encode(intext);
268 perror("Failed to encode the input data:");
271 writePNG(qrcode, outfile);
275 static QRcode_List *encodeStructured(const char *intext)
280 list = QRcode_encodeString8bitStructured(intext, version, level);
282 list = QRcode_encodeStringStructured(intext, version, level, hint, casesensitive);
288 static void qrencodeStructured(const char *intext, const char *outfile)
290 QRcode_List *qrlist, *p;
291 char filename[FILENAME_MAX];
292 char *base, *q, *suffix = NULL;
295 base = strdup(outfile);
297 fprintf(stderr, "Failed to allocate memory.\n");
300 if(strlen(base) > 4) {
301 q = base + strlen(base) - 4;
302 if(strcasecmp(".png", q) == 0) {
308 qrlist = encodeStructured(intext);
310 perror("Failed to encode the input data:");
314 for(p = qrlist; p != NULL; p = p->next) {
315 if(p->code == NULL) {
316 fprintf(stderr, "Failed to encode the input data.\n");
320 snprintf(filename, FILENAME_MAX, "%s-%02d%s", base, i, suffix);
322 snprintf(filename, FILENAME_MAX, "%s-%02d", base, i);
324 writePNG(p->code, filename);
333 QRcode_List_free(qrlist);
336 int main(int argc, char **argv)
338 int opt, lindex = -1;
339 char *outfile = NULL;
342 while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
358 fprintf(stderr, "Invalid size: %d\n", size);
363 version = atoi(optarg);
365 fprintf(stderr, "Invalid version: %d\n", version);
373 level = QR_ECLEVEL_L;
377 level = QR_ECLEVEL_M;
381 level = QR_ECLEVEL_Q;
385 level = QR_ECLEVEL_H;
388 fprintf(stderr, "Invalid level: %s\n", optarg);
394 margin = atoi(optarg);
396 fprintf(stderr, "Invalid margin: %d\n", margin);
403 hint = QR_MODE_KANJI;
419 fprintf(stderr, "Try `qrencode --help' for more information.\n");
430 if(outfile == NULL) {
431 fprintf(stderr, "No output filename is given.\n");
436 intext = argv[optind];
439 intext = readStdin();
444 fprintf(stderr, "Version must be specified to encode structured symbols.\n");
447 qrencodeStructured(intext, outfile);
449 qrencode(intext, outfile);