1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <SDL.h>
5 #include <getopt.h>
6 #include <errno.h>
7 #include "../config.h"
8 #include "../qrspec.h"
9 #include "../qrinput.h"
10 #include "../split.h"
inputTest(QRinput_List * list,const char * fmt,...)11 #include "../qrencode_inner.h"
12
13 static SDL_Surface *screen = NULL;
14 static int casesensitive = 1;
15 static int eightbit = 0;
16 static int version = 1;
17 static int size = 4;
18 static int margin = 4;
19 static int structured = 0;
20 static int micro = 0;
21 static QRecLevel level = QR_ECLEVEL_L;
22 static QRencodeMode hint = QR_MODE_8;
23
24 static char **textv;
25 static int textc;
26
27 static const struct option options[] = {
28 {"help" , no_argument , NULL, 'h'},
29 {"level" , required_argument, NULL, 'l'},
30 {"size" , required_argument, NULL, 's'},
31 {"symversion" , required_argument, NULL, 'v'},
32 {"margin" , required_argument, NULL, 'm'},
33 {"structured" , no_argument , NULL, 'S'},
34 {"kanji" , no_argument , NULL, 'k'},
35 {"casesensitive", no_argument , NULL, 'c'},
36 {"ignorecase" , no_argument , NULL, 'i'},
37 {"8bit" , no_argument , NULL, '8'},
38 {"micro" , no_argument , NULL, 'M'},
39 {"version" , no_argument , NULL, 'V'},
40 {NULL, 0, NULL, 0}
41 };
42
43 static char *optstring = "hl:s:v:m:Skci8MV";
44
45 static char levelChar[4] = {'L', 'M', 'Q', 'H'};
46 static void usage(int help, int longopt)
47 {
48 fprintf(stderr,
49 "view_qrcode version %s\n"
50 "Copyright (C) 2008, 2009, 2010 Kentaro Fukuchi\n", VERSION);
51 if(help) {
52 if(longopt) {
53 fprintf(stderr,
54 "Usage: view_qrcode [OPTION]... [STRING]\n"
55 "Encode input data in a QR Code and display.\n\n"
56 " -h, --help display the help message. -h displays only the help of short\n"
57 " options.\n\n"
58 " -s NUMBER, --size=NUMBER\n"
59 " specify module size in dots (pixels). (default=3)\n\n"
60 " -l {LMQH}, --level={LMQH}\n"
61 " specify error correction level from L (lowest) to H (highest).\n"
62 " (default=L)\n\n"
63 " -v NUMBER, --symversion=NUMBER\n"
64 " specify the version of the symbol. (default=auto)\n\n"
inputSize(QRinput * input)65 " -m NUMBER, --margin=NUMBER\n"
66 " specify the width of the margins. (default=4)\n\n"
67 " -S, --structured\n"
68 " make structured symbols. Version must be specified.\n\n"
69 " -k, --kanji assume that the input text contains kanji (shift-jis).\n\n"
70 " -c, --casesensitive\n"
71 " encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
72 " -i, --ignorecase\n"
73 " ignore case distinctions and use only upper-case characters.\n\n"
74 " -8, --8bit encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
75 " -M, --micro encode in a Micro QR Code. (experimental)\n\n"
76 " -V, --version\n"
77 " display the version number and copyrights of the qrencode.\n\n"
78 " [STRING] input data. If it is not specified, data will be taken from\n"
79 " standard input.\n"
80 );
81 } else {
82 fprintf(stderr,
83 "Usage: view_qrcode [OPTION]... [STRING]\n"
84 "Encode input data in a QR Code and display.\n\n"
85 " -h display this message.\n"
86 " --help display the usage of long options.\n"
87 " -s NUMBER specify module size in dots (pixels). (default=3)\n"
88 " -l {LMQH} specify error correction level from L (lowest) to H (highest).\n"
89 " (default=L)\n"
90 " -v NUMBER specify the version of the symbol. (default=auto)\n"
test_split2(void)91 " -m NUMBER specify the width of the margins. (default=4)\n"
92 " -S make structured symbols. Version must be specified.\n"
93 " -k assume that the input text contains kanji (shift-jis).\n"
94 " -c encode lower-case alphabet characters in 8-bit mode. (default)\n"
95 " -i ignore case distinctions and use only upper-case characters.\n"
96 " -8 encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
97 " -M encode in a Micro QR Code.\n"
98 " -V display the version number and copyrights of the qrencode.\n"
99 " [STRING] input data. If it is not specified, data will be taken from\n"
100 " standard input.\n"
101 );
102 }
103 }
104 }
105
106 #define MAX_DATA_SIZE (7090 * 16) /* from the specification */
107 static unsigned char *readStdin(int *length)
108 {
109 unsigned char *buffer;
110 int ret;
111
112 buffer = (unsigned char *)malloc(MAX_DATA_SIZE + 1);
113 if(buffer == NULL) {
114 fprintf(stderr, "Memory allocation failed.\n");
115 exit(EXIT_FAILURE);
116 }
117
118 ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
test_split3(void)119 if(ret == 0) {
120 fprintf(stderr, "No input data.\n");
121 exit(EXIT_FAILURE);
122 }
123 if(feof(stdin) == 0) {
124 fprintf(stderr, "Input data is too large.\n");
125 exit(EXIT_FAILURE);
126 }
127
128 buffer[ret] = '\0';
129 *length = ret;
130
131 return buffer;
132 }
133
134 static void draw_QRcode(QRcode *qrcode, int ox, int oy)
135 {
136 int x, y, width;
137 unsigned char *p;
138 SDL_Rect rect;
139
140 ox += margin * size;
141 oy += margin * size;
142 width = qrcode->width;
143 p = qrcode->data;
144 for(y=0; y<width; y++) {
145 for(x=0; x<width; x++) {
146 rect.x = ox + x * size;
147 rect.y = oy + y * size;
148 rect.w = size;
149 rect.h = size;
150 SDL_FillRect(screen, &rect, (*p&1)?0:0xffffff);
151 p++;
152 }
153 }
154 }
155
156 void draw_singleQRcode(QRinput *stream, int mask)
157 {
158 QRcode *qrcode;
test_split4(void)159 int width;
160
161 QRinput_setVersionAndErrorCorrectionLevel(stream, version, level);
162 if(micro) {
163 qrcode = QRcode_encodeMaskMQR(stream, mask);
164 } else {
165 qrcode = QRcode_encodeMask(stream, mask);
166 }
167 if(qrcode == NULL) {
168 width = (11 + margin * 2) * size;
169 fprintf(stderr, "Input data does not fit to this setting.\n");
170 } else {
171 version = qrcode->version;
172 width = (qrcode->width + margin * 2) * size;
173 }
174
175 screen = SDL_SetVideoMode(width, width, 32, 0);
176 SDL_FillRect(screen, NULL, 0xffffff);
177 if(qrcode) {
178 draw_QRcode(qrcode, 0, 0);
179 }
180 SDL_Flip(screen);
181 QRcode_free(qrcode);
182 }
183
184 void draw_structuredQRcode(QRinput_Struct *s)
185 {
186 int i, w, h, n, x, y;
187 int swidth;
188 QRcode_List *qrcodes, *p;
189
190 qrcodes = QRcode_encodeInputStructured(s);
191 if(qrcodes == NULL) return;
192
193 swidth = (qrcodes->code->width + margin * 2) * size;
194 n = QRcode_List_size(qrcodes);
195 w = (n < 4)?n:4;
196 h = (n - 1) / 4 + 1;
197
198 screen = SDL_SetVideoMode(swidth * w, swidth * h, 32, 0);
199 SDL_FillRect(screen, NULL, 0xffffff);
200
201 p = qrcodes;
202 for(i=0; i<n; i++) {
203 x = (i % 4) * swidth;
204 y = (i / 4) * swidth;
205 draw_QRcode(p->code, x, y);
206 p = p->next;
207 }
208 SDL_Flip(screen);
209 QRcode_List_free(qrcodes);
210 }
211
212 void draw_structuredQRcodeFromText(int argc, char **argv)
213 {
214 QRinput_Struct *s;
215 QRinput *input;
216 int i, ret;
217
218 s = QRinput_Struct_new();
219 if(s == NULL) {
test_split5(void)220 fprintf(stderr, "Failed to allocate memory.\n");
221 exit(EXIT_FAILURE);
222 }
223 for(i=0; i<argc; i++) {
224 input = QRinput_new2(version, level);
225 if(input == NULL) {
226 fprintf(stderr, "Failed to allocate memory.\n");
227 exit(EXIT_FAILURE);
228 }
229 if(eightbit) {
230 ret = QRinput_append(input, QR_MODE_8, strlen(argv[i]), (unsigned char *)argv[i]);
231 } else {
232 ret = Split_splitStringToQRinput(argv[i], input, hint, casesensitive);
233 }
234 if(ret < 0) {
235 perror("Encoding the input string");
236 exit(EXIT_FAILURE);
test_split6(void)237 }
238 ret = QRinput_Struct_appendInput(s, input);
239 if(ret < 0) {
240 perror("Encoding the input string");
241 exit(EXIT_FAILURE);
242 }
243 }
244 ret = QRinput_Struct_insertStructuredAppendHeaders(s);
245 if(ret < 0) {
246 fprintf(stderr, "Too many inputs.\n");
247 }
248
249 draw_structuredQRcode(s);
250 QRinput_Struct_free(s);
251 }
252
253 void draw_structuredQRcodeFromQRinput(QRinput *stream)
254 {
test_split7(void)255 QRinput_Struct *s;
256
257 QRinput_setVersion(stream, version);
258 QRinput_setErrorCorrectionLevel(stream, level);
259 s = QRinput_splitQRinputToStruct(stream);
260 if(s != NULL) {
261 draw_structuredQRcode(s);
262 QRinput_Struct_free(s);
263 } else {
264 fprintf(stderr, "Input data is too large for this setting.\n");
265 }
266 }
267
268 void view(int mode, QRinput *input)
269 {
270 int flag = 1;
271 int mask = -1;
test_split8(void)272 SDL_Event event;
273 int loop;
274
275 while(flag) {
276 if(mode) {
277 draw_structuredQRcodeFromText(textc, textv);
278 } else {
279 if(structured) {
280 draw_structuredQRcodeFromQRinput(input);
281 } else {
282 draw_singleQRcode(input, mask);
283 }
284 }
285 if(mode || structured) {
286 printf("Version %d, Level %c.\n", version, levelChar[level]);
287 } else {
288 printf("Version %d, Level %c, Mask %d.\n", version, levelChar[level], mask);
test_split3c(void)289 }
290 loop = 1;
291 while(loop) {
292 usleep(10000);
293 while(SDL_PollEvent(&event)) {
294 if(event.type == SDL_KEYDOWN) {
295 switch(event.key.keysym.sym) {
296 case SDLK_RIGHT:
297 version++;
298 if(version > QRSPEC_VERSION_MAX)
299 version = QRSPEC_VERSION_MAX;
300 loop = 0;
301 break;
302 case SDLK_LEFT:
303 version--;
304 if(version < 1)
305 version = 1;
306 loop = 0;
307 break;
308 case SDLK_UP:
309 size++;
310 loop = 0;
311 break;
312 case SDLK_DOWN:
313 size--;
314 if(size < 1) size = 1;
315 loop = 0;
316 break;
317 case SDLK_0:
318 case SDLK_1:
319 case SDLK_2:
320 case SDLK_3:
321 case SDLK_4:
322 case SDLK_5:
323 case SDLK_6:
324 case SDLK_7:
325 if(!mode && !structured) {
326 mask = (event.key.keysym.sym - SDLK_0);
327 loop = 0;
328 }
test_toupper(void)329 break;
330 case SDLK_8:
331 if(!mode && !structured) {
332 mask = -1;
333 loop = 0;
334 }
335 break;
336 case SDLK_l:
337 level = QR_ECLEVEL_L;
338 loop = 0;
339 break;
340 case SDLK_m:
341 level = QR_ECLEVEL_M;
342 loop = 0;
343 break;
344 case SDLK_h:
345 level = QR_ECLEVEL_H;
346 loop = 0;
347 break;
348 case SDLK_q:
349 level = QR_ECLEVEL_Q;
350 loop = 0;
351 break;
352 case SDLK_ESCAPE:
353 loop = 0;
354 flag = 0;
355 break;
356 default:
357 break;
358 }
359 }
360 if(event.type == SDL_QUIT) {
361 loop = 0;
362 flag = 0;
363 }
364 }
365 }
366 }
367 }
368
369 void view_simple(const unsigned char *str, int length)
370 {
371 QRinput *input;
372 int ret;
373
374 if(micro) {
375 input = QRinput_newMQR(version, level);
376 } else {
377 input = QRinput_new2(version, level);
378 }
test_splitNum8(void)379 if(input == NULL) {
380 fprintf(stderr, "Memory allocation error.\n");
381 exit(EXIT_FAILURE);
382 }
383 if(eightbit) {
384 ret = QRinput_append(input, QR_MODE_8, length, str);
385 } else {
386 ret = Split_splitStringToQRinput((char *)str, input, hint, casesensitive);
387 }
388 if(ret < 0) {
389 perror("Encoding the input string");
390 exit(EXIT_FAILURE);
391 }
392
393 view(0, input);
394
395 QRinput_free(input);
396 }
test_splitAnNAn(void)397
398 void view_multiText(char **argv, int argc)
399 {
400 textc = argc;
401 textv = argv;
402
403 view(1, NULL);
404 }
405
406 int main(int argc, char **argv)
407 {
408 int opt, lindex = -1;
409 unsigned char *intext = NULL;
410 int length = 0;
411
412 while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
413 switch(opt) {
414 case 'h':
415 if(lindex == 0) {
416 usage(1, 1);
417 } else {
418 usage(1, 0);
419 }
420 exit(EXIT_SUCCESS);
421 break;
422 case 's':
423 size = atoi(optarg);
424 if(size <= 0) {
425 fprintf(stderr, "Invalid size: %d\n", size);
426 exit(EXIT_FAILURE);
427 }
428 break;
429 case 'v':
test_splitAn8An(void)430 version = atoi(optarg);
431 if(version < 0) {
432 fprintf(stderr, "Invalid version: %d\n", version);
433 exit(EXIT_FAILURE);
434 }
435 break;
436 case 'l':
437 switch(*optarg) {
438 case 'l':
439 case 'L':
440 level = QR_ECLEVEL_L;
441 break;
442 case 'm':
443 case 'M':
444 level = QR_ECLEVEL_M;
445 break;
446 case 'q':
447 case 'Q':
448 level = QR_ECLEVEL_Q;
449 break;
450 case 'h':
451 case 'H':
452 level = QR_ECLEVEL_H;
453 break;
454 default:
455 fprintf(stderr, "Invalid level: %s\n", optarg);
456 exit(EXIT_FAILURE);
457 break;
458 }
459 break;
460 case 'm':
461 margin = atoi(optarg);
462 if(margin < 0) {
test_split8An8(void)463 fprintf(stderr, "Invalid margin: %d\n", margin);
464 exit(EXIT_FAILURE);
465 }
466 break;
467 case 'S':
468 structured = 1;
469 case 'k':
470 hint = QR_MODE_KANJI;
471 break;
472 case 'c':
473 casesensitive = 1;
474 break;
475 case 'i':
476 casesensitive = 0;
477 break;
478 case '8':
479 eightbit = 1;
480 break;
481 case 'M':
482 micro = 1;
483 break;
484 case 'V':
485 usage(0, 0);
486 exit(EXIT_SUCCESS);
487 break;
488 default:
489 fprintf(stderr, "Try `view_qrcode --help' for more information.\n");
490 exit(EXIT_FAILURE);
491 break;
492 }
493 }
494 if(argc == 1) {
495 usage(1, 0);
test_split8N8(void)496 exit(EXIT_SUCCESS);
497 }
498
499 if(optind < argc) {
500 intext = (unsigned char *)argv[optind];
501 length = strlen((char *)intext);
502 }
503 if(intext == NULL) {
504 intext = readStdin(&length);
505 }
506
507 if(SDL_Init(SDL_INIT_VIDEO) < 0) {
508 fprintf(stderr, "Failed initializing SDL: %s\n", SDL_GetError());
509 return -1;
510 }
511 if(structured && version < 1) {
512 fprintf(stderr, "Version number must be greater than 0 to encode structured symbols.\n");
513 exit(EXIT_FAILURE);
514 }
515 if(structured && (argc - optind > 1)) {
516 view_multiText(argv + optind, argc - optind);
517 } else {
518 view_simple(intext, length);
519 }
520
521 SDL_Quit();
522
523 return 0;
524 }
525