Przeglądaj źródła

First pass at qr code generation

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@720 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden 11 lat temu
rodzic
commit
f2f33a3536
13 zmienionych plików z 1992 dodań i 0 usunięć
  1. 206 0
      QRCode/bitstream.c
  2. 40 0
      QRCode/bitstream.h
  3. 15 0
      QRCode/config.h
  4. 357 0
      QRCode/mask.c
  5. 38 0
      QRCode/mask.h
  6. 177 0
      QRCode/mmask.c
  7. 34 0
      QRCode/mmask.h
  8. 232 0
      QRCode/mqrspec.c
  9. 152 0
      QRCode/mqrspec.h
  10. 327 0
      QRCode/rscode.c
  11. 41 0
      QRCode/rscode.h
  12. 326 0
      QRCode/split.c
  13. 47 0
      QRCode/split.h

+ 206 - 0
QRCode/bitstream.c

@@ -0,0 +1,206 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Binary sequence class.
+ * Copyright (C) 2006-2014 Kentaro Fukuchi <[email protected]>
+ *
+ * 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 "bitstream.h"
+
+#define DEFAULT_BUFSIZE (128)
+
+BitStream *BitStream_new(void)
+{
+	BitStream *bstream;
+
+	bstream = (BitStream *)malloc(sizeof(BitStream));
+	if(bstream == NULL) return NULL;
+
+	bstream->length = 0;
+	bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE);
+	if(bstream->data == NULL) {
+		free(bstream);
+		return NULL;
+	}
+	bstream->datasize = DEFAULT_BUFSIZE;
+
+	return bstream;
+}
+
+static int BitStream_expand(BitStream *bstream)
+{
+	unsigned char *data;
+
+	data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2);
+	if(data == NULL) {
+		return -1;
+	}
+
+	bstream->data = data;
+	bstream->datasize *= 2;
+
+	return 0;
+}
+
+static void BitStream_writeNum(unsigned char *dest, int bits, unsigned int num)
+{
+	unsigned int mask;
+	int i;
+	unsigned char *p;
+
+	p = dest;
+	mask = 1 << (bits - 1);
+	for(i=0; i<bits; i++) {
+		if(num & mask) {
+			*p = 1;
+		} else {
+			*p = 0;
+		}
+		p++;
+		mask = mask >> 1;
+	}
+}
+
+static void BitStream_writeBytes(unsigned char *dest, int size, unsigned char *data)
+{
+	unsigned char mask;
+	int i, j;
+	unsigned char *p;
+
+	p = dest;
+	for(i=0; i<size; i++) {
+		mask = 0x80;
+		for(j=0; j<8; j++) {
+			if(data[i] & mask) {
+				*p = 1;
+			} else {
+				*p = 0;
+			}
+			p++;
+			mask = mask >> 1;
+		}
+	}
+}
+
+int BitStream_append(BitStream *bstream, BitStream *arg)
+{
+	int ret;
+
+	if(arg == NULL) {
+		return -1;
+	}
+	if(arg->length == 0) {
+		return 0;
+	}
+
+	while(bstream->length + arg->length > bstream->datasize) {
+		ret = BitStream_expand(bstream);
+		if(ret < 0) return ret;
+	}
+
+	memcpy(bstream->data + bstream->length, arg->data, arg->length);
+	bstream->length += arg->length;
+
+	return 0;
+}
+
+int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num)
+{
+	int ret;
+
+	if(bits == 0) return 0;
+
+	while(bstream->datasize - bstream->length < bits) {
+		ret = BitStream_expand(bstream);
+		if(ret < 0) return ret;
+	}
+	BitStream_writeNum(bstream->data + bstream->length, bits, num);
+	bstream->length += bits;
+
+	return 0;
+}
+
+int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data)
+{
+	int ret;
+
+	if(size == 0) return 0;
+
+	while(bstream->datasize - bstream->length < size * 8) {
+		ret = BitStream_expand(bstream);
+		if(ret < 0) return ret;
+	}
+	BitStream_writeBytes(bstream->data + bstream->length, size, data);
+	bstream->length += size * 8;
+
+	return 0;
+}
+
+unsigned char *BitStream_toByte(BitStream *bstream)
+{
+	int i, j, size, bytes;
+	unsigned char *data, v;
+	unsigned char *p;
+
+	size = BitStream_size(bstream);
+	if(size == 0) {
+		return NULL;
+	}
+	data = (unsigned char *)malloc((size + 7) / 8);
+	if(data == NULL) {
+		return NULL;
+	}
+
+	bytes = size  / 8;
+
+	p = bstream->data;
+	for(i=0; i<bytes; i++) {
+		v = 0;
+		for(j=0; j<8; j++) {
+			v = v << 1;
+			v |= *p;
+			p++;
+		}
+		data[i] = v;
+	}
+	if(size & 7) {
+		v = 0;
+		for(j=0; j<(size & 7); j++) {
+			v = v << 1;
+			v |= *p;
+			p++;
+		}
+		data[bytes] = v;
+	}
+
+	return data;
+}
+
+void BitStream_free(BitStream *bstream)
+{
+	if(bstream != NULL) {
+		free(bstream->data);
+		free(bstream);
+	}
+}

+ 40 - 0
QRCode/bitstream.h

