source: trunk/zoo-project/zoo-services/qrencode/qrenc-service.c @ 902

Last change on this file since 902 was 743, checked in by djay, 9 years ago

Add WCPS-Proxy, data-api proxy and update Makefile for dealing with specific location of fastcgi. Add status update for contour lines computation.

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

Search

Context Navigation

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png