diff --git a/qrenc.c b/qrenc.c index c09c4ab6..c446722a 100644 --- a/qrenc.c +++ b/qrenc.c @@ -46,6 +46,7 @@ static int rle = 0; static int svg_path = 0; static int micro = 0; static int inline_svg = 0; +static int ascii_plus = 0; static int strict_versioning = 0; static QRecLevel level = QR_ECLEVEL_L; static QRencodeMode hint = QR_MODE_8; @@ -59,6 +60,9 @@ enum imageType { PNG32_TYPE, EPS_TYPE, SVG_TYPE, + FSVG1_TYPE, + FSVG2_TYPE, + FSVG3_TYPE, XPM_TYPE, ANSI_TYPE, ANSI256_TYPE, @@ -74,33 +78,34 @@ enum imageType { static enum imageType image_type = PNG_TYPE; static const struct option options[] = { - {"help" , no_argument , NULL, 'h'}, - {"output" , required_argument, NULL, 'o'}, - {"read-from" , required_argument, NULL, 'r'}, - {"level" , required_argument, NULL, 'l'}, - {"size" , required_argument, NULL, 's'}, - {"symversion" , required_argument, NULL, 'v'}, - {"margin" , required_argument, NULL, 'm'}, - {"dpi" , required_argument, NULL, 'd'}, - {"type" , required_argument, NULL, 't'}, - {"structured" , no_argument , NULL, 'S'}, - {"kanji" , no_argument , NULL, 'k'}, - {"casesensitive" , no_argument , NULL, 'c'}, - {"ignorecase" , no_argument , NULL, 'i'}, - {"8bit" , no_argument , NULL, '8'}, + {"help" , no_argument , NULL, 'h'}, + {"output" , required_argument, NULL, 'o'}, + {"read-from" , required_argument, NULL, 'r'}, + {"level" , required_argument, NULL, 'l'}, + {"size" , required_argument, NULL, 's'}, + {"symversion" , required_argument, NULL, 'v'}, + {"margin" , required_argument, NULL, 'm'}, + {"dpi" , required_argument, NULL, 'd'}, + {"type" , required_argument, NULL, 't'}, + {"structured" , no_argument , NULL, 'S'}, + {"kanji" , no_argument , NULL, 'k'}, + {"ascii-plus" , required_argument, NULL, 'A'}, + {"casesensitive", no_argument , NULL, 'c'}, + {"ignorecase" , no_argument , NULL, 'i'}, + {"8bit" , no_argument , NULL, '8'}, {"micro" , no_argument , NULL, 'M'}, - {"rle" , no_argument , &rle, 1}, - {"svg-path" , no_argument , &svg_path, 1}, - {"inline" , no_argument , &inline_svg, 1}, + {"rle" , no_argument , &rle, 1}, + {"svg-path" , no_argument , &svg_path, 1}, + {"inline" , no_argument , &inline_svg, 1}, {"strict-version", no_argument , &strict_versioning, 1}, - {"foreground" , required_argument, NULL, 'f'}, - {"background" , required_argument, NULL, 'b'}, - {"version" , no_argument , NULL, 'V'}, - {"verbose" , no_argument , &verbose, 1}, + {"foreground" , required_argument, NULL, 'f'}, + {"background" , required_argument, NULL, 'b'}, + {"version" , no_argument , NULL, 'V'}, + {"verbose" , no_argument , &verbose, 1}, {NULL, 0, NULL, 0} }; -static char *optstring = "ho:r:l:s:v:m:d:t:Skci8MV"; +static char *optstring = "ho:r:l:s:v:m:d:t:A:Skci8MV"; static void usage(int help, int longopt, int status) { @@ -134,12 +139,13 @@ static void usage(int help, int longopt, int status) " specify the width of the margins. (default=4 (2 for Micro QR)))\n\n" " -d NUMBER, --dpi=NUMBER\n" " specify the DPI of the generated PNG. (default=72)\n\n" -" -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8},\n" -" --type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}\n" +" -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8,FSVG1,FSVG2,FSVG3},\n" +" --type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8,FSVG1,FSVG2,FSVG3}\n" " specify the type of the generated image. (default=PNG)\n\n" " -S, --structured\n" " make structured symbols. Version must be specified with '-v'.\n\n" " -k, --kanji assume that the input text contains kanji (shift-jis).\n\n" +" -A NUMBER, --ascii-plus=NUMBER shows in ascii type the internal structure of the qrcode.\n\n" " -c, --casesensitive\n" " encode lower-case alphabet characters in 8-bit mode. (default)\n\n" " -i, --ignorecase\n" @@ -192,10 +198,11 @@ static void usage(int help, int longopt, int status) " -v NUMBER specify the minimum version of the symbol. (default=auto)\n" " -m NUMBER specify the width of the margins. (default=4 (2 for Micro))\n" " -d NUMBER specify the DPI of the generated PNG. (default=72)\n" -" -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}\n" +" -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8,FSVG1,FSVG2,FSVG3}\n" " specify the type of the generated image. (default=PNG)\n" " -S make structured symbols. Version number must be specified with '-v'.\n" " -k assume that the input text contains kanji (shift-jis).\n" +" -A NUMBER, --ascii-plus=NUMBER shows in ascii type the internal structure of the qrcode.\n\n" " -c encode lower-case alphabet characters in 8-bit mode. (default)\n" " -i ignore case distinctions and use only upper-case characters.\n" " -8 encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n" @@ -537,6 +544,586 @@ static void writeSVG_drawModules(FILE *fp, int x, int y, int width, const char* } } +static void writeFSVG1_drawModules(FILE *fp, int x, int y, const char* color) +{ + fprintf(fp," \ + \ + \ + ", + color,x*10,y*10, + color,x*10,y*10, + color,x*10,y*10, + color,x*10,y*10 + ); + fprintf(fp," ",color,x*10,y*10 + ); +} + +static void writeFSVG2_drawModules(FILE *fp, int x, int y, const char* color) +{ + fprintf(fp,"" + ,color,x*10+5,y*10+5 + ); +} + +static void writeFSVG3_drawModules(FILE *fp, int x, int y, const char* color) +{ + fprintf(fp,"\ + \ + \ + \ + " + ,color,x*10+1.8436925,y*10+1.755784 + ,color,x*10+1.2843877,y*10+6.8829622 + ,color,x*10+5.0531077,y*10+4.9817958 + ,color,x*10+7.2622757,y*10+8.4027872 + ,color,x*10+8.0230665,y*10+1.6966467 + ); +} + +static int writeFSVG1(const QRcode *qrcode, const char *outfile) +{ + FILE *fp; + unsigned char *row, *p; + int x, y; + int symwidth, realwidth; + char fg[7], bg[7]; + + size=10; //size forced due to design of dots. + + fp = openFile(outfile); + + symwidth = qrcode->width + margin * 2; + realwidth = symwidth * size; + + snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1], fg_color[2]); + snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1], bg_color[2]); + + /* XML declaration */ + fputs( "\n", fp ); + + /* DTD + No document type specified because "while a DTD is provided in [the SVG] + specification, the use of DTDs for validating XML documents is known to + be problematic. In particular, DTDs do not handle namespaces gracefully. + It is *not* recommended that a DOCTYPE declaration be included in SVG + documents." + http://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace + */ + + /* Vanity remark */ + fprintf(fp, "\n", QRcode_APIVersionString()); + + /* SVG code start */ + fprintf(fp, "\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + image/svg+xml\ + \ + \ + \ + \ + \ + " ,realwidth , realwidth + ); + + /* Write data */ + p = qrcode->data; + for(y = 0; y < qrcode->width+2*margin; y++) { + row = (p+((y-margin)*qrcode->width)); + for(x = 0; x < qrcode->width+2*margin; x++) { + if(y>=margin && y-marginwidth && x>=margin && x-marginwidth) { + if(*(row+x-margin)&0x1) writeFSVG1_drawModules(fp,x,y,fg); + else writeFSVG1_drawModules(fp,x,y,bg); + } else writeFSVG1_drawModules(fp,x,y,bg); + } + } + + /* Close group */ + fputs("\t\n", fp); + + /* Close SVG code */ + fputs("\n", fp); + fclose(fp); + + return 0; +} + +static int writeFSVG2(const QRcode *qrcode, const char *outfile) +{ + FILE *fp; + unsigned char *row, *p; + int x, y; + int symwidth, realwidth; + char fg[7], bg[7]; + + size=10; //size forced due to design of dots. + + fp = openFile(outfile); + + symwidth = qrcode->width + margin * 2; + realwidth = symwidth * size; + + snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1], fg_color[2]); + snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1], bg_color[2]); + + /* XML declaration */ + fputs( "\n", fp ); + + /* DTD + No document type specified because "while a DTD is provided in [the SVG] + specification, the use of DTDs for validating XML documents is known to + be problematic. In particular, DTDs do not handle namespaces gracefully. + It is *not* recommended that a DOCTYPE declaration be included in SVG + documents." + http://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace + */ + + /* Vanity remark */ + fprintf(fp, "\n", QRcode_APIVersionString()); + + /* SVG code start */ + fprintf(fp, "\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + image/svg+xml\ + \ + \ + \ + \ + \ + " ,realwidth , realwidth + ); + + /* Write data */ + p = qrcode->data; + for(y = 0; y < qrcode->width+2*margin; y++) { + row = (p+((y-margin)*qrcode->width)); + for(x = 0; x < qrcode->width+2*margin; x++) { + if(y>=margin && y-marginwidth && x>=margin && x-marginwidth) { + if(*(row+x-margin)&0x1) writeFSVG2_drawModules(fp,x,y,fg); + else writeFSVG2_drawModules(fp,x,y,bg); + } else writeFSVG2_drawModules(fp,x,y,bg); + } + } + + /* Close group */ + fputs("\t\n", fp); + + /* Close SVG code */ + fputs("\n", fp); + fclose(fp); + + return 0; +} + +static int writeFSVG3(const QRcode *qrcode, const char *outfile) +{ + FILE *fp; + unsigned char *row, *p; + int x, y; + int symwidth, realwidth; + char fg[7], bg[7]; + + size=10; //size forced due to design of dots. + + fp = openFile(outfile); + + symwidth = qrcode->width + margin * 2; + realwidth = symwidth * size; + + snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1], fg_color[2]); + snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1], bg_color[2]); + + /* XML declaration */ + fputs( "\n", fp ); + + /* DTD + No document type specified because "while a DTD is provided in [the SVG] + specification, the use of DTDs for validating XML documents is known to + be problematic. In particular, DTDs do not handle namespaces gracefully. + It is *not* recommended that a DOCTYPE declaration be included in SVG + documents." + http://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace + */ + + /* Vanity remark */ + fprintf(fp, "\n", QRcode_APIVersionString()); + + /* SVG code start */ + fprintf(fp, "\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + image/svg+xml\ + \ + \ + \ + \ + \ + " ,realwidth , realwidth + ); + + /* Write data */ + p = qrcode->data; + for(y = 0; y < qrcode->width+2*margin; y++) { + row = (p+((y-margin)*qrcode->width)); + for(x = 0; x < qrcode->width+2*margin; x++) { + if(y>=margin && y-marginwidth && x>=margin && x-marginwidth) { + if(*(row+x-margin)&0x1) writeFSVG3_drawModules(fp,x,y,fg); + else writeFSVG3_drawModules(fp,x,y,bg); + } else writeFSVG3_drawModules(fp,x,y,bg); + } + } + + /* Close group */ + fputs("\t\n", fp); + + /* Close SVG code */ + fputs("\n", fp); + fclose(fp); + + return 0; +} + static int writeSVG(const QRcode *qrcode, const char *outfile) { FILE *fp; @@ -984,10 +1571,12 @@ static int writeASCII(const QRcode *qrcode, const char *outfile, int invert) for(x = 0; x < qrcode->width; x++) { if(row[x]&0x1) { - *p++ = black; + if(ascii_plus)*p++=ascii_plus&row[x]?'1':' '; + else *p++ = black; *p++ = black; } else { - *p++ = white; + if(ascii_plus)*p++=ascii_plus&row[x]?'1':' '; + else *p++ = white; *p++ = white; } } @@ -1060,6 +1649,15 @@ static void qrencode(const unsigned char *intext, int length, const char *outfil case SVG_TYPE: writeSVG(qrcode, outfile); break; + case FSVG1_TYPE: + writeFSVG1(qrcode, outfile); + break; + case FSVG2_TYPE: + writeFSVG2(qrcode, outfile); + break; + case FSVG3_TYPE: + writeFSVG3(qrcode, outfile); + break; case XPM_TYPE: writeXPM(qrcode, outfile); break; @@ -1126,6 +1724,7 @@ static void qrencodeStructured(const unsigned char *intext, int length, const ch type_suffix = ".eps"; break; case SVG_TYPE: + case FSVG1_TYPE: type_suffix = ".svg"; break; case XPM_TYPE: @@ -1199,6 +1798,9 @@ static void qrencodeStructured(const unsigned char *intext, int length, const ch case SVG_TYPE: writeSVG(p->code, filename); break; + case FSVG1_TYPE: + writeFSVG1(p->code, filename); + break; case XPM_TYPE: writeXPM(p->code, filename); break; @@ -1326,6 +1928,12 @@ int main(int argc, char **argv) image_type = EPS_TYPE; } else if(strcasecmp(optarg, "svg") == 0) { image_type = SVG_TYPE; + } else if(strcasecmp(optarg, "fsvg1") == 0) { + image_type = FSVG1_TYPE; + } else if(strcasecmp(optarg, "fsvg2") == 0) { + image_type = FSVG2_TYPE; + } else if(strcasecmp(optarg, "fsvg3") == 0) { + image_type = FSVG3_TYPE; } else if(strcasecmp(optarg, "xpm") == 0) { image_type = XPM_TYPE; } else if(strcasecmp(optarg, "ansi") == 0) { @@ -1357,6 +1965,9 @@ int main(int argc, char **argv) case 'k': hint = QR_MODE_KANJI; break; + case 'A': + ascii_plus = atoi(optarg); + break; case 'c': casesensitive = 1; break;