@@ -0,0 +1,40 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Binary sequence class.
+ * Copyright (C) 2006-2014 Kentaro Fukuchi <[email protected]>
+ *
+ * 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
+ */
+
+#ifndef __BITSTREAM_H__
+#define __BITSTREAM_H__
+
+typedef struct {
+	int length;
+	unsigned char *data;
+	int datasize;
+} BitStream;
+
+extern BitStream *BitStream_new(void);
+extern int BitStream_append(BitStream *bstream, BitStream *arg);
+extern int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num);
+extern int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data);
+#define BitStream_size(__bstream__) (__bstream__->length)
+#define BitStream_reset(__bstream__) (__bstream__->length = 0)
+extern unsigned char *BitStream_toByte(BitStream *bstream);
+extern void BitStream_free(BitStream *bstream);
+
+#endif /* __BITSTREAM_H__ */

+ 15 - 0
QRCode/config.h

@@ -0,0 +1,15 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+// manual config.h for microsoft visual studio
+
+#define HAVE_STRDUP 1
+
+#define __STATIC static
+
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 0
+#define MICRO_VERSION 0
+#define VERSION ""
+
+#endif

+ 357 - 0
QRCode/mask.c

@@ -0,0 +1,357 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking.
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#include "qrencode.h"
+#include "qrspec.h"
+#include "mask.h"
+
+__STATIC int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
+{
+	unsigned int format;
+	unsigned char v;
+	int i;
+	int blacks = 0;
+
+	format = QRspec_getFormatInfo(mask, level);
+
+	for(i=0; i<8; i++) {
+		if(format & 1) {
+			blacks += 2;
+			v = 0x85;
+		} else {
+			v = 0x84;
+		}
+		frame[width * 8 + width - 1 - i] = v;
+		if(i < 6) {
+			frame[width * i + 8] = v;
+		} else {
+			frame[width * (i + 1) + 8] = v;
+		}
+		format= format >> 1;
+	}
+	for(i=0; i<7; i++) {
+		if(format & 1) {
+			blacks += 2;
+			v = 0x85;
+		} else {
+			v = 0x84;
+		}
+		frame[width * (width - 7 + i) + 8] = v;
+		if(i == 0) {
+			frame[width * 8 + 7] = v;
+		} else {
+			frame[width * 8 + 6 - i] = v;
+		}
+		format= format >> 1;
+	}
+
+	return blacks;
+}
+
+/**
+ * Demerit coefficients.
+ * See Section 8.8.2, pp.45, JIS X0510:2004.
+ */
+#define N1 (3)
+#define N2 (3)
+#define N3 (40)
+#define N4 (10)
+
+#define MASKMAKER(__exp__) \
+	int x, y;\
+	int b = 0;\
+\
+	for(y=0; y<width; y++) {\
+		for(x=0; x<width; x++) {\
+			if(*s & 0x80) {\
+				*d = *s;\
+			} else {\
+				*d = *s ^ ((__exp__) == 0);\
+			}\
+			b += (int)(*d & 1);\
+			s++; d++;\
+		}\
+	}\
+	return b;
+
+static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER((x+y)&1)
+}
+
+static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER(y&1)
+}
+
+static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER(x%3)
+}
+
+static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER((x+y)%3)
+}
+
+static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER(((y/2)+(x/3))&1)
+}
+
+static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER(((x*y)&1)+(x*y)%3)
+}
+
+static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER((((x*y)&1)+(x*y)%3)&1)
+}
+
+static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER((((x*y)%3)+((x+y)&1))&1)
+}
+
+#define maskNum (8)
+typedef int MaskMaker(int, const unsigned char *, unsigned char *);
+static MaskMaker *maskMakers[maskNum] = {
+	Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
+	Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
+};
+
+#ifdef WITH_TESTS
+unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
+{
+	unsigned char *masked;
+
+	masked = (unsigned char *)malloc(width * width);
+	if(masked == NULL) return NULL;
+
+	maskMakers[mask](width, frame, masked);
+
+	return masked;
+}
+#endif
+
+unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
+{
+	unsigned char *masked;
+
+	if(mask < 0 || mask >= maskNum) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	masked = (unsigned char *)malloc(width * width);
+	if(masked == NULL) return NULL;
+
+	maskMakers[mask](width, frame, masked);
+	Mask_writeFormatInformation(width, masked, mask, level);
+
+	return masked;
+}
+
+
+//static int n1;
+//static int n2;
+//static int n3;
+//static int n4;
+
+__STATIC int Mask_calcN1N3(int length, int *runLength)
+{
+	int i;
+	int demerit = 0;
+	int fact;
+
+	for(i=0; i<length; i++) {
+		if(runLength[i] >= 5) {
+			demerit += N1 + (runLength[i] - 5);
+			//n1 += N1 + (runLength[i] - 5);
+		}
+		if((i & 1)) {
+			if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
+				fact = runLength[i] / 3;
+				if(runLength[i-2] == fact &&
+				   runLength[i-1] == fact &&
+				   runLength[i+1] == fact &&
+				   runLength[i+2] == fact) {
+					if(i == 3 || runLength[i-3] >= 4 * fact) {
+						demerit += N3;
+						//n3 += N3;
+					} else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
+						demerit += N3;
+						//n3 += N3;
+					}
+				}
+			}
+		}
+	}
+
+	return demerit;
+}
+
+__STATIC int Mask_calcN2(int width, unsigned char *frame)
+{
+	int x, y;
+	unsigned char *p;
+	unsigned char b22, w22;
+	int demerit = 0;
+
+	p = frame + width + 1;
+	for(y=1; y<width; y++) {
+		for(x=1; x<width; x++) {
+			b22 = p[0] & p[-1] & p[-width] & p [-width-1];
+			w22 = p[0] | p[-1] | p[-width] | p [-width-1];
+			if((b22 | (w22 ^ 1))&1) {
+				demerit += N2;
+			}
+			p++;
+		}
+		p++;
+	}
+
+	return demerit;
+}
+
+__STATIC int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
+{
+	int head;
+	int i;
+	unsigned char prev;
+
+	if(frame[0] & 1) {
+		runLength[0] = -1;
+		head = 1;
+	} else {
+		head = 0;
+	}
+	runLength[head] = 1;
+	prev = frame[0];
+
+	for(i=1; i<width; i++) {
+		if((frame[i] ^ prev) & 1) {
+			head++;
+			runLength[head] = 1;
+			prev = frame[i];
+		} else {
+			runLength[head]++;
+		}
+	}
+
+	return head + 1;
+}
+
+__STATIC int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
+{
+	int head;
+	int i;
+	unsigned char prev;
+
+	if(frame[0] & 1) {
+		runLength[0] = -1;
+		head = 1;
+	} else {
+		head = 0;
+	}
+	runLength[head] = 1;
+	prev = frame[0];
+
+	for(i=1; i<width; i++) {
+		if((frame[i * width] ^ prev) & 1) {
+			head++;
+			runLength[head] = 1;
+			prev = frame[i * width];
+		} else {
+			runLength[head]++;
+		}
+	}
+
+	return head + 1;
+}
+
+__STATIC int Mask_evaluateSymbol(int width, unsigned char *frame)
+{
+	int x, y;
+	int demerit = 0;
+	int runLength[QRSPEC_WIDTH_MAX + 1];
+	int length;
+
+	demerit += Mask_calcN2(width, frame);
+
+	for(y=0; y<width; y++) {
+		length = Mask_calcRunLengthH(width, frame + y * width, runLength);
+		demerit += Mask_calcN1N3(length, runLength);
+	}
+
+	for(x=0; x<width; x++) {
+		length = Mask_calcRunLengthV(width, frame + x, runLength);
+		demerit += Mask_calcN1N3(length, runLength);
+	}
+
+	return demerit;
+}
+
+unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
+{
+	int i;
+	unsigned char *mask, *bestMask;
+	int minDemerit = INT_MAX;
+	int blacks;
+	int bratio;
+	int demerit;
+	int w2 = width * width;
+
+	mask = (unsigned char *)malloc(w2);
+	if(mask == NULL) return NULL;
+	bestMask = (unsigned char *)malloc(w2);
+	if(bestMask == NULL) {
+		free(mask);
+		return NULL;
+	}
+
+	for(i=0; i<maskNum; i++) {
+//		n1 = n2 = n3 = n4 = 0;
+		demerit = 0;
+		blacks = maskMakers[i](width, frame, mask);
+		blacks += Mask_writeFormatInformation(width, mask, i, level);
+		bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
+		demerit = (abs(bratio - 50) / 5) * N4;
+//		n4 = demerit;
+		demerit += Mask_evaluateSymbol(width, mask);
+//		printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
+		if(demerit < minDemerit) {
+			minDemerit = demerit;
+			memcpy(bestMask, mask, w2);
+		}
+	}
+	free(mask);
+	return bestMask;
+}

