qrcode : add quick response code
source : https://github.com/BlueDragon747/qrencode-win32
Change-Id: I0fbe4f37100afcfa761b0cef90e34b4198fccf0e
Tuleap: #1233
diff --git a/contrib/qrencode-win32/qrenc.c b/contrib/qrencode-win32/qrenc.c
new file mode 100644
index 0000000..ba6446c
--- /dev/null
+++ b/contrib/qrencode-win32/qrenc.c
@@ -0,0 +1,1191 @@
+/**
+ * qrencode - QR Code encoder
+ *
+ * QR Code encoding tool
+ * Copyright (C) 2006-2013 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <png.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <io.h>
+
+#include "qrencode.h"
+
+#define INCHES_PER_METER (100.0/2.54)
+
+static int casesensitive = 1;
+static int eightbit = 0;
+static int version = 0;
+static int size = 3;
+static int margin = -1;
+static int dpi = 72;
+static int structured = 0;
+static int rle = 0;
+static int micro = 0;
+static QRecLevel level = QR_ECLEVEL_L;
+static QRencodeMode hint = QR_MODE_8;
+static unsigned int fg_color[4] = {0, 0, 0, 255};
+static unsigned int bg_color[4] = {255, 255, 255, 255};
+
+static int verbose = 0;
+
+enum imageType {
+ PNG_TYPE,
+ EPS_TYPE,
+ SVG_TYPE,
+ ANSI_TYPE,
+ ANSI256_TYPE,
+ ASCII_TYPE,
+ ASCIIi_TYPE,
+ UTF8_TYPE,
+ ANSIUTF8_TYPE
+};
+
+static enum imageType image_type = PNG_TYPE;
+
+static const struct option options[] = {
+ {"help" , no_argument , NULL, 'h'},
+ {"output" , required_argument, NULL, 'o'},
+ {"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'},
+ {"rle" , no_argument , &rle, 1},
+ {"micro" , no_argument , NULL, 'M'},
+ {"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:l:s:v:m:d:t:Skci8MV";
+
+static void usage(int help, int longopt)
+{
+ fprintf(stderr,
+"qrencode version %s\n"
+"Copyright (C) 2006-2012 Kentaro Fukuchi\n", QRcode_APIVersionString());
+ if(help) {
+ if(longopt) {
+ fprintf(stderr,
+"Usage: qrencode [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
+" -h, --help display the help message. -h displays only the help of short\n"
+" options.\n\n"
+" -o FILENAME, --output=FILENAME\n"
+" write image to FILENAME. If '-' is specified, the result\n"
+" will be output to standard output. If -S is given, structured\n"
+" symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
+" (suffix is removed from FILENAME, if specified)\n"
+" -s NUMBER, --size=NUMBER\n"
+" specify module size in dots (pixels). (default=3)\n\n"
+" -l {LMQH}, --level={LMQH}\n"
+" specify error correction level from L (lowest) to H (highest).\n"
+" (default=L)\n\n"
+" -v NUMBER, --symversion=NUMBER\n"
+" specify the version of the symbol. See SYMBOL VERSIONS for more\n"
+" information. (default=auto)\n\n"
+" -m NUMBER, --margin=NUMBER\n"
+" 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,EPS,SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}, --type={PNG,EPS,\n"
+" SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}\n"
+" specify the type of the generated image. (default=PNG)\n\n"
+" -S, --structured\n"
+" make structured symbols. Version must be specified.\n\n"
+" -k, --kanji assume that the input text contains kanji (shift-jis).\n\n"
+" -c, --casesensitive\n"
+" encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
+" -i, --ignorecase\n"
+" ignore case distinctions and use only upper-case characters.\n\n"
+" -8, --8bit encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
+" --rle enable run-length encoding for SVG.\n\n"
+" -M, --micro encode in a Micro QR Code. (experimental)\n\n"
+" --foreground=RRGGBB[AA]\n"
+" --background=RRGGBB[AA]\n"
+" specify foreground/background color in hexadecimal notation.\n"
+" 6-digit (RGB) or 8-digit (RGBA) form are supported.\n"
+" Color output support available only in PNG and SVG.\n"
+" -V, --version\n"
+" display the version number and copyrights of the qrencode.\n\n"
+" --verbose\n"
+" display verbose information to stderr.\n\n"
+" [STRING] input data. If it is not specified, data will be taken from\n"
+" standard input.\n\n"
+"*SYMBOL VERSIONS\n"
+" The symbol versions of QR Code range from Version 1 to Version\n"
+" 40. Each version has a different module configuration or number\n"
+" of modules, ranging from Version 1 (21 x 21 modules) up to\n"
+" Version 40 (177 x 177 modules). Each higher version number\n"
+" comprises 4 additional modules per side by default. See\n"
+" http://www.qrcode.com/en/about/version.html for a detailed\n"
+" version list.\n"
+
+ );
+ } else {
+ fprintf(stderr,
+"Usage: qrencode [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
+" -h display this message.\n"
+" --help display the usage of long options.\n"
+" -o FILENAME write image to FILENAME. If '-' is specified, the result\n"
+" will be output to standard output. If -S is given, structured\n"
+" symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
+" (suffix is removed from FILENAME, if specified)\n"
+" -s NUMBER specify module size in dots (pixels). (default=3)\n"
+" -l {LMQH} specify error correction level from L (lowest) to H (highest).\n"
+" (default=L)\n"
+" -v NUMBER specify the 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,EPS,SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}\n"
+" specify the type of the generated image. (default=PNG)\n"
+" -S make structured symbols. Version must be specified.\n"
+" -k assume that the input text contains kanji (shift-jis).\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"
+" -M encode in a Micro QR Code.\n"
+" --foreground=RRGGBB[AA]\n"
+" --background=RRGGBB[AA]\n"
+" specify foreground/background color in hexadecimal notation.\n"
+" 6-digit (RGB) or 8-digit (RGBA) form are supported.\n"
+" Color output support available only in PNG and SVG.\n"
+" -V display the version number and copyrights of the qrencode.\n"
+" [STRING] input data. If it is not specified, data will be taken from\n"
+" standard input.\n"
+ );
+ }
+ }
+}
+
+static int color_set(unsigned int color[4], const char *value)
+{
+ int len = strlen(value);
+ int count;
+ if(len == 6) {
+ count = sscanf(value, "%02x%02x%02x%n", &color[0], &color[1], &color[2], &len);
+ if(count < 3 || len != 6) {
+ return -1;
+ }
+ color[3] = 255;
+ } else if(len == 8) {
+ count = sscanf(value, "%02x%02x%02x%02x%n", &color[0], &color[1], &color[2], &color[3], &len);
+ if(count < 4 || len != 8) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+#define MAX_DATA_SIZE (7090 * 16) /* from the specification */
+static unsigned char *readStdin(int *length)
+{
+ unsigned char *buffer;
+ int ret;
+
+ buffer = (unsigned char *)malloc(MAX_DATA_SIZE + 1);
+ if(buffer == NULL) {
+ fprintf(stderr, "Memory allocation failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
+ if(ret == 0) {
+ fprintf(stderr, "No input data.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(feof(stdin) == 0) {
+ fprintf(stderr, "Input data is too large.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ buffer[ret] = '\0';
+ *length = ret;
+
+ return buffer;
+}
+
+static FILE *openFile(const char *outfile)
+{
+ FILE *fp;
+
+ if(outfile == NULL || (outfile[0] == '-' && outfile[1] == '\0')) {
+ fp = stdout;
+ _setmode(_fileno(stdout), O_BINARY);
+ } else {
+ fp = fopen(outfile, "wb");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to create file: %s\n", outfile);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return fp;
+}
+
+static int writePNG(QRcode *qrcode, const char *outfile)
+{
+ static FILE *fp; // avoid clobbering by setjmp.
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_colorp palette;
+ png_byte alpha_values[2];
+ unsigned char *row, *p, *q;
+ int x, y, xx, yy, bit;
+ int realwidth;
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ row = (unsigned char *)malloc((realwidth + 7) / 8);
+ if(row == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(outfile[0] == '-' && outfile[1] == '\0') {
+ fp = stdout;
+ _setmode(_fileno(stdout), O_BINARY);
+ } else {
+ fp = fopen(outfile, "wb");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to create file: %s\n", outfile);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(png_ptr == NULL) {
+ fprintf(stderr, "Failed to initialize PNG writer.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if(info_ptr == NULL) {
+ fprintf(stderr, "Failed to initialize PNG write.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fprintf(stderr, "Failed to write PNG image.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ palette = (png_colorp) malloc(sizeof(png_color) * 2);
+ if(palette == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+ palette[0].red = fg_color[0];
+ palette[0].green = fg_color[1];
+ palette[0].blue = fg_color[2];
+ palette[1].red = bg_color[0];
+ palette[1].green = bg_color[1];
+ palette[1].blue = bg_color[2];
+ alpha_values[0] = fg_color[3];
+ alpha_values[1] = bg_color[3];
+ png_set_PLTE(png_ptr, info_ptr, palette, 2);
+ png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);
+
+ png_init_io(png_ptr, fp);
+ png_set_IHDR(png_ptr, info_ptr,
+ realwidth, realwidth,
+ 1,
+ PNG_COLOR_TYPE_PALETTE,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ png_set_pHYs(png_ptr, info_ptr,
+ dpi * INCHES_PER_METER,
+ dpi * INCHES_PER_METER,
+ PNG_RESOLUTION_METER);
+ png_write_info(png_ptr, info_ptr);
+
+ /* top margin */
+ memset(row, 0xff, (realwidth + 7) / 8);
+ for(y=0; y<margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ /* data */
+ p = qrcode->data;
+ for(y=0; y<qrcode->width; y++) {
+ bit = 7;
+ memset(row, 0xff, (realwidth + 7) / 8);
+ q = row;
+ q += margin * size / 8;
+ bit = 7 - (margin * size % 8);
+ for(x=0; x<qrcode->width; x++) {
+ for(xx=0; xx<size; xx++) {
+ *q ^= (*p & 1) << bit;
+ bit--;
+ if(bit < 0) {
+ q++;
+ bit = 7;
+ }
+ }
+ p++;
+ }
+ for(yy=0; yy<size; yy++) {
+ png_write_row(png_ptr, row);
+ }
+ }
+ /* bottom margin */
+ memset(row, 0xff, (realwidth + 7) / 8);
+ for(y=0; y<margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ fclose(fp);
+ free(row);
+ free(palette);
+
+ return 0;
+}
+
+static int writeEPS(QRcode *qrcode, const char *outfile)
+{
+ FILE *fp;
+ unsigned char *row, *p;
+ int x, y, yy;
+ int realwidth;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ /* EPS file header */
+ fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n"
+ "%%%%BoundingBox: 0 0 %d %d\n"
+ "%%%%Pages: 1 1\n"
+ "%%%%EndComments\n", realwidth, realwidth);
+ /* draw point */
+ fprintf(fp, "/p { "
+ "moveto "
+ "0 1 rlineto "
+ "1 0 rlineto "
+ "0 -1 rlineto "
+ "fill "
+ "} bind def "
+ "%d %d scale ", size, size);
+
+ /* data */
+ p = qrcode->data;
+ for(y=0; y<qrcode->width; y++) {
+ row = (p+(y*qrcode->width));
+ yy = (margin + qrcode->width - y - 1);
+
+ for(x=0; x<qrcode->width; x++) {
+ if(*(row+x)&0x1) {
+ fprintf(fp, "%d %d p ", margin + x, yy);
+ }
+ }
+ }
+
+ fprintf(fp, "\n%%%%EOF\n");
+ fclose(fp);
+
+ return 0;
+}
+
+static void writeSVG_writeRect(FILE *fp, int x, int y, int width, char* col, float opacity)
+{
+ if(fg_color[3] != 255) {
+ fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
+ "fill=\"#%s\" fill-opacity=\"%f\" />\n",
+ x, y, width, col, opacity );
+ } else {
+ fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
+ "fill=\"#%s\" />\n",
+ x, y, width, col );
+ }
+}
+
+static int writeSVG( QRcode *qrcode, const char *outfile )
+{
+ FILE *fp;
+ unsigned char *row, *p;
+ int x, y, x0, pen;
+ int symwidth, realwidth;
+ float scale;
+ char fg[7], bg[7];
+ float fg_opacity;
+ float bg_opacity;
+
+ fp = openFile(outfile);
+
+ scale = dpi * INCHES_PER_METER / 100.0;
+
+ 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]);
+ fg_opacity = (float)fg_color[3] / 255;
+ bg_opacity = (float)bg_color[3] / 255;
+
+ /* XML declaration */
+ fputs( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\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, "<!-- Created with qrencode %s (http://fukuchi.org/works/qrencode/index.html.en) -->\n",
+ QRcode_APIVersionString() );
+
+ /* SVG code start */
+ fprintf( fp, "<svg width=\"%0.2fcm\" height=\"%0.2fcm\" viewBox=\"0 0 %d %d\""\
+ " preserveAspectRatio=\"none\" version=\"1.1\""\
+ " xmlns=\"http://www.w3.org/2000/svg\">\n",
+ realwidth / scale, realwidth / scale, symwidth, symwidth
+ );
+
+ /* Make named group */
+ fputs( "\t<g id=\"QRcode\">\n", fp );
+
+ /* Make solid background */
+ if(bg_color[3] != 255) {
+ fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" fill-opacity=\"%f\" />\n", symwidth, symwidth, bg, bg_opacity);
+ } else {
+ fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", symwidth, symwidth, bg);
+ }
+
+ /* Create new viewbox for QR data */
+ fputs( "\t\t<g id=\"Pattern\">\n", fp);
+
+ /* Write data */
+ p = qrcode->data;
+ for(y=0; y<qrcode->width; y++) {
+ row = (p+(y*qrcode->width));
+
+ if( !rle ) {
+ /* no RLE */
+ for(x=0; x<qrcode->width; x++) {
+ if(*(row+x)&0x1) {
+ writeSVG_writeRect(fp, margin + x,
+ margin + y, 1,
+ fg, fg_opacity);
+ }
+ }
+ } else {
+ /* simple RLE */
+ pen = 0;
+ x0 = 0;
+ for(x=0; x<qrcode->width; x++) {
+ if( !pen ) {
+ pen = *(row+x)&0x1;
+ x0 = x;
+ } else {
+ if(!(*(row+x)&0x1)) {
+ writeSVG_writeRect(fp, x0 + margin, y + margin, x-x0, fg, fg_opacity);
+ pen = 0;
+ }
+ }
+ }
+ if( pen ) {
+ writeSVG_writeRect(fp, x0 + margin, y + margin, qrcode->width - x0, fg, fg_opacity);
+ }
+ }
+ }
+ /* Close QR data viewbox */
+ fputs( "\t\t</g>\n", fp );
+
+ /* Close group */
+ fputs( "\t</g>\n", fp );
+
+ /* Close SVG code */
+ fputs( "</svg>\n", fp );
+ fclose( fp );
+
+ return 0;
+}
+
+static void writeANSI_margin(FILE* fp, int realwidth,
+ char* buffer, int buffer_s,
+ char* white, int white_s )
+{
+ int y;
+
+ strncpy(buffer, white, white_s);
+ memset(buffer + white_s, ' ', realwidth * 2);
+ strcpy(buffer + white_s + realwidth * 2, "\033[0m\n"); // reset to default colors
+ for(y=0; y<margin; y++ ){
+ fputs(buffer, fp);
+ }
+}
+
+static int writeANSI(QRcode *qrcode, const char *outfile)
+{
+ FILE *fp;
+ unsigned char *row, *p;
+ int x, y;
+ int realwidth;
+ int last;
+
+ char *white, *black, *buffer;
+ int white_s, black_s, buffer_s;
+
+ if( image_type == ANSI256_TYPE ){
+ /* codes for 256 color compatible terminals */
+ white = "\033[48;5;231m";
+ white_s = 11;
+ black = "\033[48;5;16m";
+ black_s = 10;
+ } else {
+ white = "\033[47m";
+ white_s = 5;
+ black = "\033[40m";
+ black_s = 5;
+ }
+
+ size = 1;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ buffer_s = ( realwidth * white_s ) * 2;
+ buffer = (char *)malloc( buffer_s );
+ if(buffer == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* top margin */
+ writeANSI_margin(fp, realwidth, buffer, buffer_s, white, white_s);
+
+ /* data */
+ p = qrcode->data;
+ for(y=0; y<qrcode->width; y++) {
+ row = (p+(y*qrcode->width));
+
+ memset( buffer, 0, buffer_s );
+ strncpy( buffer, white, white_s );
+ for(x=0; x<margin; x++ ){
+ strncat( buffer, " ", 2 );
+ }
+ last = 0;
+
+ for(x=0; x<qrcode->width; x++) {
+ if(*(row+x)&0x1) {
+ if( last != 1 ){
+ strncat( buffer, black, black_s );
+ last = 1;
+ }
+ } else {
+ if( last != 0 ){
+ strncat( buffer, white, white_s );
+ last = 0;
+ }
+ }
+ strncat( buffer, " ", 2 );
+ }
+
+ if( last != 0 ){
+ strncat( buffer, white, white_s );
+ }
+ for(x=0; x<margin; x++ ){
+ strncat( buffer, " ", 2 );
+ }
+ strncat( buffer, "\033[0m\n", 5 );
+ fputs( buffer, fp );
+ }
+
+ /* bottom margin */
+ writeANSI_margin(fp, realwidth, buffer, buffer_s, white, white_s);
+
+ fclose(fp);
+ free(buffer);
+
+ return 0;
+}
+
+static void writeUTF8_margin(FILE* fp, int realwidth,
+ const char* white, const char *reset,
+ int use_ansi)
+{
+ int x, y;
+
+ for (y = 0; y < margin/2; y++) {
+ fputs(white, fp);
+ for (x = 0; x < realwidth; x++)
+ fputs("\342\226\210", fp);
+ fputs(reset, fp);
+ fputc('\n', fp);
+ }
+}
+
+static int writeUTF8(QRcode *qrcode, const char *outfile, int use_ansi)
+{
+ FILE *fp;
+ int x, y;
+ int realwidth;
+ const char *white, *reset;
+
+ if (use_ansi){
+ white = "\033[40;37;1m";
+ reset = "\033[0m";
+ } else {
+ white = "";
+ reset = "";
+ }
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2);
+
+ /* top margin */
+ writeUTF8_margin(fp, realwidth, white, reset, use_ansi);
+
+ /* data */
+ for(y = 0; y < qrcode->width; y += 2) {
+ unsigned char *row1, *row2;
+ row1 = qrcode->data + y*qrcode->width;
+ row2 = row1 + qrcode->width;
+
+ fputs(white, fp);
+
+ for (x = 0; x < margin; x++)
+ fputs("\342\226\210", fp);
+
+ for (x = 0; x < qrcode->width; x++) {
+ if(row1[x] & 1) {
+ if(y < qrcode->width - 1 && row2[x] & 1) {
+ fputc(' ', fp);
+ } else {
+ fputs("\342\226\204", fp);
+ }
+ } else {
+ if(y < qrcode->width - 1 && row2[x] & 1) {
+ fputs("\342\226\200", fp);
+ } else {
+ fputs("\342\226\210", fp);
+ }
+ }
+ }
+
+ for (x = 0; x < margin; x++)
+ fputs("\342\226\210", fp);
+
+ fputs(reset, fp);
+ fputc('\n', fp);
+ }
+
+ /* bottom margin */
+ writeUTF8_margin(fp, realwidth, white, reset, use_ansi);
+
+ fclose(fp);
+
+ return 0;
+}
+
+static void writeASCII_margin(FILE* fp, int realwidth, char* buffer, int buffer_s, int invert)
+{
+ int y, h;
+
+ h = margin;
+
+ memset(buffer, (invert?'#':' '), realwidth);
+ buffer[realwidth] = '\n';
+ buffer[realwidth + 1] = '\0';
+ for(y=0; y<h; y++ ){
+ fputs(buffer, fp);
+ }
+}
+
+static int writeASCII(QRcode *qrcode, const char *outfile, int invert)
+{
+ FILE *fp;
+ unsigned char *row;
+ int x, y;
+ int realwidth;
+ char *buffer, *p;
+ int buffer_s;
+ char black = '#';
+ char white = ' ';
+
+ if(invert) {
+ black = ' ';
+ white = '#';
+ }
+
+ size = 1;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * 2;
+ buffer_s = realwidth + 2;
+ buffer = (char *)malloc( buffer_s );
+ if(buffer == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* top margin */
+ writeASCII_margin(fp, realwidth, buffer, buffer_s, invert);
+
+ /* data */
+ for(y=0; y<qrcode->width; y++) {
+ row = qrcode->data+(y*qrcode->width);
+ p = buffer;
+
+ memset(p, white, margin * 2);
+ p += margin * 2;
+
+ for(x=0; x<qrcode->width; x++) {
+ if(row[x]&0x1) {
+ *p++ = black;
+ *p++ = black;
+ } else {
+ *p++ = white;
+ *p++ = white;
+ }
+ }
+
+ memset(p, white, margin * 2);
+ p += margin * 2;
+ *p++ = '\n';
+ *p++ = '\0';
+ fputs( buffer, fp );
+ }
+
+ /* bottom margin */
+ writeASCII_margin(fp, realwidth, buffer, buffer_s, invert);
+
+ fclose(fp);
+ free(buffer);
+
+ return 0;
+}
+
+static QRcode *encode(const unsigned char *intext, int length)
+{
+ QRcode *code;
+
+ if(micro) {
+ if(eightbit) {
+ code = QRcode_encodeDataMQR(length, intext, version, level);
+ } else {
+ code = QRcode_encodeStringMQR((char *)intext, version, level, hint, casesensitive);
+ }
+ } else {
+ if(eightbit) {
+ code = QRcode_encodeData(length, intext, version, level);
+ } else {
+ code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive);
+ }
+ }
+
+ return code;
+}
+
+static void qrencode(const unsigned char *intext, int length, const char *outfile)
+{
+ QRcode *qrcode;
+
+ qrcode = encode(intext, length);
+ if(qrcode == NULL) {
+ perror("Failed to encode the input data");
+ exit(EXIT_FAILURE);
+ }
+
+ if(verbose) {
+ fprintf(stderr, "File: %s, Version: %d\n", (outfile!=NULL)?outfile:"(stdout)", qrcode->version);
+ }
+
+ switch(image_type) {
+ case PNG_TYPE:
+ writePNG(qrcode, outfile);
+ break;
+ case EPS_TYPE:
+ writeEPS(qrcode, outfile);
+ break;
+ case SVG_TYPE:
+ writeSVG(qrcode, outfile);
+ break;
+ case ANSI_TYPE:
+ case ANSI256_TYPE:
+ writeANSI(qrcode, outfile);
+ break;
+ case ASCIIi_TYPE:
+ writeASCII(qrcode, outfile, 1);
+ break;
+ case ASCII_TYPE:
+ writeASCII(qrcode, outfile, 0);
+ break;
+ case UTF8_TYPE:
+ writeUTF8(qrcode, outfile, 0);
+ break;
+ case ANSIUTF8_TYPE:
+ writeUTF8(qrcode, outfile, 1);
+ break;
+ default:
+ fprintf(stderr, "Unknown image type.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ QRcode_free(qrcode);
+}
+
+static QRcode_List *encodeStructured(const unsigned char *intext, int length)
+{
+ QRcode_List *list;
+
+ if(eightbit) {
+ list = QRcode_encodeDataStructured(length, intext, version, level);
+ } else {
+ list = QRcode_encodeStringStructured((char *)intext, version, level, hint, casesensitive);
+ }
+
+ return list;
+}
+
+static void qrencodeStructured(const unsigned char *intext, int length, const char *outfile)
+{
+ QRcode_List *qrlist, *p;
+ char filename[FILENAME_MAX];
+ char *base, *q, *suffix = NULL;
+ const char *type_suffix;
+ int i = 1;
+ size_t suffix_size;
+
+ switch(image_type) {
+ case PNG_TYPE:
+ type_suffix = ".png";
+ break;
+ case EPS_TYPE:
+ type_suffix = ".eps";
+ break;
+ case SVG_TYPE:
+ type_suffix = ".svg";
+ break;
+ case ANSI_TYPE:
+ case ANSI256_TYPE:
+ case ASCII_TYPE:
+ case UTF8_TYPE:
+ case ANSIUTF8_TYPE:
+ type_suffix = ".txt";
+ break;
+ default:
+ fprintf(stderr, "Unknown image type.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(outfile == NULL) {
+ fprintf(stderr, "An output filename must be specified to store the structured images.\n");
+ exit(EXIT_FAILURE);
+ }
+ base = strdup(outfile);
+ if(base == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+ suffix_size = strlen(type_suffix);
+ if(strlen(base) > suffix_size) {
+ q = base + strlen(base) - suffix_size;
+ if(strcasecmp(type_suffix, q) == 0) {
+ suffix = strdup(q);
+ *q = '\0';
+ }
+ }
+
+ qrlist = encodeStructured(intext, length);
+ if(qrlist == NULL) {
+ perror("Failed to encode the input data");
+ exit(EXIT_FAILURE);
+ }
+
+ for(p = qrlist; p != NULL; p = p->next) {
+ if(p->code == NULL) {
+ fprintf(stderr, "Failed to encode the input data.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(suffix) {
+ snprintf(filename, FILENAME_MAX, "%s-%02d%s", base, i, suffix);
+ } else {
+ snprintf(filename, FILENAME_MAX, "%s-%02d", base, i);
+ }
+
+ if(verbose) {
+ fprintf(stderr, "File: %s, Version: %d\n", filename, p->code->version);
+ }
+
+ switch(image_type) {
+ case PNG_TYPE:
+ writePNG(p->code, filename);
+ break;
+ case EPS_TYPE:
+ writeEPS(p->code, filename);
+ break;
+ case SVG_TYPE:
+ writeSVG(p->code, filename);
+ break;
+ case ANSI_TYPE:
+ case ANSI256_TYPE:
+ writeANSI(p->code, filename);
+ break;
+ case ASCIIi_TYPE:
+ writeASCII(p->code, filename, 1);
+ break;
+ case ASCII_TYPE:
+ writeASCII(p->code, filename, 0);
+ break;
+ case UTF8_TYPE:
+ writeUTF8(p->code, filename, 0);
+ break;
+ case ANSIUTF8_TYPE:
+ writeUTF8(p->code, filename, 0);
+ break;
+
+ default:
+ fprintf(stderr, "Unknown image type.\n");
+ exit(EXIT_FAILURE);
+ }
+ i++;
+ }
+
+ free(base);
+ if(suffix) {
+ free(suffix);
+ }
+
+ QRcode_List_free(qrlist);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, lindex = -1;
+ char *outfile = NULL;
+ unsigned char *intext = NULL;
+ int length = 0;
+
+ while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
+ switch(opt) {
+ case 'h':
+ if(lindex == 0) {
+ usage(1, 1);
+ } else {
+ usage(1, 0);
+ }
+ exit(EXIT_SUCCESS);
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 's':
+ size = atoi(optarg);
+ if(size <= 0) {
+ fprintf(stderr, "Invalid size: %d\n", size);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ version = atoi(optarg);
+ if(version < 0) {
+ fprintf(stderr, "Invalid version: %d\n", version);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'l':
+ switch(*optarg) {
+ case 'l':
+ case 'L':
+ level = QR_ECLEVEL_L;
+ break;
+ case 'm':
+ case 'M':
+ level = QR_ECLEVEL_M;
+ break;
+ case 'q':
+ case 'Q':
+ level = QR_ECLEVEL_Q;
+ break;
+ case 'h':
+ case 'H':
+ level = QR_ECLEVEL_H;
+ break;
+ default:
+ fprintf(stderr, "Invalid level: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ break;
+ }
+ break;
+ case 'm':
+ margin = atoi(optarg);
+ if(margin < 0) {
+ fprintf(stderr, "Invalid margin: %d\n", margin);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'd':
+ dpi = atoi(optarg);
+ if( dpi < 0 ) {
+ fprintf(stderr, "Invalid DPI: %d\n", dpi);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 't':
+ if(strcasecmp(optarg, "png") == 0) {
+ image_type = PNG_TYPE;
+ } else if(strcasecmp(optarg, "eps") == 0) {
+ image_type = EPS_TYPE;
+ } else if(strcasecmp(optarg, "svg") == 0) {
+ image_type = SVG_TYPE;
+ } else if(strcasecmp(optarg, "ansi") == 0) {
+ image_type = ANSI_TYPE;
+ } else if(strcasecmp(optarg, "ansi256") == 0) {
+ image_type = ANSI256_TYPE;
+ } else if(strcasecmp(optarg, "asciii") == 0) {
+ image_type = ASCIIi_TYPE;
+ } else if(strcasecmp(optarg, "ascii") == 0) {
+ image_type = ASCII_TYPE;
+ } else if(strcasecmp(optarg, "utf8") == 0) {
+ image_type = UTF8_TYPE;
+ } else if(strcasecmp(optarg, "ansiutf8") == 0) {
+ image_type = ANSIUTF8_TYPE;
+ } else {
+ fprintf(stderr, "Invalid image type: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'S':
+ structured = 1;
+ break;
+ case 'k':
+ hint = QR_MODE_KANJI;
+ break;
+ case 'c':
+ casesensitive = 1;
+ break;
+ case 'i':
+ casesensitive = 0;
+ break;
+ case '8':
+ eightbit = 1;
+ break;
+ case 'M':
+ micro = 1;
+ break;
+ case 'f':
+ if(color_set(fg_color, optarg)) {
+ fprintf(stderr, "Invalid foreground color value.\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'b':
+ if(color_set(bg_color, optarg)) {
+ fprintf(stderr, "Invalid background color value.\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'V':
+ usage(0, 0);
+ exit(EXIT_SUCCESS);
+ break;
+ case 0:
+ break;
+ default:
+ fprintf(stderr, "Try `qrencode --help' for more information.\n");
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if(argc == 1) {
+ usage(1, 0);
+ exit(EXIT_SUCCESS);
+ }
+
+ if(outfile == NULL && image_type == PNG_TYPE) {
+ fprintf(stderr, "No output filename is given.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(optind < argc) {
+ intext = (unsigned char *)argv[optind];
+ length = strlen((char *)intext);
+ }
+ if(intext == NULL) {
+ intext = readStdin(&length);
+ }
+
+ if(micro && version > MQRSPEC_VERSION_MAX) {
+ fprintf(stderr, "Version should be less or equal to %d.\n", MQRSPEC_VERSION_MAX);
+ exit(EXIT_FAILURE);
+ } else if(!micro && version > QRSPEC_VERSION_MAX) {
+ fprintf(stderr, "Version should be less or equal to %d.\n", QRSPEC_VERSION_MAX);
+ exit(EXIT_FAILURE);
+ }
+
+ if(margin < 0) {
+ if(micro) {
+ margin = 2;
+ } else {
+ margin = 4;
+ }
+ }
+
+ if(micro) {
+ if(version == 0) {
+ fprintf(stderr, "Version must be specified to encode a Micro QR Code symbol.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(structured) {
+ fprintf(stderr, "Micro QR Code does not support structured symbols.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if(structured) {
+ if(version == 0) {
+ fprintf(stderr, "Version must be specified to encode structured symbols.\n");
+ exit(EXIT_FAILURE);
+ }
+ qrencodeStructured(intext, length, outfile);
+ } else {
+ qrencode(intext, length, outfile);
+ }
+
+ return 0;
+}