提交原始齿轮泵代码

This commit is contained in:
kite_lucs
2026-08-26 16:13:59 +08:00
commit afc8fcf2a4
1688 changed files with 316635 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
#-------------------------------------------------
#
# Project created by QtCreator 2013-04-25T18:27:50
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = 121
TEMPLATE = app
SOURCES +=\
bitstream.cpp \
mask.cpp \
qrenc.cpp \
qrencode.cpp \
qrinput.cpp \
qrspec.cpp \
rscode.cpp \
split.cpp \
mainwindow.cpp
HEADERS += \
bistream.h \
mask.h \
qrencode_inner.h \
qrinput.h \
qrspec.h \
rscode.h \
split.h \
mainwindow.h
unix:!macx: LIBS += -L$$PWD/../../../../../../../usr/local/lib/ -lqrencode
INCLUDEPATH += $$PWD/../../../../../../../usr/local/include
DEPENDPATH += $$PWD/../../../../../../../usr/local/include
unix:!macx: LIBS += -lpng12
FORMS += \
mainwindow.ui
+43
View File
@@ -0,0 +1,43 @@
#ifndef BISTREAM_H
#define BISTREAM_H
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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 {
char *data;
} BitStream;
extern BitStream *BitStream_new(void);
extern void BitStream_append(BitStream *bstream, BitStream *arg);
extern void BitStream_appendNum(BitStream *bstream, int bits, unsigned int num);
extern void BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data);
extern unsigned int BitStream_size(BitStream *bstream);
extern unsigned char *BitStream_toByte(BitStream *bstream);
extern void BitStream_free(BitStream *bstream);
#endif /* __BITSTREAM_H__ */
#endif // BISTREAM_H
+231
View File
@@ -0,0 +1,231 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 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 "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;
}
#ifdef WITH_TESTS
BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
{
BitStream *bstream;
if(size == 0) return BitStream_new();
bstream = (BitStream *)malloc(sizeof(BitStream));
if(bstream == NULL) return NULL;
bstream->data = (unsigned char *)malloc(size);
if(bstream->data == NULL) {
free(bstream);
return NULL;
}
bstream->length = size;
bstream->datasize = size;
memcpy(bstream->data, bits, size);
return bstream;
}
#endif
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, size_t bits, unsigned int num)
{
unsigned int mask;
size_t i;
unsigned char *p;
p = dest;
mask = 1U << (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, size_t size, unsigned char *data)
{
unsigned char mask;
size_t 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, size_t 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, size_t 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)
{
size_t i, j, size, bytes, oddbits;
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 = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[i] = v;
}
oddbits = size & 7;
if(oddbits > 0) {
v = 0;
for(j = 0; j < oddbits; j++) {
v = (unsigned char)(v << 1);
v |= *p;
p++;
}
data[bytes] = (unsigned char)(v << (8 - oddbits));
}
return data;
}
void BitStream_free(BitStream *bstream)
{
if(bstream != NULL) {
free(bstream->data);
free(bstream);
}
}
+180
View File
@@ -0,0 +1,180 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bistream.h"
BitStream *BitStream_new(void)
{
BitStream *bstream;
bstream = (BitStream *)malloc(sizeof(BitStream));
bstream->data = NULL;
return bstream;
}
static BitStream *BitStream_newFromNum(int bits, unsigned int num)
{
unsigned int mask;
int i;
char *p;
BitStream *bstream;
bstream = BitStream_new();
bstream->data = (char *)malloc(bits + 1);
p = bstream->data;
mask = 1 << (bits - 1);
for(i=0; i<bits; i++) {
if(num & mask) {
*p = '1';
} else {
*p = '0';
}
p++;
mask = mask >> 1;
}
*p = '\0';
return bstream;
}
static BitStream *BitStream_newFromBytes(int size, unsigned char *data)
{
unsigned char mask;
int i, j;
char *p;
BitStream *bstream;
bstream = BitStream_new();
bstream->data = (char *)malloc(size * 8 + 1);
p = bstream->data;
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;
}
}
*p = '\0';
return bstream;
}
void BitStream_append(BitStream *bstream, BitStream *arg)
{
int l1, l2;
char *_new;
if(arg == NULL || arg->data == NULL) {
return;
}
if(bstream->data == NULL) {
bstream->data = strdup(arg->data);
return;
}
l1 = strlen(bstream->data);
l2 = strlen(arg->data);
_new = (char *)malloc(l1 + l2 + 1);
strcpy(_new, bstream->data);
strcat(_new, arg->data);
free(bstream->data);
bstream->data = _new;
}
void BitStream_appendNum(BitStream *bstream, int bits, unsigned int num)
{
BitStream *b;
b = BitStream_newFromNum(bits, num);
BitStream_append(bstream, b);
BitStream_free(b);
}
void BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data)
{
BitStream *b;
b = BitStream_newFromBytes(size, data);
BitStream_append(bstream, b);
BitStream_free(b);
}
unsigned int BitStream_size(BitStream *bstream)
{
if(bstream->data == NULL) return 0;
return strlen(bstream->data);
}
unsigned char *BitStream_toByte(BitStream *bstream)
{
int i, j, size, bytes;
unsigned char *data, v;
char *p;
size = BitStream_size(bstream);
data = (unsigned char *)malloc((size + 7) / 8);
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 == '1';
p++;
}
data[i] = v;
}
if(size & 7) {
v = 0;
for(j=0; j<(size & 7); j++) {
v = v << 1;
v |= *p == '1';
p++;
}
data[bytes] = v;
}
return data;
}
void BitStream_free(BitStream *bstream)
{
if(bstream->data != NULL) {
free(bstream->data);
}
free(bstream);
}
+43
View File
@@ -0,0 +1,43 @@
/*
* qrencode - QR Code encoder
*
* Binary sequence class.
* Copyright (C) 2006-2017 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
*/
#ifndef BITSTREAM_H
#define BITSTREAM_H
typedef struct {
size_t length;
size_t datasize;
unsigned char *data;
} BitStream;
extern BitStream *BitStream_new(void);
#ifdef WITH_TESTS
extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits);
#endif
extern int BitStream_append(BitStream *bstream, BitStream *arg);
extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num);
extern int BitStream_appendBytes(BitStream *bstream, size_t 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 */
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>662</width>
<height>388</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
+11
View File
@@ -0,0 +1,11 @@
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
+1
View File
@@ -0,0 +1 @@
+25
View File
@@ -0,0 +1,25 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
+173
View File
@@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>565</width>
<height>435</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>330</x>
<y>350</y>
<width>99</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>encode</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>290</y>
<width>541</width>
<height>51</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>270</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Message</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox_size">
<property name="geometry">
<rect>
<x>450</x>
<y>240</y>
<width>85</width>
<height>27</height>
</rect>
</property>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="comboBox_level">
<property name="geometry">
<rect>
<x>310</x>
<y>240</y>
<width>85</width>
<height>27</height>
</rect>
</property>
<item>
<property name="text">
<string>L</string>
</property>
</item>
<item>
<property name="text">
<string>M</string>
</property>
</item>
<item>
<property name="text">
<string>H</string>
</property>
</item>
<item>
<property name="text">
<string>Q</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>370</x>
<y>240</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>230</x>
<y>250</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>level:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLabel" name="labQRImage">
<property name="geometry">
<rect>
<x>40</x>
<y>10</y>
<width>431</width>
<height>211</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>565</width>
<height>23</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
+357
View File
@@ -0,0 +1,357 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 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 <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mask.h"
STATIC_IN_RELEASE 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((size_t)(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((size_t)(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_IN_RELEASE 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_IN_RELEASE 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_IN_RELEASE 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_IN_RELEASE 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_IN_RELEASE 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((size_t)w2);
if(mask == NULL) return NULL;
bestMask = (unsigned char *)malloc((size_t)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, (size_t)w2);
}
}
free(mask);
return bestMask;
}
+257
View File
@@ -0,0 +1,257 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#include <stdlib.h>
#include <limits.h>
#include "qrencode.h"
#include "qrencode_inner.h"
#include "qrspec.h"
#include "mask.h"
/**
* 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;\
unsigned 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 += (*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)
}
typedef int MaskMaker(int, const unsigned char *, unsigned char *);
static MaskMaker *maskMakers[] = {
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
};
unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask)
{
unsigned char *masked;
masked = (unsigned char *)malloc(width * width);
maskMakers[mask](width, frame, masked);
return masked;
}
static int runLength[QRSPEC_WIDTH_MAX + 1];
//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(runLength[i-3] < 0 || runLength[i-3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
} else if(i+3 >= length || runLength[i+3] >= 4 * fact) {
demerit += N3;
//n3 += N3;
}
}
}
}
}
return demerit;
}
int Mask_evaluateSymbol(int width, unsigned char *frame)
{
int x, y;
unsigned char *p;
unsigned char b22, w22;
unsigned int i;
int head;
int demerit = 0;
p = frame;
i = 0;
for(y=0; y<width; y++) {
head = 0;
runLength[0] = 1;
for(x=0; x<width; x++) {
if(x > 0 && y > 0) {
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;
}
}
if(x == 0 && (p[0] & 1)) {
runLength[0] = -1;
head = 1;
runLength[head] = 1;
} else if(x > 0) {
if((p[0] ^ p[-1]) & 1) {
head++;
runLength[head] = 1;
} else {
runLength[head]++;
}
}
p++;
}
demerit += Mask_calcN1N3(head+1, runLength);
}
i = 0;
for(x=0; x<width; x++) {
head = 0;
runLength[0] = 1;
p = frame + x;
for(y=0; y<width; y++) {
if(y == 0 && (p[0] & 1)) {
runLength[0] = -1;
head = 1;
runLength[head] = 1;
} else if(y > 0) {
if((p[0] ^ p[-width]) & 1) {
head++;
runLength[head] = 1;
} else {
runLength[head]++;
}
}
p+=width;
}
demerit += Mask_calcN1N3(head+1, 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 bestMaskNum = 0;
int blacks;
int demerit;
bestMask = NULL;
for(i=0; i<8; i++) {
// n1 = n2 = n3 = n4 = 0;
demerit = 0;
mask = (unsigned char *)malloc(width * width);
blacks = maskMakers[i](width, frame, mask);
blacks += QRcode_writeFormatInformation(width, mask, i, level);
blacks = 100 * blacks / (width * width);
demerit = (abs(blacks - 50) / 5) * N4;
// n4 = demerit;
if(demerit > minDemerit) {
free(mask);
continue;
}
demerit += Mask_evaluateSymbol(width, mask);
// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
if(demerit < minDemerit) {
minDemerit = demerit;
bestMaskNum = i;
if(bestMask != NULL) {
free(bestMask);
}
bestMask = mask;
} else {
free(mask);
}
}
return bestMask;
}
+38
View File
@@ -0,0 +1,38 @@
/*
* qrencode - QR Code encoder
*
* Masking.
* Copyright (C) 2006-2017 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
*/
#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
View File
@@ -0,0 +1,177 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 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 <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "qrencode.h"
#include "mqrspec.h"
#include "mmask.h"
STATIC_IN_RELEASE 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((size_t)(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((size_t)(width * width));
if(masked == NULL) return NULL;
maskMakers[mask](width, frame, masked);
MMask_writeFormatInformation(version, width, masked, mask, level);
return masked;
}
STATIC_IN_RELEASE 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((size_t)(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((size_t)(width * width));
if(mask == NULL) break;
}
}
free(mask);
return bestMask;
}
+34
View File
@@ -0,0 +1,34 @@
/*
* qrencode - QR Code encoder
*
* Masking for Micro QR Code.
* Copyright (C) 2006-2017 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
*/
#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
View File
@@ -0,0 +1,232 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* 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((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(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);
}
+150
View File
@@ -0,0 +1,150 @@
/*
* qrencode - QR Code encoder
*
* Micro QR Code specification in convenient format.
* Copyright (C) 2006-2017 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
*/
#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 version of the symbol
* @param level error correction level
* @return maximum size (bits)
*/
extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction 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 version of the symbol
* @param level error correction 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 error correction level
* @return version number
*/
extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version version of the symbol
* @return width
*/
extern int MQRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version version of the symbol
* @return number of remainder bits
*/
extern int MQRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @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 encode mode
* @param version vesion of the symbol
* @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 vesion of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int MQRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param version version of the symbol
* @param level error correction 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.
* @param version version of the symbol
* @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 */
+216
View File
@@ -0,0 +1,216 @@
#include <stdio.h>
#include <stdlib.h>
#include <QImage>
#include <getopt.h>
#include <qrencode.h>
#include <qdebug.h>
#include "mainwindow.h"
#include <QApplication>
#include "ui_mainwindow.h"
char *intext = " ";
static int casesensitive = 0;
static int eightbit = 0;
static int kanji = 0;
static int version = 0;
static int Size = 3;
static int margin = 4;
static QRecLevel level = QR_ECLEVEL_L;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->textEdit->setText(tr("1234567893233695"));
}
MainWindow::~MainWindow()
{
delete ui;
}
enum {
O_HELP,
O_OUTPUT,
O_SIZE,
O_VERSION,
O_LEVEL,
O_MARGIN,
O_KANJI,
O_CASE,
O_8BIT,
};
static const struct option options[] = {
{"h", no_argument , NULL, O_HELP},
{"o", required_argument, NULL, O_OUTPUT},
{"l", required_argument, NULL, O_LEVEL},
{"s", required_argument, NULL, O_SIZE},
{"v", required_argument, NULL, O_VERSION},
{"m", required_argument, NULL, O_MARGIN},
{"k", no_argument , NULL, O_KANJI},
{"c", no_argument , NULL, O_CASE},
{"8", no_argument , NULL, O_8BIT},
{NULL, 0, NULL, 0}
};
static void usage(void)
{
qDebug()<<(
"qrencode version %s\n\n"
"Usage: qrencode [OPTION]... [STRING]\n"
"Encode input data in a QR Code and save as a PNG image.\n\n"
" -h display this message.\n"
" -o FILENAME write PNG image to FILENAME. If '-' is specified, the result\n"
" will be output to standard output.\n"
" -s NUMBER specify the size of dot (pixel). (default=3)\n"
" -l {LMQH} specify error collectin 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 margin. (default=4)\n"
" -k assume that the input text contains kanji (shift-jis).\n"
" -c encode alphabet characters in 8-bit mode. If your application\n"
" is case-sensitive, choose this.\n"
" -8 encode entire data in 8-bit mode. -c and -k will be ignored.\n"
" [STRING] input data. If it is not specified, data will be taken from\n"
" standard input.\n"
);
}
#define MAX_DATA_SIZE 7090 /* from the specification */
static char *readStdin(void)
{
char *buffer;
int ret;
buffer = (char *)malloc(MAX_DATA_SIZE);
ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
if(ret == 0) {
fprintf(stderr, "No input data.\n");
exit(1);
}
if(!feof(stdin)) {
fprintf(stderr, "Input data is too large.\n");
exit(1);
}
buffer[ret] = '\0';
return buffer;
}
static QRcode *encode(const char *intext)
{
QRencodeMode hint;
QRcode *code;
if(kanji) {
hint = QR_MODE_KANJI;
} else {
hint = QR_MODE_8;
}
if(eightbit) {
code = QRcode_encodeString8bit(intext, version, level);
} else {
code = QRcode_encodeString(intext, version, level, hint, casesensitive);
}
return code;
}
static void qrencode(const char *intext, const char *outfile)
{
FILE *fp;
QRcode *qrcode;
//png_structp png_ptr;
//png_infop info_ptr;
unsigned char *row, *p, *q;
int x, y, xx, yy, bit;
int realwidth;
qrcode = encode(intext);
if(qrcode == NULL) {
fprintf(stderr, "Failed to encode the input data.\n");
exit(1);
}
realwidth = (qrcode->width + margin * 2) * Size;
row = (unsigned char *)malloc(realwidth);
// top margin
memset(row, 0x0, realwidth );
qDebug()<<"1: "<< qrcode->width<<realwidth<<margin<<Size<<sizeof(intext);
// realwidth = (qrcode->width + margin * 2) * Size;
QImage QRImage(realwidth,qrcode->width*Size,QImage::Format_ARGB32 );
QImage *img;
img = &QRImage;
img->fill(0x00ffffff);
/* data */
p = qrcode->data;
int ypos=0;//margin * Size;
int xpos=0;
for(y=0; y<qrcode->width; y++) {
bit = 7;
bit = 7 - (margin * Size % 8);
xpos=margin * Size;
for(x=0; x<qrcode->width; x++) {
for(xx=0; xx<Size; xx++) {
if((*p & 1) << bit){
for(yy=0; yy<Size; yy++) {
img->setPixel(xpos,ypos+yy,0xff000000);
}
}
xpos++;
}
p++;
bit--;
if(bit < 0) {
//q++;
bit = 7;
}
}
ypos+=Size;
}
img->save("Myqr.bmp");
free(row);
QRcode_free(qrcode);
}
void MainWindow::on_pushButton_clicked()
{
QString in;
//usage();
in = ui->textEdit->toPlainText();
//intext = in.toLatin1().data();
intext = (char *)malloc(in.length()*2);
memset(intext,0,sizeof(intext));
//intext =in.unicode();
//memcpy(&intext[0], in.unicode (),2*in.length());
memcpy(intext,in.toLocal8Bit().data(),2*in.length());
qDebug()<<in<< intext;
Size = ui->comboBox_size->currentIndex()+3;
qrencode(intext,outfile);
QImage img("Myqr.bmp",0);
ui->labQRImage->setPixmap( QPixmap::fromImage(img,Qt::AutoColor));
}
int main(int argc, char **argv)
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
+924
View File
@@ -0,0 +1,924 @@
/*
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 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 <errno.h>
#include "qrencode.h"
#include "qrspec.h"
#include "mqrspec.h"
#include "bitstream.h"
#include "qrinput.h"
#include "rsecc.h"
#include "split.h"
#include "mask.h"
#include "mmask.h"
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc)
{
block->dataLength = dl;
block->data = data;
block->eccLength = el;
block->ecc = ecc;
RSECC_encode((size_t)dl, (size_t)el, data, ecc);
}
static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
{
int i;
RSblock *block;
unsigned char *dp, *ep;
int el, dl;
dl = QRspec_rsDataCodes1(spec);
el = QRspec_rsEccCodes1(spec);
block = blocks;
dp = data;
ep = ecc;
for(i = 0; i < QRspec_rsBlockNum1(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
if(QRspec_rsBlockNum2(spec) == 0) return 0;
dl = QRspec_rsDataCodes2(spec);
el = QRspec_rsEccCodes2(spec);
for(i = 0; i < QRspec_rsBlockNum2(spec); i++) {
RSblock_initBlock(block, dl, dp, el, ep);
dp += dl;
ep += el;
block++;
}
return 0;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw);
STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input)
{
QRRawCode *raw;
int spec[5], ret;
raw = (QRRawCode *)malloc(sizeof(QRRawCode));
if(raw == NULL) return NULL;
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
free(raw);
return NULL;
}
QRspec_getEccSpec(input->version, input->level, spec);
raw->version = input->version;
raw->b1 = QRspec_rsBlockNum1(spec);
raw->dataLength = QRspec_rsDataLength(spec);
raw->eccLength = QRspec_rsEccLength(spec);
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
free(raw->datacode);
free(raw);
return NULL;
}
raw->blocks = QRspec_rsBlockNum(spec);
raw->rsblock = (RSblock *)calloc((size_t)(raw->blocks), sizeof(RSblock));
if(raw->rsblock == NULL) {
QRraw_free(raw);
return NULL;
}
ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
if(ret < 0) {
QRraw_free(raw);
return NULL;
}
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw)
{
int col, row;
unsigned char ret;
if(raw->count < raw->dataLength) {
row = raw->count % raw->blocks;
col = raw->count / raw->blocks;
if(col >= raw->rsblock[0].dataLength) {
row += raw->b1;
}
ret = raw->rsblock[row].data[col];
} else if(raw->count < raw->dataLength + raw->eccLength) {
row = (raw->count - raw->dataLength) % raw->blocks;
col = (raw->count - raw->dataLength) / raw->blocks;
ret = raw->rsblock[row].ecc[col];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw)
{
if(raw != NULL) {
free(raw->datacode);
free(raw->ecccode);
free(raw->rsblock);
free(raw);
}
}
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw);
STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input)
{
MQRRawCode *raw;
raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
if(raw == NULL) return NULL;
raw->version = input->version;
raw->dataLength = MQRspec_getDataLength(input->version, input->level);
raw->eccLength = MQRspec_getECCLength(input->version, input->level);
raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
raw->datacode = QRinput_getByteStream(input);
if(raw->datacode == NULL) {
free(raw);
return NULL;
}
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
if(raw->ecccode == NULL) {
free(raw->datacode);
free(raw);
return NULL;
}
raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock));
if(raw->rsblock == NULL) {
MQRraw_free(raw);
return NULL;
}
RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode);
raw->count = 0;
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw)
{
unsigned char ret;
if(raw->count < raw->dataLength) {
ret = raw->datacode[raw->count];
} else if(raw->count < raw->dataLength + raw->eccLength) {
ret = raw->ecccode[raw->count - raw->dataLength];
} else {
return 0;
}
raw->count++;
return ret;
}
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw)
{
if(raw != NULL) {
free(raw->datacode);
free(raw->ecccode);
free(raw->rsblock);
free(raw);
}
}
/******************************************************************************
* Frame filling
*****************************************************************************/
typedef struct {
int width;
unsigned char *frame;
int x, y;
int dir;
int bit;
int mqr;
} FrameFiller;
static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr)
{
filler->width = width;
filler->frame = frame;
filler->x = width - 1;
filler->y = width - 1;
filler->dir = -1;
filler->bit = -1;
filler->mqr = mqr;
}
static unsigned char *FrameFiller_next(FrameFiller *filler)
{
unsigned char *p;
int x, y, w;
if(filler->bit == -1) {
filler->bit = 0;
return filler->frame + filler->y * filler->width + filler->x;
}
x = filler->x;
y = filler->y;
p = filler->frame;
w = filler->width;
if(filler->bit == 0) {
x--;
filler->bit++;
} else {
x++;
y += filler->dir;
filler->bit--;
}
if(filler->dir < 0) {
if(y < 0) {
y = 0;
x -= 2;
filler->dir = 1;
if(!filler->mqr && x == 6) {
x--;
y = 9;
}
}
} else if(y == w) {
y = w - 1;
x -= 2;
filler->dir = -1;
if(!filler->mqr && x == 6) {
x--;
y -= 8;
}
}
if(x < 0 || y < 0) return NULL;
filler->x = x;
filler->y = y;
if(p[y * w + x] & 0x80) {
// This tail recursion could be optimized.
return FrameFiller_next(filler);
}
return &p[y * w + x];
}
#ifdef WITH_TESTS
unsigned char *FrameFiller_test(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 0);
length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
+ QRspec_getRemainder(version);
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
free(frame);
return NULL;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
unsigned char *FrameFiller_testMQR(int version)
{
int width;
unsigned char *frame, *p;
int i, length;
FrameFiller filler;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) return NULL;
FrameFiller_set(&filler, width, frame, 1);
length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
+ MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
for(i = 0; i < length; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) {
fprintf(stderr, "Frame filler run over the frame!\n");
return frame;
}
*p = (unsigned char)(i & 0x7f) | 0x80;
}
return frame;
}
#endif
/******************************************************************************
* QR-code encoding
*****************************************************************************/
STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data)
{
QRcode *qrcode;
qrcode = (QRcode *)malloc(sizeof(QRcode));
if(qrcode == NULL) return NULL;
qrcode->version = version;
qrcode->width = width;
qrcode->data = data;
return qrcode;
}
void QRcode_free(QRcode *qrcode)
{
if(qrcode != NULL) {
free(qrcode->data);
free(qrcode);
}
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask)
{
int width, version;
QRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j;
QRcode *qrcode = NULL;
FrameFiller filler;
if(input->mqr) {
errno = EINVAL;
return NULL;
}
if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
errno = EINVAL;
return NULL;
}
if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_H)) {
errno = EINVAL;
return NULL;
}
raw = QRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
if(frame == NULL) {
QRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 0);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j = 0; j < 8; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
QRraw_free(raw);
raw = NULL;
/* remainder bits */
j = QRspec_getRemainder(version);
for(i = 0; i < j; i++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02;
}
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)malloc((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = Mask_mask(width, frame, input->level);
} else {
masked = Mask_makeMask(width, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
free(masked);
}
EXIT:
QRraw_free(raw);
free(frame);
return qrcode;
}
STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
{
int width, version;
MQRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
int i, j, length;
QRcode *qrcode = NULL;
FrameFiller filler;
if(!input->mqr) {
errno = EINVAL;
return NULL;
}
if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
errno = EINVAL;
return NULL;
}
if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_Q)) {
errno = EINVAL;
return NULL;
}
raw = MQRraw_new(input);
if(raw == NULL) return NULL;
version = raw->version;
width = MQRspec_getWidth(version);
frame = MQRspec_newFrame(version);
if(frame == NULL) {
MQRraw_free(raw);
return NULL;
}
FrameFiller_set(&filler, width, frame, 1);
/* interleaved data and ecc codes */
for(i = 0; i < raw->dataLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
if(raw->oddbits && i == raw->dataLength - 1) {
length = raw->oddbits;
} else {
length = 8;
}
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = ((bit & code) != 0);
bit = bit >> 1;
}
}
for(i = 0; i < raw->eccLength; i++) {
code = MQRraw_getCode(raw);
bit = 0x80;
length = 8;
for(j = 0; j < length; j++) {
p = FrameFiller_next(&filler);
if(p == NULL) goto EXIT;
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
MQRraw_free(raw);
raw = NULL;
/* masking */
if(mask == -2) { // just for debug purpose
masked = (unsigned char *)malloc((size_t)(width * width));
memcpy(masked, frame, (size_t)(width * width));
} else if(mask < 0) {
masked = MMask_mask(version, frame, input->level);
} else {
masked = MMask_makeMask(version, frame, mask, input->level);
}
if(masked == NULL) {
goto EXIT;
}
qrcode = QRcode_new(version, width, masked);
if(qrcode == NULL) {
free(masked);
}
EXIT:
MQRraw_free(raw);
free(frame);
return qrcode;
}
QRcode *QRcode_encodeInput(QRinput *input)
{
if(input->mqr) {
return QRcode_encodeMaskMQR(input, -1);
} else {
return QRcode_encodeMask(input, -1);
}
}
static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode *code;
int ret;
if(string == NULL) {
errno = EINVAL;
return NULL;
}
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
errno = EINVAL;
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
}
QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
int i;
if(version == 0) {
version = 1;
}
for(i = version; i <= MQRSPEC_VERSION_MAX ; i++) {
QRcode *code = QRcode_encodeStringReal(string, i, level, 1, hint, casesensitive);
if(code != NULL) return code;
}
return NULL;
}
static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
{
QRinput *input;
QRcode *code;
int ret;
if(data == NULL || length == 0) {
errno = EINVAL;
return NULL;
}
if(mqr) {
input = QRinput_newMQR(version, level);
} else {
input = QRinput_new2(version, level);
}
if(input == NULL) return NULL;
ret = QRinput_append(input, QR_MODE_8, length, data);
if(ret < 0) {
QRinput_free(input);
return NULL;
}
code = QRcode_encodeInput(input);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
{
return QRcode_encodeDataReal(data, size, version, level, 0);
}
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 0);
}
QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
{
int i;
if(version == 0) {
version = 1;
}
for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
QRcode *code = QRcode_encodeDataReal(data, size, i, level, 1);
if(code != NULL) return code;
}
return NULL;
}
QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
{
int i;
if(string == NULL) {
errno = EINVAL;
return NULL;
}
if(version == 0) {
version = 1;
}
for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
QRcode *code = QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), i, level, 1);
if(code != NULL) return code;
}
return NULL;
}
/******************************************************************************
* Structured QR-code encoding
*****************************************************************************/
static QRcode_List *QRcode_List_newEntry(void)
{
QRcode_List *entry;
entry = (QRcode_List *)malloc(sizeof(QRcode_List));
if(entry == NULL) return NULL;
entry->next = NULL;
entry->code = NULL;
return entry;
}
static void QRcode_List_freeEntry(QRcode_List *entry)
{
if(entry != NULL) {
QRcode_free(entry->code);
free(entry);
}
}
void QRcode_List_free(QRcode_List *qrlist)
{
QRcode_List *list = qrlist, *next;
while(list != NULL) {
next = list->next;
QRcode_List_freeEntry(list);
list = next;
}
}
int QRcode_List_size(QRcode_List *qrlist)
{
QRcode_List *list = qrlist;
int size = 0;
while(list != NULL) {
size++;
list = list->next;
}
return size;
}
QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
{
QRcode_List *head = NULL;
QRcode_List *tail = NULL;
QRcode_List *entry;
QRinput_InputList *list = s->head;
while(list != NULL) {
if(head == NULL) {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
head = entry;
tail = head;
} else {
entry = QRcode_List_newEntry();
if(entry == NULL) goto ABORT;
tail->next = entry;
tail = tail->next;
}
tail->code = QRcode_encodeInput(list->input);
if(tail->code == NULL) {
goto ABORT;
}
list = list->next;
}
return head;
ABORT:
QRcode_List_free(head);
return NULL;
}
static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
{
QRinput_Struct *s;
QRcode_List *codes;
s = QRinput_splitQRinputToStruct(input);
if(s == NULL) return NULL;
codes = QRcode_encodeInputStructured(s);
QRinput_Struct_free(s);
return codes;
}
static QRcode_List *QRcode_encodeDataStructuredReal(
int size, const unsigned char *data,
int version, QRecLevel level,
int eightbit, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode_List *codes;
int ret;
if(version <= 0) {
errno = EINVAL;
return NULL;
}
if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
errno = EINVAL;
return NULL;
}
input = QRinput_new2(version, level);
if(input == NULL) return NULL;
if(eightbit) {
ret = QRinput_append(input, QR_MODE_8, size, data);
} else {
ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
}
if(ret < 0) {
QRinput_free(input);
return NULL;
}
codes = QRcode_encodeInputToStructured(input);
QRinput_free(input);
return codes;
}
QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
}
QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataStructured((int)strlen(string), (unsigned char *)string, version, level);
}
QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
if(string == NULL) {
errno = EINVAL;
return NULL;
}
return QRcode_encodeDataStructuredReal((int)strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
}
/******************************************************************************
* System utilities
*****************************************************************************/
void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
{
if(major_version != NULL) {
*major_version = MAJOR_VERSION;
}
if(minor_version != NULL) {
*minor_version = MINOR_VERSION;
}
if(micro_version != NULL) {
*micro_version = MICRO_VERSION;
}
}
char *QRcode_APIVersionString(void)
{
return VERSION;
}
void QRcode_clearCache(void)
{
return;
}
+419
View File
@@ -0,0 +1,419 @@
/*
* qrencode - QR Code encoder
*
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qrencode.h"
#include "qrencode_inner.h"
#include "qrspec.h"
#include "bistream.h"
#include "qrinput.h"
#include "rscode.h"
#include "split.h"
#include "mask.h"
/******************************************************************************
* Raw code
*****************************************************************************/
static void RSblock_init(RSblock *block, int dl, unsigned char *data, int el)
{
RS *rs;
block->dataLength = dl;
block->data = data;
block->eccLength = el;
block->ecc = (unsigned char *)malloc(el);
rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
encode_rs_char(rs, data, block->ecc);
}
QRRawCode *QRraw_new(QRinput *input)
{
QRRawCode *raw;
int *spec;
int i;
RSblock *rsblock;
unsigned char *p;
p = QRinput_getByteStream(input);
if(p == NULL) {
return NULL;
}
raw = (QRRawCode *)malloc(sizeof(QRRawCode));
raw->datacode = p;
spec = QRspec_getEccSpec(input->version, input->level);
raw->version = input->version;
raw->blocks = QRspec_rsBlockNum(spec);
raw->rsblock = (RSblock *)malloc(sizeof(RSblock) * raw->blocks);
rsblock = raw->rsblock;
p = raw->datacode;
for(i=0; i<QRspec_rsBlockNum1(spec); i++) {
RSblock_init(rsblock, QRspec_rsDataCodes1(spec), p,
QRspec_rsEccCodes1(spec));
p += QRspec_rsDataCodes1(spec);
rsblock++;
}
for(i=0; i<QRspec_rsBlockNum2(spec); i++) {
RSblock_init(rsblock, QRspec_rsDataCodes2(spec), p,
QRspec_rsEccCodes2(spec));
p += QRspec_rsDataCodes2(spec);
rsblock++;
}
raw->b1 = QRspec_rsBlockNum1(spec);
raw->dataLength = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
raw->eccLength = QRspec_rsBlockNum(spec) * QRspec_rsEccCodes1(spec);
raw->count = 0;
free(spec);
return raw;
}
/**
* Return a code (byte).
* This function can be called iteratively.
* @param raw raw code.
* @return code
*/
unsigned char QRraw_getCode(QRRawCode *raw)
{
int col, row;
unsigned char ret;
if(raw->count < raw->dataLength) {
row = raw->count % raw->blocks;
col = raw->count / raw->blocks;
if(col >= raw->rsblock[row].dataLength) {
row += raw->b1;
}
ret = raw->rsblock[row].data[col];
} else if(raw->count < raw->dataLength + raw->eccLength) {
row = (raw->count - raw->dataLength) % raw->blocks;
col = (raw->count - raw->dataLength) / raw->blocks;
ret = raw->rsblock[row].ecc[col];
} else {
return 0;
}
raw->count++;
return ret;
}
void QRraw_free(QRRawCode *raw)
{
int i;
free(raw->datacode);
for(i=0; i<raw->blocks; i++) {
free(raw->rsblock[i].ecc);
}
free(raw->rsblock);
free(raw);
}
/******************************************************************************
* Frame filling
*****************************************************************************/
typedef struct {
int width;
unsigned char *frame;
int x, y;
int dir;
int bit;
} FrameFiller;
static FrameFiller *FrameFiller_new(int width, unsigned char *frame)
{
FrameFiller *filler;
filler = (FrameFiller *)malloc(sizeof(FrameFiller));
filler->width = width;
filler->frame = frame;
filler->x = width - 1;
filler->y = width - 1;
filler->dir = -1;
filler->bit = -1;
return filler;
}
static unsigned char *FrameFiller_next(FrameFiller *filler)
{
unsigned char *p;
int x, y, w;
if(filler->bit == -1) {
filler->bit = 0;
return filler->frame + filler->y * filler->width + filler->x;
}
x = filler->x;
y = filler->y;
p = filler->frame;
w = filler->width;
if(filler->bit == 0) {
x--;
filler->bit++;
} else {
x++;
y += filler->dir;
filler->bit--;
}
if(filler->dir < 0) {
if(y < 0) {
y = 0;
x -= 2;
filler->dir = 1;
if(x == 6) {
x--;
y = 9;
}
}
} else {
if(y == w) {
y = w - 1;
x -= 2;
filler->dir = -1;
if(x == 6) {
x--;
y -= 8;
}
}
}
if(x < 0 || y < 0) return NULL;
filler->x = x;
filler->y = y;
if(p[y * w + x] & 0x80) {
// This tail recursion could be optimized.
return FrameFiller_next(filler);
}
return &p[y * w + x];
}
unsigned char *FrameFiller_fillerTest(int version)
{
int width, length;
unsigned char *frame, *p;
FrameFiller *filler;
int i, j;
unsigned char cl = 1;
unsigned char ch = 0;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
filler = FrameFiller_new(width, frame);
length = QRspec_getDataLength(version, QR_ECLEVEL_L)
+ QRspec_getECCLength(version, QR_ECLEVEL_L);
for(i=0; i<length; i++) {
for(j=0; j<8; j++) {
p = FrameFiller_next(filler);
*p = ch | cl;
cl++;
if(cl == 9) {
cl = 1;
ch += 0x10;
}
}
}
length = QRspec_getRemainder(version);
for(i=0; i<length; i++) {
p = FrameFiller_next(filler);
*p = 0xa0;
}
p = FrameFiller_next(filler);
free(filler);
if(p != NULL) {
return NULL;
}
return frame;
}
/******************************************************************************
* Format information
*****************************************************************************/
int QRcode_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;
}
/******************************************************************************
* QR-code encoding
*****************************************************************************/
static QRcode *QRcode_new(int version, int width, unsigned char *data)
{
QRcode *qrcode;
qrcode = (QRcode *)malloc(sizeof(QRcode));
qrcode->version = version;
qrcode->width = width;
qrcode->data = data;
return qrcode;
}
void QRcode_free(QRcode *qrcode)
{
if(qrcode == NULL) return;
if(qrcode->data != NULL) {
free(qrcode->data);
}
free(qrcode);
}
QRcode *QRcode_encodeMask(QRinput *input, int version, QRecLevel level, int mask)
{
int width;
QRRawCode *raw;
unsigned char *frame, *masked, *p, code, bit;
FrameFiller *filler;
int i, j;
QRcode *qrcode;
QRinput_setVersion(input, version);
QRinput_setErrorCorrectionLevel(input, level);
raw = QRraw_new(input);
if(raw == NULL) {
return NULL;
}
version = raw->version;
width = QRspec_getWidth(version);
frame = QRspec_newFrame(version);
filler = FrameFiller_new(width, frame);
/* inteleaved data and ecc codes */
for(i=0; i<raw->dataLength + raw->eccLength; i++) {
code = QRraw_getCode(raw);
bit = 0x80;
for(j=0; j<8; j++) {
p = FrameFiller_next(filler);
*p = 0x02 | ((bit & code) != 0);
bit = bit >> 1;
}
}
QRraw_free(raw);
/* remainder bits */
j = QRspec_getRemainder(version);
for(i=0; i<j; i++) {
p = FrameFiller_next(filler);
*p = 0x02;
}
free(filler);
/* masking */
if(mask < 0) {
masked = Mask_mask(width, frame, level);
} else {
masked = Mask_makeMask(width, frame, mask);
QRcode_writeFormatInformation(width, masked, mask, QRinput_getErrorCorrectionLevel(input));
}
qrcode = QRcode_new(version, width, masked);
free(frame);
return qrcode;
}
QRcode *QRcode_encodeInput(QRinput *input, int version, QRecLevel level)
{
return QRcode_encodeMask(input, version, level, -1);
}
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
{
QRinput *input;
QRcode *code;
input = QRinput_new();
QRinput_append(input, QR_MODE_8, strlen(string), (unsigned char *)string);
code = QRcode_encodeInput(input, version, level);
QRinput_free(input);
return code;
}
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
{
QRinput *input;
QRcode *code;
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
return NULL;
}
input = QRinput_new();
Split_splitStringToQRinput(string, input, version, hint, casesensitive);
code = QRcode_encodeInput(input, version, level);
QRinput_free(input);
return code;
}
+576
View File
@@ -0,0 +1,576 @@
/**
* qrencode - QR Code encoder
*
* Copyright (C) 2006-2017 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
*/
/** \mainpage
* Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
* symbology.
*
* \section encoding Encoding
*
* There are two methods to encode data: <b>encoding a string/data</b> or
* <b>encoding a structured data</b>.
*
* \subsection encoding-string Encoding a string/data
* You can encode a string by calling QRcode_encodeString().
* The given string is parsed automatically and encoded. If you want to encode
* data that can be represented as a C string style (NUL terminated), you can
* simply use this way.
*
* If the input data contains Kanji (Shift-JIS) characters and you want to
* encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
* Otherwise, all of non-alphanumeric characters are encoded as 8-bit data.
* If you want to encode a whole string in 8-bit mode, you can use
* QRcode_encodeString8bit() instead.
*
* Please note that a C string can not contain NUL characters. If your data
* contains NUL, you must use QRcode_encodeData().
*
* \subsection encoding-input Encoding a structured data
* You can construct a structured input data manually. If the structure of the
* input data is known, you can use this method.
* At first, create a ::QRinput object by QRinput_new(). Then add input data
* to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
* to encode the QRinput data.
* You can reuse the QRinput object again to encode it in other symbols with
* different parameters.
*
* \section result Result
* The encoded symbol is generated as a ::QRcode object. It will contain its
* version number, the width of the symbol, and an array represents the symbol.
* See ::QRcode for the details. You can free the object by QRcode_free().
*
* Please note that the version of the result may be larger than specified.
* In such cases, the input data would be too large to be encoded in a
* symbol of the specified version.
*
* \section structured Structured append
* Libqrencode can generate "Structured-appended" symbols that enables to split
* a large data set into mulitple QR codes. A QR code reader concatenates
* multiple QR code symbols into a string.
* Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
* to generate structured-appended symbols. This functions returns an instance
* of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
* can retrieve each QR code in this way:
*
* \code
* QRcode_List *qrcodes;
* QRcode_List *entry;
* QRcode *qrcode;
*
* qrcodes = QRcode_encodeStringStructured(...);
* entry = qrcodes;
* while(entry != NULL) {
* qrcode = entry->code;
* // do something
* entry = entry->next;
* }
* QRcode_List_free(entry);
* \endcode
*
* Instead of using auto-parsing functions, you can construct your own
* structured input. At first, instantiate an object of ::QRinput_Struct
* by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
* and one QR code is generated for a ::QRinput.
* QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
* object. In order to generate structured-appended symbols, it is required to
* embed headers to each symbol. You can use
* QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
* headers to each symbol. You should call this function just once before
* encoding symbols.
*/
#ifndef QRENCODE_H
#define QRENCODE_H
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Encoding mode.
*/
typedef enum {
QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
QR_MODE_NUM = 0, ///< Numeric mode
QR_MODE_AN, ///< Alphabet-numeric mode
QR_MODE_8, ///< 8-bit data mode
QR_MODE_KANJI, ///< Kanji (shift-jis) mode
QR_MODE_STRUCTURE, ///< Internal use only
QR_MODE_ECI, ///< ECI mode
QR_MODE_FNC1FIRST, ///< FNC1, first position
QR_MODE_FNC1SECOND, ///< FNC1, second position
} QRencodeMode;
/**
* Level of error correction.
*/
typedef enum {
QR_ECLEVEL_L = 0, ///< lowest
QR_ECLEVEL_M,
QR_ECLEVEL_Q,
QR_ECLEVEL_H ///< highest
} QRecLevel;
/**
* Maximum version (size) of QR-code symbol.
*/
#define QRSPEC_VERSION_MAX 40
/**
* Maximum version (size) of QR-code symbol.
*/
#define MQRSPEC_VERSION_MAX 4
#define STATIC_IN_RELEASE static
#define MAJOR_VERSION 4
#define MINOR_VERSION 1
#define MICRO_VERSION 1
#define VERSION "4.1.1"
/******************************************************************************
* Input data (qrinput.c)
*****************************************************************************/
/**
* Singly linked list to contain input strings. An instance of this class
* contains its version and error correction level too. It is required to
* set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
* or use QRinput_new2() to instantiate an object.
*/
typedef struct _QRinput QRinput;
/**
* Instantiate an input data object. The version is set to 0 (auto-select)
* and the error correction level is set to QR_ECLEVEL_L.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput *QRinput_new(void);
/**
* Instantiate an input data object.
* @param version version number.
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_new2(int version, QRecLevel level);
/**
* Instantiate an input data object. Object's Micro QR Code flag is set.
* Unlike with full-sized QR Code, version number must be specified (>0).
* @param version version number (1--4).
* @param level Error correction level.
* @return an input object (initialized). On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw EINVAL invalid arguments.
*/
extern QRinput *QRinput_newMQR(int version, QRecLevel level);
/**
* Append data to an input object.
* The data is copied and appended to the input object.
* @param input input object.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
/**
* Append ECI header.
* @param input input object.
* @param ecinum ECI indicator number (0 - 999999)
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL input data is invalid.
*
*/
extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
/**
* Get current version.
* @param input input object.
* @return current version.
*/
extern int QRinput_getVersion(QRinput *input);
/**
* Set version of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersion(QRinput *input, int version);
/**
* Get current error correction level.
* @param input input object.
* @return Current error correcntion level.
*/
extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
/**
* Set error correction level of the QR code that is to be encoded.
* This function cannot be applied to Micro QR Code.
* @param input input object.
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
/**
* Set version and error correction level of the QR code at once.
* This function is recommened for Micro QR Code.
* @param input input object.
* @param version version number (0 = auto)
* @param level Error correction level.
* @retval 0 success.
* @retval -1 invalid argument.
*/
extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
/**
* Free the input object.
* All of data chunks in the input object are freed too.
* @param input input object.
*/
extern void QRinput_free(QRinput *input);
/**
* Validate the input data.
* @param mode encoding mode.
* @param size size of data (byte).
* @param data a pointer to the memory area of the input data.
* @retval 0 success.
* @retval -1 invalid arguments.
*/
extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
/**
* Set of QRinput for structured symbols.
*/
typedef struct _QRinput_Struct QRinput_Struct;
/**
* Instantiate a set of input data object.
* @return an instance of QRinput_Struct. On error, NULL is returned and errno
* is set to indicate the error.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_Struct_new(void);
/**
* Set parity of structured symbols.
* @param s structured input object.
* @param parity parity of s.
*/
extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
/**
* Append a QRinput object to the set. QRinput created by QRinput_newMQR()
* will be rejected.
* @warning never append the same QRinput object twice or more.
* @param s structured input object.
* @param input an input object.
* @retval >0 number of input objects in the structure.
* @retval -1 an error occurred. See Exceptions for the details.
* @throw ENOMEM unable to allocate memory.
* @throw EINVAL invalid arguments.
*/
extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
/**
* Free all of QRinput in the set.
* @param s a structured input object.
*/
extern void QRinput_Struct_free(QRinput_Struct *s);
/**
* Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
* insert structured-append headers. QRinput created by QRinput_newMQR() will
* be rejected.
* @param input input object. Version number and error correction level must be
* set.
* @return a set of input data. On error, NULL is returned, and errno is set
* to indicate the error. See Exceptions for the details.
* @throw ERANGE input data is too large.
* @throw EINVAL invalid input data.
* @throw ENOMEM unable to allocate memory.
*/
extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
/**
* Insert structured-append headers to the input structure. It calculates
* a parity and set it if the parity is not set yet.
* @param s input structure
* @retval 0 success.
* @retval -1 an error occurred and errno is set to indeicate the error.
* See Execptions for the details.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory.
*/
extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
/**
* Set FNC1-1st position flag.
*/
extern int QRinput_setFNC1First(QRinput *input);
/**
* Set FNC1-2nd position flag and application identifier.
*/
extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
/******************************************************************************
* QRcode output (qrencode.c)
*****************************************************************************/
/**
* QRcode class.
* Symbol data is represented as an array contains width*width uchars.
* Each uchar represents a module (dot). If the less significant bit of
* the uchar is 1, the corresponding module is black. The other bits are
* meaningless for usual applications, but here its specification is described.
*
* @verbatim
MSB 76543210 LSB
|||||||`- 1=black/0=white
||||||`-- 1=ecc/0=data code area
|||||`--- format information
||||`---- version information
|||`----- timing pattern
||`------ alignment pattern
|`------- finder pattern and separator
`-------- non-data modules (format, timing, etc.)
@endverbatim
*/
typedef struct {
int version; ///< version of the symbol
int width; ///< width of the symbol
unsigned char *data; ///< symbol data
} QRcode;
/**
* Singly-linked list of QRcode. Used to represent a structured symbols.
* A list is terminated with NULL.
*/
typedef struct _QRcode_List {
QRcode *code;
struct _QRcode_List *next;
} QRcode_List;
/**
* Create a symbol from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param input input data.
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and 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 QRcode *QRcode_encodeInput(QRinput *input);
/**
* Create a symbol from the string. The library automatically parses the input
* string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return an instance of QRcode class. The version of the result QRcode may
* be larger than the designated version. On error, NULL is returned,
* and 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.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeString().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Micro QR Code version of QRcode_encodeString8bit().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
/**
* Encode byte stream (may include '\0') in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input data.
* @param version version of the symbol. If 0, the library chooses the minimum
* version for the given input data.
* @param level error correction level.
* @throw EINVAL invalid input object.
* @throw ENOMEM unable to allocate memory for input objects.
* @throw ERANGE input data is too large.
*/
extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Micro QR Code version of QRcode_encodeData().
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Free the instance of QRcode class.
* @param qrcode an instance of QRcode class.
*/
extern void QRcode_free(QRcode *qrcode);
/**
* Create structured symbols from the input data.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param s input data, structured.
* @return a singly-linked list of QRcode.
*/
extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
/**
* Create structured symbols from the string. The library automatically parses
* the input string and encodes in a QR Code symbol.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param string input string. It must be NUL terminated.
* @param version version of the symbol.
* @param level error correction level.
* @param hint tell the library how Japanese Kanji characters should be
* encoded. If QR_MODE_KANJI is given, the library assumes that the
* given string contains Shift-JIS characters and encodes them in
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
* characters will be encoded as is. If you want to embed UTF-8
* string, choose this. Other mode will cause EINVAL error.
* @param casesensitive case-sensitive(1) or not(0).
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* 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 QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
/**
* Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
*/
extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
/**
* Create structured symbols from byte stream (may include '\0'). Wholde data
* are encoded in 8-bit mode.
* @warning This function is THREAD UNSAFE when pthread is disabled.
* @param size size of the input data.
* @param data input dat.
* @param version version of the symbol.
* @param level error correction level.
* @return a singly-linked list of QRcode. On error, NULL is returned, and
* 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 QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
/**
* Return the number of symbols included in a QRcode_List.
* @param qrlist a head entry of a QRcode_List.
* @return number of symbols in the list.
*/
extern int QRcode_List_size(QRcode_List *qrlist);
/**
* Free the QRcode_List.
* @param qrlist a head entry of a QRcode_List.
*/
extern void QRcode_List_free(QRcode_List *qrlist);
/******************************************************************************
* System utilities
*****************************************************************************/
/**
* Return a string that identifies the library version.
* @param major_version major version number
* @param minor_version minor version number
* @param micro_version micro version number
*/
extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
/**
* Return a string that identifies the library version.
* @return a string identifies the library version. The string is held by the
* library. Do NOT free it.
*/
extern char *QRcode_APIVersionString(void);
/**
* @deprecated
*/
#ifndef _MSC_VER
extern void QRcode_clearCache(void) __attribute__ ((deprecated));
#else
extern void QRcode_clearCache(void);
#endif
#if defined(__cplusplus)
}
#endif
#endif /* QRENCODE_H */
+1
View File
@@ -0,0 +1 @@
+88
View File
@@ -0,0 +1,88 @@
/**
* qrencode - QR Code encoder
*
* Header for test use
* Copyright (C) 2006-2017 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
*/
#ifndef QRENCODE_INNER_H
#define QRENCODE_INNER_H
/**
* This header file includes definitions for test use.
*/
/******************************************************************************
* Raw code
*****************************************************************************/
typedef struct {
int dataLength;
int eccLength;
unsigned char *data;
unsigned char *ecc;
} RSblock;
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
int b1;
int blocks;
RSblock *rsblock;
int count;
} QRRawCode;
extern QRRawCode *QRraw_new(QRinput *input);
extern unsigned char QRraw_getCode(QRRawCode *raw);
extern void QRraw_free(QRRawCode *raw);
/******************************************************************************
* Raw code for Micro QR Code
*****************************************************************************/
typedef struct {
int version;
int dataLength;
int eccLength;
unsigned char *datacode;
unsigned char *ecccode;
RSblock *rsblock;
int oddbits;
int count;
} MQRRawCode;
extern MQRRawCode *MQRraw_new(QRinput *input);
extern unsigned char MQRraw_getCode(MQRRawCode *raw);
extern void MQRraw_free(MQRRawCode *raw);
/******************************************************************************
* Frame filling
*****************************************************************************/
extern unsigned char *FrameFiller_test(int version);
extern unsigned char *FrameFiller_testMQR(int version);
/******************************************************************************
* QR-code encoding
*****************************************************************************/
extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
extern QRcode *QRcode_new(int version, int width, unsigned char *data);
#endif /* QRENCODE_INNER_H */
+1639
View File
File diff suppressed because it is too large Load Diff
+776
View File
@@ -0,0 +1,776 @@
/*
* qrencode - QR Code encoder
*
* Input data chunk class
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qrencode.h"
#include "qrspec.h"
#include "bistream.h"
#include "qrinput.h"
/******************************************************************************
* Entry of input data
*****************************************************************************/
static QRinput_List *QRinput_newEntry(QRencodeMode mode, int size, const unsigned char *data)
{
QRinput_List *entry;
if(QRinput_check(mode, size, data)) {
return NULL;
}
entry = (QRinput_List *)malloc(sizeof(QRinput_List));
entry->mode = mode;
entry->size = size;
entry->data = (unsigned char *)malloc(size);
memcpy(entry->data, data, size);
entry->bstream = NULL;
entry->next = NULL;
return entry;
}
static QRinput_List *QRinput_freeEntry(QRinput_List *entry)
{
QRinput_List *next;
next = entry->next;
free(entry->data);
if(entry->bstream) {
BitStream_free(entry->bstream);
}
free(entry);
return next;
}
/******************************************************************************
* Input Data
*****************************************************************************/
QRinput *QRinput_new(void)
{
QRinput *input;
input = (QRinput *)malloc(sizeof(QRinput));
input->head = NULL;
input->tail = NULL;
input->version = 0;
input->level = QR_ECLEVEL_L;
return input;
}
int QRinput_getVersion(QRinput *input)
{
return input->version;
}
void QRinput_setVersion(QRinput *input, int v)
{
input->version = v;
}
void QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level)
{
input->level = level;
}
QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input)
{
return input->level;
}
int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data)
{
QRinput_List *entry;
entry = QRinput_newEntry(mode, size, data);
if(entry == NULL) {
return -1;
}
if(input->tail == NULL) {
input->head = entry;
input->tail = entry;
} else {
input->tail->next = entry;
input->tail = entry;
}
return 0;
}
void QRinput_free(QRinput *input)
{
QRinput_List *list;
list = input->head;
while(list != NULL) {
list = QRinput_freeEntry(list);
}
free(input);
}
/******************************************************************************
* Numeric data
*****************************************************************************/
/**
* Check the input data.
* @param size
* @param data
* @return result
*/
static int QRinput_checkModeNum(int size, const char *data)
{
int i;
for(i=0; i<size; i++) {
if(data[i] < '0' || data[i] > '9')
return -1;
}
return 0;
}
/**
* Estimates the length of the encoded bit stream of numeric data.
* @param size
* @return number of bits
*/
int QRinput_estimateBitsModeNum(int size)
{
int w;
int bits;
w = size / 3;
bits = w * 10;
switch(size - w * 3) {
case 1:
bits += 4;
break;
case 2:
bits += 7;
break;
default:
break;
}
return bits;
}
/**
* Convert the number data to a bit stream.
* @param entry
*/
static void QRinput_encodeModeNum(QRinput_List *entry, int version)
{
int words;
int i;
unsigned int val;
words = entry->size / 3;
entry->bstream = BitStream_new();
val = 0x1;
BitStream_appendNum(entry->bstream, 4, val);
val = entry->size;
BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_NUM, version), val);
for(i=0; i<words; i++) {
val = (entry->data[i*3 ] - '0') * 100;
val += (entry->data[i*3+1] - '0') * 10;
val += (entry->data[i*3+2] - '0');
BitStream_appendNum(entry->bstream, 10, val);
}
if(entry->size - words * 3 == 1) {
val = entry->data[words*3] - '0';
BitStream_appendNum(entry->bstream, 4, val);
} else if(entry->size - words * 3 == 2) {
val = (entry->data[words*3 ] - '0') * 10;
val += (entry->data[words*3+1] - '0');
BitStream_appendNum(entry->bstream, 7, val);
}
}
/******************************************************************************
* Alphabet-numeric data
*****************************************************************************/
const signed char QRinput_anTable[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1
};
/**
* Check the input data.
* @param size
* @param data
* @return result
*/
static int QRinput_checkModeAn(int size, const char *data)
{
int i;
for(i=0; i<size; i++) {
if(QRinput_lookAnTable(data[i]) < 0)
return -1;
}
return 0;
}
/**
* Estimates the length of the encoded bit stream of alphabet-numeric data.
* @param size
* @return number of bits
*/
int QRinput_estimateBitsModeAn(int size)
{
int w;
int bits;
w = size / 2;
bits = w * 11;
if(size & 1) {
bits += 6;
}
return bits;
}
/**
* Convert the alphabet-numeric data to a bit stream.
* @param entry
*/
static void QRinput_encodeModeAn(QRinput_List *entry, int version)
{
int words;
int i;
unsigned int val;
words = entry->size / 2;
entry->bstream = BitStream_new();
val = 0x2;
BitStream_appendNum(entry->bstream, 4, val);
val = entry->size;
BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_AN, version), val);
for(i=0; i<words; i++) {
val = (unsigned int)QRinput_lookAnTable(entry->data[i*2 ]) * 45;
val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]);
BitStream_appendNum(entry->bstream, 11, val);
}
if(entry->size & 1) {
val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]);
BitStream_appendNum(entry->bstream, 6, val);
}
}
/******************************************************************************
* 8 bit data
*****************************************************************************/
/**
* Estimates the length of the encoded bit stream of 8 bit data.
* @param size
* @return number of bits
*/
int QRinput_estimateBitsMode8(int size)
{
return size * 8;
}
/**
* Convert the 8bits data to a bit stream.
* @param entry
*/
static void QRinput_encodeMode8(QRinput_List *entry, int version)
{
int i;
unsigned int val;
entry->bstream = BitStream_new();
val = 0x4;
BitStream_appendNum(entry->bstream, 4, val);
val = entry->size;
BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_8, version), val);
for(i=0; i<entry->size; i++) {
BitStream_appendNum(entry->bstream, 8, entry->data[i]);
}
}
/******************************************************************************
* Kanji data
*****************************************************************************/
/**
* Estimates the length of the encoded bit stream of kanji data.
* @param size
* @return number of bits
*/
int QRinput_estimateBitsModeKanji(int size)
{
return (size / 2) * 13;
}
/**
* Check the input data.
* @param size
* @param data
* @return result
*/
static int QRinput_checkModeKanji(int size, const unsigned char *data)
{
int i;
unsigned int val;
if(size & 1)
return -1;
for(i=0; i<size; i+=2) {
val = ((unsigned int)data[i] << 8) | data[i+1];
if(val < 0x8140 || (val > 0x9ffc && val < 0xe040) || val > 0xebbf) {
return -1;
}
}
return 0;
}
/**
* Convert the kanji data to a bit stream.
* @param entry
*/
static void QRinput_encodeModeKanji(QRinput_List *entry, int version)
{
int i;
unsigned int val, h;
entry->bstream = BitStream_new();
val = 0x8;
BitStream_appendNum(entry->bstream, 4, val);
val = entry->size / 2;
BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_KANJI, version), val);
for(i=0; i<entry->size; i+=2) {
val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1];
if(val <= 0x9ffc) {
val -= 0x8140;
} else {
val -= 0xc140;
}
h = (val >> 8) * 0xc0;
val = (val & 0xff) + h;
BitStream_appendNum(entry->bstream, 13, val);
}
}
/******************************************************************************
* Validation
*****************************************************************************/
/**
* Validate the input data
* @param mode
* @param size
* @param data
* @return result
*/
int QRinput_check(QRencodeMode mode, int size, const unsigned char *data)
{
switch(mode) {
case QR_MODE_NUM:
return QRinput_checkModeNum(size, (const char *)data);
break;
case QR_MODE_AN:
return QRinput_checkModeAn(size, (const char *)data);
break;
case QR_MODE_KANJI:
return QRinput_checkModeKanji(size, data);
break;
default:
break;
}
return 0;
}
QRencodeMode QRinput_identifyMode(const char *string)
{
unsigned char c, d;
unsigned int word;
c = string[0];
if((unsigned char)((signed char)c - '0') < 10) {
return QR_MODE_NUM;
} else if((QRinput_lookAnTable(c)) >= 0) {
return QR_MODE_AN;
} else {
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;
}
/******************************************************************************
* Estimation of the bit length
*****************************************************************************/
/**
* Estimates the length of the encoded bit stream on the current version.
* @param entry
* @param version version of the symbol
* @return number of bits
*/
static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version)
{
int bits = 0;
int l, m;
int num;
switch(entry->mode) {
case QR_MODE_NUM:
bits = QRinput_estimateBitsModeNum(entry->size);
break;
case QR_MODE_AN:
bits = QRinput_estimateBitsModeAn(entry->size);
break;
case QR_MODE_8:
bits = QRinput_estimateBitsMode8(entry->size);
break;
case QR_MODE_KANJI:
bits = QRinput_estimateBitsModeKanji(entry->size);
break;
}
l = QRspec_lengthIndicator(entry->mode, version);
m = 1 << l;
num = (bits + m - 1) / m;
bits += num * (4 + l); // mode indicator (4bits) + length indicator
return bits;
}
/**
* Estimates the length of the encoded bit stream of the data.
* @param input input data
* @param version version of the symbol
* @return number of bits
*/
int QRinput_estimateBitStreamSize(QRinput *input, int version)
{
QRinput_List *list;
int bits = 0;
list = input->head;
while(list != NULL) {
bits += QRinput_estimateBitStreamSizeOfEntry(list, version);
list = list->next;
}
return bits;
}
/**
* Estimates the required version number of the symbol.
* @param input input data
* @return required version number
*/
static int QRinput_estimateVersion(QRinput *input)
{
int bits;
int _new, prev;
_new = 0;
do {
prev = _new;
bits = QRinput_estimateBitStreamSize(input, prev);
_new = QRspec_getMinimumVersion((bits + 7) / 8, input->level);
if (_new == -1) {
return -1;
}
} while (_new > prev);
return _new;
}
/******************************************************************************
* Data conversion
*****************************************************************************/
/**
* Convert the input data in the data chunk to a bit stream.
* @param entry
* @return number of bits
*/
static int QRinput_encodeBitStream(QRinput_List *entry, int version)
{
int words;
QRinput_List *st1, *st2;
if(entry->bstream != NULL) {
BitStream_free(entry->bstream);
entry->bstream = NULL;
}
words = QRspec_maximumWords(entry->mode, version);
if(entry->size > words) {
st1 = QRinput_newEntry(entry->mode, words, entry->data);
st2 = QRinput_newEntry(entry->mode, entry->size - words, &entry->data[words]);
QRinput_encodeBitStream(st1, version);
QRinput_encodeBitStream(st2, version);
entry->bstream = BitStream_new();
BitStream_append(entry->bstream, st1->bstream);
BitStream_append(entry->bstream, st2->bstream);
QRinput_freeEntry(st1);
QRinput_freeEntry(st2);
} else {
switch(entry->mode) {
case QR_MODE_NUM:
QRinput_encodeModeNum(entry, version);
break;
case QR_MODE_AN:
QRinput_encodeModeAn(entry, version);
break;
case QR_MODE_8:
QRinput_encodeMode8(entry, version);
break;
case QR_MODE_KANJI:
QRinput_encodeModeKanji(entry, version);
break;
default:
break;
}
}
return BitStream_size(entry->bstream);
}
/**
* Convert the input data to a bit stream.
* @param input input data.
* @return length of the bit stream.
*/
static int QRinput_createBitStream(QRinput *input)
{
QRinput_List *list;
int bits = 0;
list = input->head;
while(list != NULL) {
bits += QRinput_encodeBitStream(list, input->version);
list = list->next;
}
return bits;
}
/**
* Convert the input data to a bit stream.
* When the version number is given and that is not sufficient, it is increased
* automatically.
* @param input input data.
* @return -1 if the input data was too large. Otherwise 0.
*/
static int QRinput_convertData(QRinput *input)
{
int bits;
int ver;
ver = QRinput_estimateVersion(input);
if(ver > QRinput_getVersion(input)) {
QRinput_setVersion(input, ver);
}
for(;;) {
bits = QRinput_createBitStream(input);
ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level);
if(ver < 0) {
return -1;
} else if(ver > QRinput_getVersion(input)) {
QRinput_setVersion(input, ver);
} else {
break;
}
}
return 0;
}
/**
* Create padding bits for the input data.
* @param input input data.
* @return padding bit stream.
*/
static BitStream *QRinput_createPaddingBit(QRinput *input)
{
int bits, maxbits, words, maxwords, i;
QRinput_List *list;
BitStream *bstream;
if(input->version <= 0)
return NULL;
maxwords = QRspec_getDataLength(input->version, input->level);
maxbits = maxwords * 8;
list = input->head;
bits = 0;
while(list != NULL) {
bits += BitStream_size(list->bstream);
list = list->next;
}
words = (bits + 7) / 8;
if(maxbits - bits < 5) {
if(maxbits == bits) {
return NULL;
} else {
bstream = BitStream_new();
BitStream_appendNum(bstream, maxbits - bits, 0);
return bstream;
}
}
bits += 4;
words = (bits + 7) / 8;
bstream = BitStream_new();
BitStream_appendNum(bstream, words * 8 - bits + 4, 0);
/* FIXME: It would be able to add padding bits by more efficient way. */
for(i=0; i<maxwords - words; i++) {
if(i & 1) {
BitStream_appendNum(bstream, 8, 0x11);
} else {
BitStream_appendNum(bstream, 8, 0xec);
}
}
return bstream;
}
/**
* Merge all bit streams in the input data.
* @param input input data.
* @return merged bit stream
*/
BitStream *QRinput_mergeBitStream(QRinput *input)
{
BitStream *bstream;
QRinput_List *list;
if(QRinput_convertData(input) < 0) {
return NULL;
}
bstream = BitStream_new();
list = input->head;
while(list != NULL) {
BitStream_append(bstream, list->bstream);
list = list->next;
}
return bstream;
}
/**
* Merge all bit streams in the input data and append padding bits
* @param input input data.
* @return padded merged bit stream
*/
BitStream *QRinput_getBitStream(QRinput *input)
{
BitStream *bstream;
BitStream *padding;
bstream = QRinput_mergeBitStream(input);
if(bstream == NULL) {
return NULL;
}
padding = QRinput_createPaddingBit(input);
if(padding != NULL) {
BitStream_append(bstream, padding);
BitStream_free(padding);
}
return bstream;
}
/**
* Pack all bit streams padding bits into a byte array.
* @param input input data.
* @return padded merged byte stream
*/
unsigned char *QRinput_getByteStream(QRinput *input)
{
BitStream *bstream;
unsigned char *array;
bstream = QRinput_getBitStream(input);
if(bstream == NULL) {
return NULL;
}
array = BitStream_toByte(bstream);
BitStream_free(bstream);
return array;
}
+124
View File
@@ -0,0 +1,124 @@
/*
* qrencode - QR Code encoder
*
* Input data chunk class
* Copyright (C) 2006-2017 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
*/
#ifndef QRINPUT_H
#define QRINPUT_H
#include "qrencode.h"
#include "bitstream.h"
int QRinput_isSplittableMode(QRencodeMode mode);
/******************************************************************************
* Entry of input data
*****************************************************************************/
typedef struct _QRinput_List QRinput_List;
struct _QRinput_List {
QRencodeMode mode;
int size; ///< Size of data chunk (byte).
unsigned char *data; ///< Data chunk.
BitStream *bstream;
QRinput_List *next;
};
/******************************************************************************
* Input Data
*****************************************************************************/
struct _QRinput {
int version;
QRecLevel level;
QRinput_List *head;
QRinput_List *tail;
int mqr;
int fnc1;
unsigned char appid;
};
/******************************************************************************
* Structured append input data
*****************************************************************************/
typedef struct _QRinput_InputList QRinput_InputList;
struct _QRinput_InputList {
QRinput *input;
QRinput_InputList *next;
};
struct _QRinput_Struct {
int size; ///< number of structured symbols
int parity;
QRinput_InputList *head;
QRinput_InputList *tail;
};
/**
* Pack all bit streams padding bits into a byte array.
* @param input input data.
* @return padded merged byte stream
*/
extern unsigned char *QRinput_getByteStream(QRinput *input);
extern int QRinput_estimateBitsModeNum(int size);
extern int QRinput_estimateBitsModeAn(int size);
extern int QRinput_estimateBitsMode8(int size);
extern int QRinput_estimateBitsModeKanji(int size);
extern QRinput *QRinput_dup(QRinput *input);
extern const signed char QRinput_anTable[128];
/**
* Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
* @param __c__ character
* @return value
*/
#define QRinput_lookAnTable(__c__) \
((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
/**
* Length of a standard mode indicator in bits.
*/
#define MODE_INDICATOR_SIZE 4
/**
* Length of a segment of structured-append header.
*/
#define STRUCTURE_HEADER_SIZE 20
/**
* Maximum number of symbols in a set of structured-appended symbols.
*/
#define MAX_STRUCTURED_SYMBOLS 16
#ifdef WITH_TESTS
extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_getBitStream(QRinput *input, BitStream *bstream);
extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
extern int QRinput_estimateVersion(QRinput *input);
extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity);
#endif
#endif /* QRINPUT_H */
+514
View File
@@ -0,0 +1,514 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* 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 "qrspec.h"
#include "qrinput.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; //< Edge length of the symbol
int words; //< Data capacity (bytes)
int remainder; //< Remainder bit (bits)
int ec[4]; //< Number of ECC code (bytes)
} QRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
{ 0, 0, 0, { 0, 0, 0, 0}},
{ 21, 26, 0, { 7, 10, 13, 17}}, // 1
{ 25, 44, 7, { 10, 16, 22, 28}},
{ 29, 70, 7, { 15, 26, 36, 44}},
{ 33, 100, 7, { 20, 36, 52, 64}},
{ 37, 134, 7, { 26, 48, 72, 88}}, // 5
{ 41, 172, 7, { 36, 64, 96, 112}},
{ 45, 196, 0, { 40, 72, 108, 130}},
{ 49, 242, 0, { 48, 88, 132, 156}},
{ 53, 292, 0, { 60, 110, 160, 192}},
{ 57, 346, 0, { 72, 130, 192, 224}}, //10
{ 61, 404, 0, { 80, 150, 224, 264}},
{ 65, 466, 0, { 96, 176, 260, 308}},
{ 69, 532, 0, { 104, 198, 288, 352}},
{ 73, 581, 3, { 120, 216, 320, 384}},
{ 77, 655, 3, { 132, 240, 360, 432}}, //15
{ 81, 733, 3, { 144, 280, 408, 480}},
{ 85, 815, 3, { 168, 308, 448, 532}},
{ 89, 901, 3, { 180, 338, 504, 588}},
{ 93, 991, 3, { 196, 364, 546, 650}},
{ 97, 1085, 3, { 224, 416, 600, 700}}, //20
{101, 1156, 4, { 224, 442, 644, 750}},
{105, 1258, 4, { 252, 476, 690, 816}},
{109, 1364, 4, { 270, 504, 750, 900}},
{113, 1474, 4, { 300, 560, 810, 960}},
{117, 1588, 4, { 312, 588, 870, 1050}}, //25
{121, 1706, 4, { 336, 644, 952, 1110}},
{125, 1828, 4, { 360, 700, 1020, 1200}},
{129, 1921, 3, { 390, 728, 1050, 1260}},
{133, 2051, 3, { 420, 784, 1140, 1350}},
{137, 2185, 3, { 450, 812, 1200, 1440}}, //30
{141, 2323, 3, { 480, 868, 1290, 1530}},
{145, 2465, 3, { 510, 924, 1350, 1620}},
{149, 2611, 3, { 540, 980, 1440, 1710}},
{153, 2761, 3, { 570, 1036, 1530, 1800}},
{157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
{161, 3034, 0, { 600, 1120, 1680, 1980}},
{165, 3196, 0, { 630, 1204, 1770, 2100}},
{169, 3362, 0, { 660, 1260, 1860, 2220}},
{173, 3532, 0, { 720, 1316, 1950, 2310}},
{177, 3706, 0, { 750, 1372, 2040, 2430}} //40
};
int QRspec_getDataLength(int version, QRecLevel level)
{
return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
}
int QRspec_getECCLength(int version, QRecLevel level)
{
return qrspecCapacity[version].ec[level];
}
int QRspec_getMinimumVersion(int size, QRecLevel level)
{
int i;
int words;
for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
if(words >= size) return i;
}
return QRSPEC_VERSION_MAX;
}
int QRspec_getWidth(int version)
{
return qrspecCapacity[version].width;
}
int QRspec_getRemainder(int version)
{
return qrspecCapacity[version].remainder;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
static const int lengthTableBits[4][3] = {
{10, 12, 14},
{ 9, 11, 13},
{ 8, 16, 16},
{ 8, 10, 12}
};
int QRspec_lengthIndicator(QRencodeMode mode, int version)
{
int l;
if(!QRinput_isSplittableMode(mode)) return 0;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
return lengthTableBits[mode][l];
}
int QRspec_maximumWords(QRencodeMode mode, int version)
{
int l;
int bits;
int words;
if(!QRinput_isSplittableMode(mode)) return 0;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
bits = lengthTableBits[mode][l];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Table of the error correction code (Reed-Solomon block)
* See Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
{{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
{{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
{{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
{{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
{{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
{{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
{{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
{{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
{{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
{{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
{{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
{{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
{{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
{{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
{{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
{{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
{{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
{{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
{{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
{{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
{{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
{{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
{{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
{{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
{{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
{{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
{{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
{{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
{{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
{{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
{{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
{{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
};
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5])
{
int b1, b2;
int data, ecc;
b1 = eccTable[version][level][0];
b2 = eccTable[version][level][1];
data = QRspec_getDataLength(version, level);
ecc = QRspec_getECCLength(version, level);
if(b2 == 0) {
spec[0] = b1;
spec[1] = data / b1;
spec[2] = ecc / b1;
spec[3] = spec[4] = 0;
} else {
spec[0] = b1;
spec[1] = data / (b1 + b2);
spec[2] = ecc / (b1 + b2);
spec[3] = b2;
spec[4] = spec[1] + 1;
}
}
/******************************************************************************
* Alignment pattern
*****************************************************************************/
/**
* Positions of alignment patterns.
* This array includes only the second and the third position of the alignment
* patterns. Rest of them can be calculated from the distance between them.
*
* See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
*/
static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
{ 0, 0},
{ 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
};
/**
* Put an alignment marker.
* @param frame
* @param width
* @param ox,oy center coordinate of the pattern
*/
static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
};
int x, y;
const unsigned char *s;
frame += (oy - 2) * width + ox - 2;
s = finder;
for(y = 0; y < 5; y++) {
for(x = 0; x < 5; x++) {
frame[x] = s[x];
}
frame += width;
s += 5;
}
}
static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width)
{
int d, w, x, y, cx, cy;
if(version < 2) return;
d = alignmentPattern[version][1] - alignmentPattern[version][0];
if(d < 0) {
w = 2;
} else {
w = (width - alignmentPattern[version][0]) / d + 2;
}
if(w * w - 3 == 1) {
x = alignmentPattern[version][0];
y = alignmentPattern[version][0];
QRspec_putAlignmentMarker(frame, width, x, y);
return;
}
cx = alignmentPattern[version][0];
for(x = 1; x < w - 1; x++) {
QRspec_putAlignmentMarker(frame, width, 6, cx);
QRspec_putAlignmentMarker(frame, width, cx, 6);
cx += d;
}
cy = alignmentPattern[version][0];
for(y = 0; y < w-1; y++) {
cx = alignmentPattern[version][0];
for(x = 0; x < w-1; x++) {
QRspec_putAlignmentMarker(frame, width, cx, cy);
cx += d;
}
cy += d;
}
}
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Version information pattern (BCH coded).
* See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
*/
static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
};
unsigned int QRspec_getVersionPattern(int version)
{
if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
return versionPattern[version - 7];
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_qrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
{0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
{0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
{0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
};
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
{
if(mask < 0 || mask > 7) return 0;
return formatInfo[level][mask];
}
/******************************************************************************
* 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 *QRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
unsigned int verinfo, v;
width = qrspecCapacity[version].width;
frame = (unsigned char *)malloc((size_t)(width * width));
if(frame == NULL) return NULL;
memset(frame, 0, (size_t)(width * width));
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
putFinderPattern(frame, width, width - 7, 0);
putFinderPattern(frame, width, 0, width - 7);
/* Separator */
p = frame;
q = frame + width * (width - 7);
for(y = 0; y < 7; y++) {
p[7] = 0xc0;
p[width - 8] = 0xc0;
q[7] = 0xc0;
p += width;
q += width;
}
memset(frame + width * 7, 0xc0, 8);
memset(frame + width * 8 - 8, 0xc0, 8);
memset(frame + width * (width - 8), 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8, 0x84, 9);
memset(frame + width * 9 - 8, 0x84, 8);
p = frame + 8;
for(y = 0; y < 8; y++) {
*p = 0x84;
p += width;
}
p = frame + width * (width - 7) + 8;
for(y = 0; y < 7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + width * 6 + 8;
q = frame + width * 8 + 6;
for(x = 1; x < width-15; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
/* Alignment pattern */
QRspec_putAlignmentPattern(version, frame, width);
/* Version information */
if(version >= 7) {
verinfo = QRspec_getVersionPattern(version);
p = frame + width * (width - 11);
v = verinfo;
for(x = 0; x < 6; x++) {
for(y = 0; y < 3; y++) {
p[width * y + x] = 0x88 | (v & 1);
v = v >> 1;
}
}
p = frame + width - 11;
v = verinfo;
for(y = 0; y < 6; y++) {
for(x = 0; x < 3; x++) {
p[x] = 0x88 | (v & 1);
v = v >> 1;
}
p += width;
}
}
/* and a little bit... */
frame[width * (width - 8) + 8] = 0x81;
return frame;
}
unsigned char *QRspec_newFrame(int version)
{
if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
return QRspec_createFrame(version);
}
+574
View File
@@ -0,0 +1,574 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qrspec.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
typedef struct {
int width; //< Edge length of the symbol
int words; //< Data capacity (bytes)
int remainder; //< Remainder bit (bits)
int ec[4]; //< Number of ECC code (bytes)
} QRspec_Capacity;
/**
* Table of the capacity of symbols
* See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
{ 0, 0, 0, { 0, 0, 0, 0}},
{ 21, 26, 0, { 7, 10, 13, 17}}, // 1
{ 25, 44, 7, { 10, 16, 22, 28}},
{ 29, 70, 7, { 15, 26, 36, 44}},
{ 33, 100, 7, { 20, 36, 52, 64}},
{ 37, 134, 7, { 26, 48, 72, 88}}, // 5
{ 41, 172, 7, { 36, 64, 96, 112}},
{ 45, 196, 0, { 40, 72, 108, 130}},
{ 49, 242, 0, { 48, 88, 132, 156}},
{ 53, 292, 0, { 60, 110, 160, 192}},
{ 57, 346, 0, { 72, 130, 192, 224}}, //10
{ 61, 404, 0, { 80, 150, 224, 264}},
{ 65, 466, 0, { 96, 176, 260, 308}},
{ 69, 532, 0, { 104, 198, 288, 352}},
{ 73, 581, 3, { 120, 216, 320, 384}},
{ 77, 655, 3, { 132, 240, 360, 432}}, //15
{ 81, 733, 3, { 144, 280, 408, 480}},
{ 85, 815, 3, { 168, 308, 448, 532}},
{ 89, 901, 3, { 180, 338, 504, 588}},
{ 93, 991, 3, { 196, 364, 546, 650}},
{ 97, 1085, 3, { 224, 416, 600, 700}}, //20
{101, 1156, 4, { 224, 442, 644, 750}},
{105, 1258, 4, { 252, 476, 690, 816}},
{109, 1364, 4, { 270, 504, 750, 900}},
{113, 1474, 4, { 300, 560, 810, 960}},
{117, 1588, 4, { 312, 588, 870, 1050}}, //25
{121, 1706, 4, { 336, 644, 952, 1110}},
{125, 1828, 4, { 360, 700, 1020, 1200}},
{129, 1921, 3, { 390, 728, 1050, 1260}},
{133, 2051, 3, { 420, 784, 1140, 1350}},
{137, 2185, 3, { 450, 812, 1200, 1440}}, //30
{141, 2323, 3, { 480, 868, 1290, 1530}},
{145, 2465, 3, { 510, 924, 1350, 1620}},
{149, 2611, 3, { 540, 980, 1440, 1710}},
{153, 2761, 3, { 570, 1036, 1530, 1800}},
{157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
{161, 3034, 0, { 600, 1120, 1680, 1980}},
{165, 3196, 0, { 630, 1204, 1770, 2100}},
{169, 3362, 0, { 660, 1260, 1860, 2220}},
{173, 3532, 0, { 720, 1316, 1950, 2310}},
{177, 3706, 0, { 750, 1372, 2040, 2430}} //40
};
int QRspec_getDataLength(int version, QRecLevel level)
{
return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
}
int QRspec_getECCLength(int version, QRecLevel level)
{
return qrspecCapacity[version].ec[level];
}
int QRspec_getMinimumVersion(int size, QRecLevel level)
{
int i;
int words;
for(i=1; i<= QRSPEC_VERSION_MAX; i++) {
words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
if(words >= size) return i;
}
return -1;
}
int QRspec_getWidth(int version)
{
return qrspecCapacity[version].width;
}
int QRspec_getRemainder(int version)
{
return qrspecCapacity[version].remainder;
}
/******************************************************************************
* Length indicator
*****************************************************************************/
static const int lengthTableBits[4][3] = {
{10, 12, 14},
{ 9, 11, 13},
{ 8, 16, 16},
{ 8, 10, 12}
};
int QRspec_lengthIndicator(QRencodeMode mode, int version)
{
int l;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
return lengthTableBits[mode][l];
}
int QRspec_maximumWords(QRencodeMode mode, int version)
{
int l;
int bits;
int words;
if(version <= 9) {
l = 0;
} else if(version <= 26) {
l = 1;
} else {
l = 2;
}
bits = lengthTableBits[mode][l];
words = (1 << bits) - 1;
if(mode == QR_MODE_KANJI) {
words *= 2; // the number of bytes is required
}
return words;
}
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Table of the error correction code (Reed-Solomon block)
* See Table 12-16 (pp.30-36), JIS X0510:2004.
*/
static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
{{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
{{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
{{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
{{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
{{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
{{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
{{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
{{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
{{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
{{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
{{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
{{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
{{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
{{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
{{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
{{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
{{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
{{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
{{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
{{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
{{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
{{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
{{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
{{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
{{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
{{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
{{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
{{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
{{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
{{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
{{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
{{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
};
int *QRspec_getEccSpec(int version, QRecLevel level)
{
int b1, b2;
int data, ecc;
int *array;
b1 = eccTable[version][level][0];
b2 = eccTable[version][level][1];
data = QRspec_getDataLength(version, level);
ecc = QRspec_getECCLength(version, level);
array = (int *)malloc(sizeof(int) * 6);
if(b2 == 0) {
array[0] = b1;
array[1] = data / b1;
array[2] = ecc / b1;
array[3] = array[4] = array[5] = 0;
} else {
array[0] = b1;
array[1] = data / (b1 + b2);
array[2] = ecc / (b1 + b2);
array[3] = b2;
array[4] = array[1] + 1;
array[5] = (ecc - (array[2] * b1)) / b2;
}
return array;
}
/******************************************************************************
* Alignment pattern
*****************************************************************************/
/**
* Positions of alignment patterns.
* This array includes only the second and the third position of the alignment
* patterns. Rest of them can be calculated from the distance between them.
*
* See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
*/
static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
{ 0, 0},
{ 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
};
QRspec_Alignment *QRspec_getAlignmentPattern(int version)
{
int width;
int d, w, x, y, cx, cy;
QRspec_Alignment *al;
int *p;
if(version < 2) return NULL;
al = (QRspec_Alignment *)malloc(sizeof(QRspec_Alignment));
width = qrspecCapacity[version].width;
d = alignmentPattern[version][1] - alignmentPattern[version][0];
if(d < 0) {
w = 2;
} else {
w = (width - alignmentPattern[version][0]) / d + 2;
}
al->n = w * w - 3;
al->pos = (int *)malloc(sizeof(int) * al->n * 2);
if(al->n == 1) {
al->pos[0] = alignmentPattern[version][0];
al->pos[1] = alignmentPattern[version][0];
return al;
}
#if 0
/* Just for debug purpose */
printf("%d ", version);
cx = alignmentPattern[version][0];
for(x=0; x<w-1; x++) {
printf(" %3d", cx);
cx += d;
}
printf("\n");
#endif
p = al->pos;
cx = alignmentPattern[version][0];
for(x=1; x<w - 1; x++) {
p[0] = 6;
p[1] = cx;
p[2] = cx;
p[3] = 6;
cx += d;
p += 4;
}
cy = alignmentPattern[version][0];
for(y=0; y<w-1; y++) {
cx = alignmentPattern[version][0];
for(x=0; x<w-1; x++) {
p[0] = cx;
p[1] = cy;
cx += d;
p += 2;
}
cy += d;
}
return al;
}
void QRspec_freeAlignment(QRspec_Alignment *al)
{
if(al != NULL) {
if(al->pos != NULL) {
free(al->pos);
}
free(al);
}
}
/******************************************************************************
* Version information pattern
*****************************************************************************/
/**
* Version information pattern (BCH coded).
* See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
*/
static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
};
unsigned int QRspec_getVersionPattern(int version)
{
if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
return versionPattern[version -7];
}
/******************************************************************************
* Format information
*****************************************************************************/
/* See calcFormatInfo in tests/test_qrspec.c */
static const unsigned int formatInfo[4][8] = {
{0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
{0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
{0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
{0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
};
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
{
if(mask < 0 || mask > 7) return 0;
return formatInfo[level][mask];
}
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Cache of initial frames.
*/
/* C99 says that static storage shall be initialized to a null pointer
* by compiler. */
static unsigned char *frames[QRSPEC_VERSION_MAX + 1];
/**
* 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;
}
}
/**
* Put an alignment pattern.
* @param frame
* @param width
* @param ox,oy center coordinate of the pattern
*/
static void putAlignmentPattern(unsigned char *frame, int width, int ox, int oy)
{
static const unsigned char finder[] = {
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
};
int x, y;
const unsigned char *s;
frame += (oy - 2) * width + ox - 2;
s = finder;
for(y=0; y<5; y++) {
for(x=0; x<5; x++) {
frame[x] = s[x];
}
frame += width;
s += 5;
}
}
static unsigned char *QRspec_createFrame(int version)
{
unsigned char *frame, *p, *q;
int width;
int x, y;
unsigned int verinfo, mask;
QRspec_Alignment *alignment;
width = qrspecCapacity[version].width;
frame = (unsigned char *)malloc(width * width);
memset(frame, 0, width * width);
/* Finder pattern */
putFinderPattern(frame, width, 0, 0);
putFinderPattern(frame, width, width - 7, 0);
putFinderPattern(frame, width, 0, width - 7);
/* Separator */
p = frame;
q = frame + width * (width - 7);
for(y=0; y<7; y++) {
p[7] = 0xc0;
p[width - 8] = 0xc0;
q[7] = 0xc0;
p += width;
q += width;
}
memset(frame + width * 7, 0xc0, 8);
memset(frame + width * 8 - 8, 0xc0, 8);
memset(frame + width * (width - 8), 0xc0, 8);
/* Mask format information area */
memset(frame + width * 8, 0x84, 9);
memset(frame + width * 9 - 8, 0x84, 8);
p = frame + 8;
for(y=0; y<8; y++) {
*p = 0x84;
p += width;
}
p = frame + width * (width - 7) + 8;
for(y=0; y<7; y++) {
*p = 0x84;
p += width;
}
/* Timing pattern */
p = frame + width * 6 + 8;
q = frame + width * 8 + 6;
for(x=1; x<width-15; x++) {
*p = 0x90 | (x & 1);
*q = 0x90 | (x & 1);
p++;
q += width;
}
/* Alignment pattern */
alignment = QRspec_getAlignmentPattern(version);
if(alignment != NULL) {
for(x=0; x<alignment->n; x++) {
putAlignmentPattern(frame, width,
alignment->pos[x*2], alignment->pos[x*2+1]);
}
QRspec_freeAlignment(alignment);
}
/* Version information */
if(version >= 7) {
verinfo = QRspec_getVersionPattern(version);
p = frame + width * (width - 11);
mask = 0x20000;
for(x=0; x<6; x++) {
for(y=0; y<3; y++) {
p[width * y + x] = 0x88 | ((mask & verinfo) != 0);
mask = mask >> 1;
}
}
p = frame + width - 11;
mask = 0x20000;
for(y=0; y<6; y++) {
for(x=0; x<3; x++) {
p[x] = 0x88 | ((mask & verinfo) != 0);
mask = mask >> 1;
}
p += width;
}
}
/* and a little bit... */
frame[width * (width - 8) + 8] = 0x81;
return frame;
}
unsigned char *QRspec_newFrame(int version)
{
unsigned char *frame;
int width;
if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
if(frames[version] == NULL) {
frames[version] = QRspec_createFrame(version);
}
width = qrspecCapacity[version].width;
frame = (unsigned char *)malloc(width * width);
memcpy(frame, frames[version], width * width);
return frame;
}
+174
View File
@@ -0,0 +1,174 @@
/*
* qrencode - QR Code encoder
*
* QR Code specification in convenient format.
* Copyright (C) 2006-2017 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
*/
#ifndef QRSPEC_H
#define QRSPEC_H
#include "qrencode.h"
/******************************************************************************
* Version and capacity
*****************************************************************************/
/**
* Maximum width of a symbol
*/
#define QRSPEC_WIDTH_MAX 177
/**
* Return maximum data code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return maximum size (bytes)
*/
extern int QRspec_getDataLength(int version, QRecLevel level);
/**
* Return maximum error correction code length (bytes) for the version.
* @param version version of the symbol
* @param level error correction level
* @return ECC size (bytes)
*/
extern int QRspec_getECCLength(int version, QRecLevel level);
/**
* Return a version number that satisfies the input code length.
* @param size input code length (byte)
* @param level error correction level
* @return version number
*/
extern int QRspec_getMinimumVersion(int size, QRecLevel level);
/**
* Return the width of the symbol for the version.
* @param version vesion of the symbol
* @return width of the symbol
*/
extern int QRspec_getWidth(int version);
/**
* Return the numer of remainder bits.
* @param version vesion of the symbol
* @return number of remainder bits
*/
extern int QRspec_getRemainder(int version);
/******************************************************************************
* Length indicator
*****************************************************************************/
/**
* Return the size of length indicator for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the size of the appropriate length indicator (bits).
*/
extern int QRspec_lengthIndicator(QRencodeMode mode, int version);
/**
* Return the maximum length for the mode and version.
* @param mode encode mode
* @param version vesion of the symbol
* @return the maximum length (bytes)
*/
extern int QRspec_maximumWords(QRencodeMode mode, int version);
/******************************************************************************
* Error correction code
*****************************************************************************/
/**
* Return an array of ECC specification.
* @param version version of the symbol
* @param level error correction level
* @param spec an array of ECC specification contains as following:
* {# of type1 blocks, # of data code, # of ecc code,
* # of type2 blocks, # of data code}
*/
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]);
#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3])
#define QRspec_rsBlockNum1(__spec__) (__spec__[0])
#define QRspec_rsDataCodes1(__spec__) (__spec__[1])
#define QRspec_rsEccCodes1(__spec__) (__spec__[2])
#define QRspec_rsBlockNum2(__spec__) (__spec__[3])
#define QRspec_rsDataCodes2(__spec__) (__spec__[4])
#define QRspec_rsEccCodes2(__spec__) (__spec__[2])
#define QRspec_rsDataLength(__spec__) \
((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \
(QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__)))
#define QRspec_rsEccLength(__spec__) \
(QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__))
/******************************************************************************
* 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 version of the symbol
* @return BCH encoded version information pattern
*/
extern unsigned int QRspec_getVersionPattern(int version);
/******************************************************************************
* Format information
*****************************************************************************/
/**
* Return BCH encoded format information pattern.
* @param mask mask number
* @param level error correction level
* @return BCH encoded format information pattern
*/
extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level);
/******************************************************************************
* Frame
*****************************************************************************/
/**
* Return a copy of initialized frame.
* @param version version of the symbol
* @return Array of unsigned char. You can free it by free().
*/
extern unsigned char *QRspec_newFrame(int version);
/******************************************************************************
* Mode indicator
*****************************************************************************/
/**
* Mode indicator. See Table 2 of JIS X0510:2004, pp.16.
*/
#define QRSPEC_MODEID_ECI 7
#define QRSPEC_MODEID_NUM 1
#define QRSPEC_MODEID_AN 2
#define QRSPEC_MODEID_8 4
#define QRSPEC_MODEID_KANJI 8
#define QRSPEC_MODEID_FNC1FIRST 5
#define QRSPEC_MODEID_FNC1SECOND 9
#define QRSPEC_MODEID_STRUCTURE 3
#define QRSPEC_MODEID_TERMINATOR 0
#endif /* QRSPEC_H */
+291
View File
@@ -0,0 +1,291 @@
/*
* 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,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#include <stdlib.h>
#include <string.h>
#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;
};
RS *rslist = NULL;
static inline 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 ((RS *)0)
int i, j, sr,root,iprim;
rs = NULL;
/* Check parameter ranges */
if(symsize < 0 || symsize > 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;
for(rs = rslist; rs != NULL; rs = rs->next) {
if(rs->mm != symsize) continue;
if(rs->gfpoly != gfpoly) continue;
if(rs->fcr != fcr) continue;
if(rs->prim != prim) continue;
if(rs->nroots != nroots) continue;
if(rs->pad != pad) continue;
return rs;
}
rs = init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad);
rs->next = rslist;
rslist = rs;
return rs;
}
void free_rs_char(RS *rs)
{
free(rs->alpha_to);
free(rs->index_of);
free(rs->genpoly);
free(rs);
}
/* 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;
}
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef RSCODE_H
#define RSCODE_H
/*
* 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,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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;
/* WARNING: Thread unsafe!!! */
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);
#endif /* __RSCODE_H__ */
#endif // RSCODE_H
+149
View File
@@ -0,0 +1,149 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon error correction code encoder specialized for QR code.
* This code is rewritten by Kentaro Fukuchi, referring to the FEC library
* developed by Phil Karn (KA9Q).
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* Copyright (C) 2014-2017 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 <stdlib.h>
#include <string.h>
#if HAVE_LIBPTHREAD
#include <pthread.h>
#endif
#include "rsecc.h"
#if HAVE_LIBPTHREAD
static pthread_mutex_t RSECC_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static int initialized = 0;
#define SYMBOL_SIZE (8)
#define symbols ((1U << SYMBOL_SIZE) - 1)
static const unsigned int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */
/* min/max codeword length of ECC, calculated from the specification. */
#define min_length (2)
#define max_length (30)
#define max_generatorSize (max_length)
static unsigned char alpha[symbols + 1];
static unsigned char aindex[symbols + 1];
static unsigned char generator[max_length - min_length + 1][max_generatorSize + 1];
static unsigned char generatorInitialized[max_length - min_length + 1];
static void RSECC_initLookupTable(void)
{
unsigned int i, b;
alpha[symbols] = 0;
aindex[0] = symbols;
b = 1;
for(i = 0; i < symbols; i++) {
alpha[i] = b;
aindex[b] = i;
b <<= 1;
if(b & (symbols + 1)) {
b ^= proot;
}
b &= symbols;
}
}
static void RSECC_init(void)
{
RSECC_initLookupTable();
memset(generatorInitialized, 0, (max_length - min_length + 1));
initialized = 1;
}
static void generator_init(size_t length)
{
size_t i, j;
int g[max_generatorSize + 1];
g[0] = 1;
for(i = 0; i < length; i++) {
g[i + 1] = 1;
/* Because g[0] never be zero, skipped some conditional checks. */
for(j = i; j > 0; j--) {
g[j] = g[j - 1] ^ alpha[(aindex[g[j]] + i) % symbols];
}
g[0] = alpha[(aindex[g[0]] + i) % symbols];
}
for(i = 0; i <= length; i++) {
generator[length - min_length][i] = aindex[g[i]];
}
generatorInitialized[length - min_length] = 1;
}
int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc)
{
size_t i, j;
unsigned char feedback;
unsigned char *gen;
#if HAVE_LIBPTHREAD
pthread_mutex_lock(&RSECC_mutex);
#endif
if(!initialized) {
RSECC_init();
}
#if HAVE_LIBPTHREAD
pthread_mutex_unlock(&RSECC_mutex);
#endif
if(ecc_length > max_length) return -1;
memset(ecc, 0, ecc_length);
#if HAVE_LIBPTHREAD
pthread_mutex_lock(&RSECC_mutex);
#endif
if(!generatorInitialized[ecc_length - min_length]) generator_init(ecc_length);
#if HAVE_LIBPTHREAD
pthread_mutex_unlock(&RSECC_mutex);
#endif
gen = generator[ecc_length - min_length];
for(i = 0; i < data_length; i++) {
feedback = aindex[data[i] ^ ecc[0]];
if(feedback != symbols) {
for(j = 1; j < ecc_length; j++) {
ecc[j] ^= alpha[(unsigned int)(feedback + gen[ecc_length - j]) % symbols];
}
}
memmove(&ecc[0], &ecc[1], ecc_length - 1);
if(feedback != symbols) {
ecc[ecc_length - 1] = alpha[(unsigned int)(feedback + gen[0]) % symbols];
} else {
ecc[ecc_length - 1] = 0;
}
}
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
/*
* qrencode - QR Code encoder
*
* Reed solomon error correction code encoder specialized for QR code.
* This code is rewritten by Kentaro Fukuchi, referring to the FEC library
* developed by Phil Karn (KA9Q).
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* Copyright (C) 2014-2017 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
*/
#ifndef RSECC_H
#define RSECC_H
extern int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc);
#endif /* RSECC_H */
+323
View File
@@ -0,0 +1,323 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* 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 *newstring = malloc(len);
if(newstring == NULL) return NULL;
return (char *)memcpy(newstring, s, len);
}
#endif
static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
{
unsigned char c, d;
unsigned int word;
c = (unsigned char)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 = (unsigned char)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_eatAn(const char *string, QRinput *input, QRencodeMode hint);
static int Split_eat8(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 = (int)(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((int)(p - string)) /* + 4 + la */
+ QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ (isalnum(*q)?(4 + ln):0)
- QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */;
if(dif < 0) {
break;
}
p = q;
} else {
p++;
}
}
run = (int)(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 = (int)(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((int)(p - string)) /* + 4 + l8 */
+ QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ swcost
- QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
if(dif < 0) {
break;
}
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((int)(p - string)) /* + 4 + l8 */
+ QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la
+ swcost
- QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
if(dif < 0) {
break;
}
p = q;
} else {
p++;
}
}
run = (int)(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;
while(*string != '\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) break;
if(length < 0) return -1;
string += length;
}
return 0;
}
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;
}
+213
View File
@@ -0,0 +1,213 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006,2007 Kentaro Fukuchi <fukuchi@megaui.net>
*
* 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
*/
#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)
static int Split_eatNum(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive);
static int Split_eatAn(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive);
static int Split_eat8(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive);
static int Split_eatKanji(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive);
static int Split_eatNum(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive)
{
const char *p;
int run;
int dif;
int ln;
ln = QRspec_lengthIndicator(QR_MODE_NUM, version);
p = string;
while(isdigit(*p)) {
p++;
}
run = p - string;
if(*p & 0x80) {
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, version, hint, casesensitive);
}
}
if(isalnum(*p) && !casesensitive) {
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, version, hint, casesensitive);
}
}
QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
return run;
}
static int Split_eatAn(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive)
{
const char *p, *q;
int run;
int dif;
int la, ln;
if(casesensitive) {
return Split_eat8(string, input, version, hint, casesensitive);
}
la = QRspec_lengthIndicator(QR_MODE_AN, version);
ln = QRspec_lengthIndicator(QR_MODE_NUM, 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
- QRinput_estimateBitsModeAn(q - string) /* - 4 - la */;
if(dif < 0) {
break;
} else {
p = q;
}
} else {
p++;
}
}
run = p - string;
if(*p & 0x80) {
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, version, hint, casesensitive);
}
}
QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
return run;
}
static int Split_eatKanji(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive)
{
const char *p;
p = string;
while(QRinput_identifyMode(p) == QR_MODE_KANJI) {
p += 2;
}
QRinput_append(input, QR_MODE_KANJI, p - string, (unsigned char *)string);
return p - string;
}
static int Split_eat8(const char *string, QRinput *input, int version, QRencodeMode hint, int casesensitive)
{
const char *p, *q;
QRencodeMode mode;
int dif;
int la, ln;
la = QRspec_lengthIndicator(QR_MODE_AN, version);
ln = QRspec_lengthIndicator(QR_MODE_NUM, version);
p = string;
while(*p != '\0') {
mode = QRinput_identifyMode(p);
if(hint == QR_MODE_KANJI && mode == QR_MODE_KANJI) {
break;
}
if(mode != QR_MODE_8 && mode != QR_MODE_KANJI) {
if(mode == QR_MODE_NUM) {
q = p;
while(isdigit(*q)) {
q++;
}
dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
+ QRinput_estimateBitsModeNum(q - p) + 4 + ln
- QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
if(dif < 0) {
break;
} else {
p = q;
}
} else if(!casesensitive) {
q = p;
while(isalnum(*q)) {
q++;
}
dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
+ QRinput_estimateBitsModeAn(q - p) + 4 + la
- QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
if(dif < 0) {
break;
} else {
p = q;
}
} else {
p++;
}
} else {
p++;
}
}
QRinput_append(input, QR_MODE_8, p - string, (unsigned char *)string);
return p - string;
}
void Split_splitStringToQRinput(const char *string, QRinput *input,
int version, QRencodeMode hint, int casesensitive)
{
int length;
QRencodeMode mode;
if(*string == '\0') return;
mode = QRinput_identifyMode(string);
if(mode == QR_MODE_NUM) {
length = Split_eatNum(string, input, version, hint, casesensitive);
} else if(mode == QR_MODE_AN && !casesensitive) {
length = Split_eatAn(string, input, version, hint, casesensitive);
} else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
length = Split_eatKanji(string, input, version, hint, casesensitive);
} else {
length = Split_eat8(string, input, version, hint, casesensitive);
}
if(length == 0) return;
Split_splitStringToQRinput(&string[length], input, hint, mode, casesensitive);
}
+47
View File
@@ -0,0 +1,47 @@
/*
* qrencode - QR Code encoder
*
* Input data splitter.
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
*
* 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 */