+ 38 - 0
QRCode/mask.h

@@ -0,0 +1,38 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking.
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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
+ */
+
+#ifndef __MASK_H__
+#define __MASK_H__
+
+extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
+
+#ifdef WITH_TESTS
+extern int Mask_calcN2(int width, unsigned char *frame);
+extern int Mask_calcN1N3(int length, int *runLength);
+extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength);
+extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength);
+extern int Mask_evaluateSymbol(int width, unsigned char *frame);
+extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
+#endif
+
+#endif /* __MASK_H__ */

+ 177 - 0
QRCode/mmask.c

@@ -0,0 +1,177 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking for Micro QR Code.
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#include "qrencode.h"
+#include "mqrspec.h"
+#include "mmask.h"
+
+__STATIC void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
+{
+	unsigned int format;
+	unsigned char v;
+	int i;
+
+	format = MQRspec_getFormatInfo(mask, version, level);
+
+	for(i=0; i<8; i++) {
+		v = 0x84 | (format & 1);
+		frame[width * (i + 1) + 8] = v;
+		format = format >> 1;
+	}
+	for(i=0; i<7; i++) {
+		v = 0x84 | (format & 1);
+		frame[width * 8 + 7 - i] = v;
+		format = format >> 1;
+	}
+}
+
+#define MASKMAKER(__exp__) \
+	int x, y;\
+\
+	for(y=0; y<width; y++) {\
+		for(x=0; x<width; x++) {\
+			if(*s & 0x80) {\
+				*d = *s;\
+			} else {\
+				*d = *s ^ ((__exp__) == 0);\
+			}\
+			s++; d++;\
+		}\
+	}
+
+static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER(y&1)
+}
+
+static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER(((y/2)+(x/3))&1)
+}
+
+static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER((((x*y)&1)+(x*y)%3)&1)
+}
+
+static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
+{
+	MASKMAKER((((x+y)&1)+((x*y)%3))&1)
+}
+
+#define maskNum (4)
+typedef void MaskMaker(int, const unsigned char *, unsigned char *);
+static MaskMaker *maskMakers[maskNum] = {
+	Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
+};
+
+#ifdef WITH_TESTS
+unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
+{
+	unsigned char *masked;
+
+	masked = (unsigned char *)malloc(width * width);
+	if(masked == NULL) return NULL;
+
+	maskMakers[mask](width, frame, masked);
+
+	return masked;
+}
+#endif
+
+unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
+{
+	unsigned char *masked;
+	int width;
+
+	if(mask < 0 || mask >= maskNum) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	width = MQRspec_getWidth(version);
+	masked = (unsigned char *)malloc(width * width);
+	if(masked == NULL) return NULL;
+
+	maskMakers[mask](width, frame, masked);
+	MMask_writeFormatInformation(version, width, masked, mask, level);
+
+	return masked;
+}
+
+__STATIC int MMask_evaluateSymbol(int width, unsigned char *frame)
+{
+	int x, y;
+	unsigned char *p;
+	int sum1 = 0, sum2 = 0;
+
+	p = frame + width * (width - 1);
+	for(x=1; x<width; x++) {
+		sum1 += (p[x] & 1);
+	}
+
+	p = frame + width * 2 - 1;
+	for(y=1; y<width; y++) {
+		sum2 += (*p & 1);
+		p += width;
+	}
+
+	return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
+}
+
+unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
+{
+	int i;
+	unsigned char *mask, *bestMask;
+	int maxScore = 0;
+	int score;
+	int width;
+
+	width = MQRspec_getWidth(version);
+
+	mask = (unsigned char *)malloc(width * width);
+	if(mask == NULL) return NULL;
+	bestMask = NULL;
+
+	for(i=0; i<maskNum; i++) {
+		score = 0;
+		maskMakers[i](width, frame, mask);
+		MMask_writeFormatInformation(version, width, mask, i, level);
+		score = MMask_evaluateSymbol(width, mask);
+		if(score > maxScore) {
+			maxScore = score;
+			free(bestMask);
+			bestMask = mask;
+			mask = (unsigned char *)malloc(width * width);
+			if(mask == NULL) break;
+		}
+	}
+	free(mask);
+	return bestMask;
+}

+ 34 - 0
QRCode/mmask.h

@@ -0,0 +1,34 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking for Micro QR Code.
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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
+ */
+
+#ifndef __MMASK_H__
+#define __MMASK_H__
+
+extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
+
+#ifdef WITH_TESTS
+extern int MMask_evaluateSymbol(int width, unsigned char *frame);
+extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
+#endif
+
+#endif /* __MMASK_H__ */

+ 232 - 0
QRCode/mqrspec.c

@@ -0,0 +1,232 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Micor QR Code specification in convenient format. 
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ *  or
+ * "Automatic identification and data capture techniques -- 
+ *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * 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 <errno.h>
+
+#include "mqrspec.h"
+
+/******************************************************************************
+ * Version and capacity
+ *****************************************************************************/
+
+typedef struct {
+	int width; //< Edge length of the symbol
+	int ec[4];  //< Number of ECC code (bytes)
+} MQRspec_Capacity;
+
+/**
+ * Table of the capacity of symbols
+ * See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004.
+ */
+static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
+	{  0, {0,  0,  0, 0}},
+	{ 11, {2,  0,  0, 0}},
+	{ 13, {5,  6,  0, 0}},
+	{ 15, {6,  8,  0, 0}},
+	{ 17, {8, 10, 14, 0}}
+};
+
+int MQRspec_getDataLengthBit(int version, QRecLevel level)
+{
+	int w;
+	int ecc;
+
+	w = mqrspecCapacity[version].width - 1;
+	ecc = mqrspecCapacity[version].ec[level];
+	if(ecc == 0) return 0;
+	return w * w - 64 - ecc * 8;
+}
+
+int MQRspec_getDataLength(int version, QRecLevel level)
+{
+	return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
+}
+
+int MQRspec_getECCLength(int version, QRecLevel level)
+{
+	return mqrspecCapacity[version].ec[level];
+}
+
+int MQRspec_getWidth(int version)
+{
+	return mqrspecCapacity[version].width;
+}
+
+/******************************************************************************
+ * Length indicator
+ *****************************************************************************/
+
+/**
+ * See Table 3 (pp.107) of Appendix 1, JIS X0510:2004.
+ */
+static const int lengthTableBits[4][4] = {
+	{ 3, 4, 5, 6},
+	{ 0, 3, 4, 5},
+	{ 0, 0, 4, 5},
+	{ 0, 0, 3, 4}
+};
+
+int MQRspec_lengthIndicator(QRencodeMode mode, int version)
+{
+	return lengthTableBits[mode][version - 1];
+}
+
+int MQRspec_maximumWords(QRencodeMode mode, int version)
+{
+	int bits;
+	int words;
+
+	bits = lengthTableBits[mode][version - 1];
+	words = (1 << bits) - 1;
+	if(mode == QR_MODE_KANJI) {
+		words *= 2; // the number of bytes is required
+	}
+
+	return words;
+}
+
+/******************************************************************************
+ * Format information
+ *****************************************************************************/
+
+/* See calcFormatInfo in tests/test_mqrspec.c */
+static const unsigned int formatInfo[4][8] = {
+	{0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
+	{0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
+	{0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
+	{0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
+};
+
+/* See Table 10 of Appendix 1. (pp.115) */
+static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
+	{-1, -1, -1},
+	{ 0, -1, -1},
+	{ 1,  2, -1},
+	{ 3,  4, -1},
+	{ 5,  6,  7}
+};
+
+unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
+{
+	int type;
+
+	if(mask < 0 || mask > 3) return 0;
+	if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
+	if(level == QR_ECLEVEL_H) return 0;
+	type = typeTable[version][level];
+	if(type < 0) return 0;
+
+	return formatInfo[mask][type];
+}
+
+/******************************************************************************
+ * Frame
+ *****************************************************************************/
+
+/**
+ * Put a finder pattern.
+ * @param frame
+ * @param width
+ * @param ox,oy upper-left coordinate of the pattern
+ */
+static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
+{
+	static const unsigned char finder[] = {
+		0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+		0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+		0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+		0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+		0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+		0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+		0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+	};
+	int x, y;
+	const unsigned char *s;
+
+	frame += oy * width + ox;
+	s = finder;
+	for(y=0; y<7; y++) {
+		for(x=0; x<7; x++) {
+			frame[x] = s[x];
+		}
+		frame += width;
+		s += 7;
+	}
+}
+
+static unsigned char *MQRspec_createFrame(int version)
+{
+	unsigned char *frame, *p, *q;
+	int width;
+	int x, y;
+
+	width = mqrspecCapacity[version].width;
+	frame = (unsigned char *)malloc(width * width);
+	if(frame == NULL) return NULL;
+
+	memset(frame, 0, width * width);
+	/* Finder pattern */
+	putFinderPattern(frame, width, 0, 0);
+	/* Separator */
+	p = frame;
+	for(y=0; y<7; y++) {
+		p[7] = 0xc0;
+		p += width;
+	}
+	memset(frame + width * 7, 0xc0, 8);
+	/* Mask format information area */
+	memset(frame + width * 8 + 1, 0x84, 8);
+	p = frame + width + 8;
+	for(y=0; y<7; y++) {
+		*p = 0x84;
+		p += width;
+	}
+	/* Timing pattern */
+	p = frame + 8;
+	q = frame + width * 8;
+	for(x=1; x<width-7; x++) {
+		*p =  0x90 | (x & 1);
+		*q =  0x90 | (x & 1);
+		p++;
+		q += width;
+	}
+
+	return frame;
+}
+
+unsigned char *MQRspec_newFrame(int version)
+{
+	if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
+
+	return MQRspec_createFrame(version);
+}

+ 152 - 0
QRCode/mqrspec.h

@@ -0,0 +1,152 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Micro QR Code specification in convenient format. 
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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
+ */
+
+#ifndef __MQRSPEC_H__
+#define __MQRSPEC_H__
+
+#include "qrencode.h"
+
+/******************************************************************************
+ * Version and capacity
+ *****************************************************************************/
+
+/**
+ * Maximum width of a symbol
+ */
+#define MQRSPEC_WIDTH_MAX 17
+
+/**
+ * Return maximum data code length (bits) for the version.
+ * @param version
+ * @param level
+ * @return maximum size (bits)
+ */
+extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
+
+/**
+ * Return maximum data code length (bytes) for the version.
+ * @param version
+ * @param level
+ * @return maximum size (bytes)
+ */
+extern int MQRspec_getDataLength(int version, QRecLevel level);
+
+/**
+ * Return maximum error correction code length (bytes) for the version.
+ * @param version
+ * @param level
+ * @return ECC size (bytes)
+ */
+extern int MQRspec_getECCLength(int version, QRecLevel level);
+
+/**
+ * Return a version number that satisfies the input code length.
+ * @param size input code length (byte)
+ * @param level
+ * @return version number
+ */
+extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
+
+/**
+ * Return the width of the symbol for the version.
+ * @param version
+ * @return width
+ */
+extern int MQRspec_getWidth(int version);
+
+/**
+ * Return the numer of remainder bits.
+ * @param version
+ * @return number of remainder bits
+ */
+extern int MQRspec_getRemainder(int version);
+
+/******************************************************************************
+ * Length indicator
+ *****************************************************************************/
+
+/**
+ * Return the size of lenght indicator for the mode and version.
+ * @param mode
+ * @param version
+ * @return the size of the appropriate length indicator (bits).
+ */
+extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
+
+/**
+ * Return the maximum length for the mode and version.
+ * @param mode
+ * @param version
+ * @return the maximum length (bytes)
+ */
+extern int MQRspec_maximumWords(QRencodeMode mode, int version);
+
+/******************************************************************************
+ * Version information pattern
+ *****************************************************************************/
+
+/**
+ * Return BCH encoded version information pattern that is used for the symbol
+ * of version 7 or greater. Use lower 18 bits.
+ * @param version
+ * @return BCH encoded version information pattern
+ */
+extern unsigned int MQRspec_getVersionPattern(int version);
+
+/******************************************************************************
+ * Format information
+ *****************************************************************************/
+
+/**
+ * Return BCH encoded format information pattern.
+ * @param mask
+ * @param version
+ * @param level
+ * @return BCH encoded format information pattern
+ */
+extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
+
+/******************************************************************************
+ * Frame
+ *****************************************************************************/
+
+/**
+ * Return a copy of initialized frame.
+ * When the same version is requested twice or more, a copy of cached frame
+ * is returned.
+ * @param version
+ * @return Array of unsigned char. You can free it by free().
+ */
+extern unsigned char *MQRspec_newFrame(int version);
+
+/******************************************************************************
+ * Mode indicator
+ *****************************************************************************/
+
+/**
+ * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107.
+ */
+#define MQRSPEC_MODEID_NUM       0
+#define MQRSPEC_MODEID_AN        1
+#define MQRSPEC_MODEID_8         2
+#define MQRSPEC_MODEID_KANJI     3
+
+#endif /* __MQRSPEC_H__ */

+ 327 - 0
QRCode/rscode.c

@@ -0,0 +1,327 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Reed solomon encoder. This code is taken from Phil Karn's libfec then
+ * editted and packed into a pair of .c and .h files.
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * (libfec is released under the GNU Lesser General Public License.)
+ *
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#ifdef HAVE_LIBPTHREAD
+#  include <pthread.h>
+#endif
+
+#include "rscode.h"
+
+/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs
+ *
+ */
+typedef unsigned char data_t;
+
+
+/**
+ * Reed-Solomon codec control block
+ */
+struct _RS {
+	int mm;              /* Bits per symbol */
+	int nn;              /* Symbols per block (= (1<<mm)-1) */
+	data_t *alpha_to;     /* log lookup table */
+	data_t *index_of;     /* Antilog lookup table */
+	data_t *genpoly;      /* Generator polynomial */
+	int nroots;     /* Number of generator roots = number of parity symbols */
+	int fcr;        /* First consecutive root, index form */
+	int prim;       /* Primitive element, index form */
+	int iprim;      /* prim-th root of 1, index form */
+	int pad;        /* Padding bytes in shortened block */
+	int gfpoly;
+	struct _RS *next;
+};
+
+static RS *rslist = NULL;
+#ifdef HAVE_LIBPTHREAD
+static pthread_mutex_t rslist_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+int modnn(RS *rs, int x){
+	while (x >= rs->nn) {
+		x -= rs->nn;
+		x = (x >> rs->mm) + (x & rs->nn);
+	}
+	return x;
+}
+
+
+#define MODNN(x) modnn(rs,x)
+
+#define MM (rs->mm)
+#define NN (rs->nn)
+#define ALPHA_TO (rs->alpha_to) 
+#define INDEX_OF (rs->index_of)
+#define GENPOLY (rs->genpoly)
+#define NROOTS (rs->nroots)
+#define FCR (rs->fcr)
+#define PRIM (rs->prim)
+#define IPRIM (rs->iprim)
+#define PAD (rs->pad)
+#define A0 (NN)
+
+
+/* Initialize a Reed-Solomon codec
+ * symsize = symbol size, bits
+ * gfpoly = Field generator polynomial coefficients
+ * fcr = first root of RS code generator polynomial, index form
+ * prim = primitive element to generate polynomial roots
+ * nroots = RS code generator polynomial degree (number of roots)
+ * pad = padding bytes at front of shortened block
+ */
+static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
+{
+  RS *rs;
+
+
+/* Common code for intializing a Reed-Solomon control block (char or int symbols)
+ * Copyright 2004 Phil Karn, KA9Q
+ * May be used under the terms of the GNU Lesser General Public License (LGPL)
+ */
+//#undef NULL
+//#define NULL ((void *)0)
+
+  int i, j, sr,root,iprim;
+
+  rs = NULL;
+  /* Check parameter ranges */
+  if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){
+    goto done;
+  }
+
+  if(fcr < 0 || fcr >= (1<<symsize))
+    goto done;
+  if(prim <= 0 || prim >= (1<<symsize))
+    goto done;
+  if(nroots < 0 || nroots >= (1<<symsize))
+    goto done; /* Can't have more roots than symbol values! */
+  if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
+    goto done; /* Too much padding */
+
+  rs = (RS *)calloc(1,sizeof(RS));
+  if(rs == NULL)
+    goto done;
+
+  rs->mm = symsize;
+  rs->nn = (1<<symsize)-1;
+  rs->pad = pad;
+
+  rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
+  if(rs->alpha_to == NULL){
+    free(rs);
+    rs = NULL;
+    goto done;
+  }
+  rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
+  if(rs->index_of == NULL){
+    free(rs->alpha_to);
+    free(rs);
+    rs = NULL;
+    goto done;
+  }
+
+  /* Generate Galois field lookup tables */
+  rs->index_of[0] = A0; /* log(zero) = -inf */
+  rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
+  sr = 1;
+  for(i=0;i<rs->nn;i++){
+    rs->index_of[sr] = i;
+    rs->alpha_to[i] = sr;
+    sr <<= 1;
+    if(sr & (1<<symsize))
+      sr ^= gfpoly;
+    sr &= rs->nn;
+  }
+  if(sr != 1){
+    /* field generator polynomial is not primitive! */
+    free(rs->alpha_to);
+    free(rs->index_of);
+    free(rs);
+    rs = NULL;
+    goto done;
+  }
+
+  /* Form RS code generator polynomial from its roots */
+  rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1));
+  if(rs->genpoly == NULL){
+    free(rs->alpha_to);
+    free(rs->index_of);
+    free(rs);
+    rs = NULL;
+    goto done;
+  }
+  rs->fcr = fcr;
+  rs->prim = prim;
+  rs->nroots = nroots;
+  rs->gfpoly = gfpoly;
+
+  /* Find prim-th root of 1, used in decoding */
+  for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
+    ;
+  rs->iprim = iprim / prim;
+
+  rs->genpoly[0] = 1;
+  for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
+    rs->genpoly[i+1] = 1;
+
+    /* Multiply rs->genpoly[] by  @**(root + x) */
+    for (j = i; j > 0; j--){
+      if (rs->genpoly[j] != 0)
+	rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
+      else
+	rs->genpoly[j] = rs->genpoly[j-1];
+    }
+    /* rs->genpoly[0] can never be zero */
+    rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
+  }
+  /* convert rs->genpoly[] to index form for quicker encoding */
+  for (i = 0; i <= nroots; i++)
+    rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
+ done:;
+
+  return rs;
+}
+
+RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
+{
+	RS *rs;
+
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_lock(&rslist_mutex);
+#endif
+	for(rs = rslist; rs != NULL; rs = rs->next) {
+		if(rs->pad != pad) continue;
+		if(rs->nroots != nroots) continue;
+		if(rs->mm != symsize) continue;
+		if(rs->gfpoly != gfpoly) continue;
+		if(rs->fcr != fcr) continue;
+		if(rs->prim != prim) continue;
+
+		goto DONE;
+	}
+
+	rs = init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad);
+	if(rs == NULL) goto DONE;
+	rs->next = rslist;
+	rslist = rs;
+
+DONE:
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_unlock(&rslist_mutex);
+#endif
+	return rs;
+}
+
+
+void free_rs_char(RS *rs)
+{
+	free(rs->alpha_to);
+	free(rs->index_of);
+	free(rs->genpoly);
+	free(rs);
+}
+
+void free_rs_cache(void)
+{
+	RS *rs, *next;
+
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_lock(&rslist_mutex);
+#endif
+	rs = rslist;
+	while(rs != NULL) {
+		next = rs->next;
+		free_rs_char(rs);
+		rs = next;
+	}
+	rslist = NULL;
+#ifdef HAVE_LIBPTHREAD
+	pthread_mutex_unlock(&rslist_mutex);
+#endif
+}
+
+/* The guts of the Reed-Solomon encoder, meant to be #included
+ * into a function body with the following typedefs, macros and variables supplied
+ * according to the code parameters:
+
+ * data_t - a typedef for the data symbol
+ * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded
+ * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols
+ * NROOTS - the number of roots in the RS code generator polynomial,
+ *          which is the same as the number of parity symbols in a block.
+            Integer variable or literal.
+	    * 
+ * NN - the total number of symbols in a RS block. Integer variable or literal.
+ * PAD - the number of pad symbols in a block. Integer variable or literal.
+ * ALPHA_TO - The address of an array of NN elements to convert Galois field
+ *            elements in index (log) form to polynomial form. Read only.
+ * INDEX_OF - The address of an array of NN elements to convert Galois field
+ *            elements in polynomial form to index (log) form. Read only.
+ * MODNN - a function to reduce its argument modulo NN. May be inline or a macro.
+ * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form
+
+ * The memset() and memmove() functions are used. The appropriate header
+ * file declaring these functions (usually <string.h>) must be included by the calling
+ * program.
+
+ * Copyright 2004, Phil Karn, KA9Q
+ * May be used under the terms of the GNU Lesser General Public License (LGPL)
+ */
+
+#undef A0
+#define A0 (NN) /* Special reserved value encoding zero in index form */
+
+void encode_rs_char(RS *rs, const data_t *data, data_t *parity)
+{
+  int i, j;
+  data_t feedback;
+
+  memset(parity,0,NROOTS*sizeof(data_t));
+
+  for(i=0;i<NN-NROOTS-PAD;i++){
+    feedback = INDEX_OF[data[i] ^ parity[0]];
+    if(feedback != A0){      /* feedback term is non-zero */
+#ifdef UNNORMALIZED
+      /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
+       * always be for the polynomials constructed by init_rs()
+       */
+      feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
+#endif
+      for(j=1;j<NROOTS;j++)
+	parity[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
+    }
+    /* Shift */
+    memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
+    if(feedback != A0)
+      parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
+    else
+      parity[NROOTS-1] = 0;
+  }
+}

+ 41 - 0
QRCode/rscode.h

@@ -0,0 +1,41 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Reed solomon encoder. This code is taken from Phil Karn's libfec then
+ * editted and packed into a pair of .c and .h files.
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * (libfec is released under the GNU Lesser General Public License.)
+ *
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
+ *
+ * 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
+ */
+
+#ifndef __RSCODE_H__
+#define __RSCODE_H__
+
+/*
+ * General purpose RS codec, 8-bit symbols.
+ */
+
+typedef struct _RS RS;
+
+extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad);
+extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity);
+extern void free_rs_char(RS *rs);
+extern void free_rs_cache(void);
+
+#endif /* __RSCODE_H__ */

+ 326 - 0
QRCode/split.c

@@ -0,0 +1,326 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Input data splitter.
+ * Copyright (C) 2006-2013 Kentaro Fukuchi <[email protected]>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ *  or
+ * "Automatic identification and data capture techniques --
+ *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "qrencode.h"
+#include "qrinput.h"
+#include "qrspec.h"
+#include "split.h"
+
+#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
+#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
+
+#if !HAVE_STRDUP
+#undef strdup
+char *strdup(const char *s)
+{
+	size_t len = strlen(s) + 1;
+	void *new = malloc(len);
+	if(new == NULL) return NULL;
+	return (char *)memcpy(new, s, len);
+}
+#endif
+
+static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
+{
+	unsigned char c, d;
+	unsigned int word;
+
+	c = string[0];
+
+	if(c == '\0') return QR_MODE_NUL;
+	if(isdigit(c)) {
+		return QR_MODE_NUM;
+	} else if(isalnum(c)) {
+		return QR_MODE_AN;
+	} else if(hint == QR_MODE_KANJI) {
+		d = string[1];
+		if(d != '\0') {
+			word = ((unsigned int)c << 8) | d;
+			if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
+				return QR_MODE_KANJI;
+			}
+		}
+	}
+
+	return QR_MODE_8;
+}
+
+static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint);
+static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
+static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
+static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint);
+
+static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
+{
+	const char *p;
+	int ret;
+	int run;
+	int dif;
+	int ln;
+	QRencodeMode mode;
+
+	ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
+
+	p = string;
+	while(isdigit(*p)) {
+		p++;
+	}
+	run = p - string;
+	mode = Split_identifyMode(p, hint);
+	if(mode == QR_MODE_8) {
+		dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+			+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
+			- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
+		if(dif > 0) {
+			return Split_eat8(string, input, hint);
+		}
+	}
+	if(mode == QR_MODE_AN) {
+		dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+			+ QRinput_estimateBitsModeAn(1) /* + 4 + la */
+			- QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
+		if(dif > 0) {
+			return Split_eatAn(string, input, hint);
+		}
+	}
+
+	ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
+	if(ret < 0) return -1;
+
+	return run;
+}
+
+static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
+{
+	const char *p, *q;
+	int ret;
+	int run;
+	int dif;
+	int la, ln;
+
+	la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
+	ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
+
+	p = string;
+	while(isalnum(*p)) {
+		if(isdigit(*p)) {
+			q = p;
+			while(isdigit(*q)) {
+				q++;
+			}
+			dif = QRinput_estimateBitsModeAn(p - string) /* + 4 + la */
+				+ QRinput_estimateBitsModeNum(q - p) + 4 + ln
+				+ (isalnum(*q)?(4 + ln):0)
+				- QRinput_estimateBitsModeAn(q - string) /* - 4 - la */;
+			if(dif < 0) {
+				break;
+			} else {
+				p = q;
+			}
+		} else {
+			p++;
+		}
+	}
+
+	run = p - string;
+
+	if(*p && !isalnum(*p)) {
+		dif = QRinput_estimateBitsModeAn(run) + 4 + la
+			+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
+			- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
+		if(dif > 0) {
+			return Split_eat8(string, input, hint);
+		}
+	}
+
+	ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
+	if(ret < 0) return -1;
+
+	return run;
+}
+
+static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
+{
+	const char *p;
+	int ret;
+	int run;
+
+	p = string;
+	while(Split_identifyMode(p, hint) == QR_MODE_KANJI) {
+		p += 2;
+	}
+	run = p - string;
+	ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string);
+	if(ret < 0) return -1;
+
+	return run;
+}
+
+static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
+{
+	const char *p, *q;
+	QRencodeMode mode;
+	int ret;
+	int run;
+	int dif;
+	int la, ln, l8;
+	int swcost;
+
+	la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
+	ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
+	l8 = QRspec_lengthIndicator(QR_MODE_8, input->version);
+
+	p = string + 1;
+	while(*p != '\0') {
+		mode = Split_identifyMode(p, hint);
+		if(mode == QR_MODE_KANJI) {
+			break;
+		}
+		if(mode == QR_MODE_NUM) {
+			q = p;
+			while(isdigit(*q)) {
+				q++;
+			}
+			if(Split_identifyMode(q, hint) == QR_MODE_8) {
+				swcost = 4 + l8;
+			} else {
+				swcost = 0;
+			}
+			dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
+				+ QRinput_estimateBitsModeNum(q - p) + 4 + ln
+				+ swcost
+				- QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
+			if(dif < 0) {
+				break;
+			} else {
+				p = q;
+			}
+		} else if(mode == QR_MODE_AN) {
+			q = p;
+			while(isalnum(*q)) {
+				q++;
+			}
+			if(Split_identifyMode(q, hint) == QR_MODE_8) {
+				swcost = 4 + l8;
+			} else {
+				swcost = 0;
+			}
+			dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
+				+ QRinput_estimateBitsModeAn(q - p) + 4 + la
+				+ swcost
+				- QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
+			if(dif < 0) {
+				break;
+			} else {
+				p = q;
+			}
+		} else {
+			p++;
+		}
+	}
+
+	run = p - string;
+	ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string);
+	if(ret < 0) return -1;
+
+	return run;
+}
+
+static int Split_splitString(const char *string, QRinput *input,
+		QRencodeMode hint)
+{
+	int length;
+	QRencodeMode mode;
+
+	if(*string == '\0') return 0;
+
+	mode = Split_identifyMode(string, hint);
+	if(mode == QR_MODE_NUM) {
+		length = Split_eatNum(string, input, hint);
+	} else if(mode == QR_MODE_AN) {
+		length = Split_eatAn(string, input, hint);
+	} else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
+		length = Split_eatKanji(string, input, hint);
+	} else {
+		length = Split_eat8(string, input, hint);
+	}
+	if(length == 0) return 0;
+	if(length < 0) return -1;
+	return Split_splitString(&string[length], input, hint);
+}
+
+static char *dupAndToUpper(const char *str, QRencodeMode hint)
+{
+	char *newstr, *p;
+	QRencodeMode mode;
+
+	newstr = strdup(str);
+	if(newstr == NULL) return NULL;
+
+	p = newstr;
+	while(*p != '\0') {
+		mode = Split_identifyMode(p, hint);
+		if(mode == QR_MODE_KANJI) {
+			p += 2;
+		} else {
+			if (*p >= 'a' && *p <= 'z') {
+				*p = (char)((int)*p - 32);
+			}
+			p++;
+		}
+	}
+
+	return newstr;
+}
+
+int Split_splitStringToQRinput(const char *string, QRinput *input,
+		QRencodeMode hint, int casesensitive)
+{
+	char *newstr;
+	int ret;
+
+	if(string == NULL || *string == '\0') {
+		errno = EINVAL;
+		return -1;
+	}
+	if(!casesensitive) {
+		newstr = dupAndToUpper(string, hint);
+		if(newstr == NULL) return -1;
+		ret = Split_splitString(newstr, input, hint);
+		free(newstr);
+	} else {
+		ret = Split_splitString(string, input, hint);
+	}
+
+	return ret;
+}

+ 47 - 0
QRCode/split.h

@@ -0,0 +1,47 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Input data splitter.
+ * Copyright (C) 2006-2013 Kentaro Fukuchi <[email protected]>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ *  or
+ * "Automatic identification and data capture techniques -- 
+ *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * 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
+ */
+
+#ifndef __SPLIT_H__
+#define __SPLIT_H__
+
+#include "qrencode.h"
+
+/**
+ * Split the input string (null terminated) into QRinput.
+ * @param string input string
+ * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8.
+ * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS.
+ * @retval 0 success.
+ * @retval -1 an error occurred. errno is set to indicate the error. See
+ *               Exceptions for the details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ */
+extern int Split_splitStringToQRinput(const char *string, QRinput *input,
+		QRencodeMode hint, int casesensitive);
+
+#endif /* __SPLIT_H__ */