You've already forked lazarus-ccr
* QR code * MicroQR * Aztec * Aztec Rune * DataMatrix git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1758 8e941d3f-bd1b-0410-a28a-d453659cc2b4
3508 lines
87 KiB
ObjectPascal
3508 lines
87 KiB
ObjectPascal
unit uqr;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses sysutils,ureedsolomon,uhelper,zint,usjis;
|
|
|
|
function qr_code(symbol: PointerTo_zint_symbol; source: PBYTE; length: Integer): Integer;
|
|
function microqr(symbol: PointerTo_zint_symbol; source: PBYTE; length: Integer): Integer;
|
|
|
|
implementation
|
|
|
|
const LEVEL_L = 1;
|
|
const LEVEL_M = 2;
|
|
const LEVEL_Q = 3;
|
|
const LEVEL_H = 4;
|
|
|
|
const
|
|
qr_total_codewords: array [0..39] of integer = (
|
|
26, 44, 70, 100, 134, 172, 196, 242, 292, 346, 404, 466, 532, 581, 655, 733, 815,
|
|
901, 991, 1085, 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051,
|
|
2185, 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
|
|
);
|
|
|
|
qr_data_codewords_L: array [0..39] of integer = (
|
|
19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647,
|
|
721, 795, 861, 932, 1006, 1094, 1174, 1276, 1370, 1468, 1531, 1631,
|
|
1735, 1843, 1955, 2071, 2191, 2306, 2434, 2566, 2702, 2812, 2956
|
|
);
|
|
|
|
qr_data_codewords_M: array [0..39] of integer = (
|
|
16, 28, 44, 64, 86, 108, 124, 154, 182, 216, 254, 290, 334, 365, 415, 453, 507,
|
|
563, 627, 669, 714, 782, 860, 914, 1000, 1062, 1128, 1193, 1267,
|
|
1373, 1455, 1541, 1631, 1725, 1812, 1914, 1992, 2102, 2216, 2334
|
|
);
|
|
|
|
qr_data_codewords_Q: array [0..39] of integer = (
|
|
13, 22, 34, 48, 62, 76, 88, 110, 132, 154, 180, 206, 244, 261, 295, 325, 367,
|
|
397, 445, 485, 512, 568, 614, 664, 718, 754, 808, 871, 911,
|
|
985, 1033, 1115, 1171, 1231, 1286, 1354, 1426, 1502, 1582, 1666
|
|
);
|
|
|
|
qr_data_codewords_H: array [0..39] of integer = (
|
|
9, 16, 26, 36, 46, 60, 66, 86, 100, 122, 140, 158, 180, 197, 223, 253, 283,
|
|
313, 341, 385, 406, 442, 464, 514, 538, 596, 628, 661, 701,
|
|
745, 793, 845, 901, 961, 986, 1054, 1096, 1142, 1222, 1276
|
|
);
|
|
|
|
qr_blocks_L: array [0..39] of integer = (
|
|
1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12,
|
|
12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25
|
|
);
|
|
|
|
qr_blocks_M: array [0..39] of integer = (
|
|
1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20,
|
|
21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49
|
|
);
|
|
|
|
qr_blocks_Q: array [0..39] of integer = (
|
|
1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25,
|
|
27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68
|
|
);
|
|
|
|
qr_blocks_H: array [0..39] of integer = (
|
|
1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30,
|
|
32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81
|
|
);
|
|
|
|
qr_sizes: array [0..39] of integer = (
|
|
21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
|
|
101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177
|
|
);
|
|
|
|
|
|
qr_annex_c: array [0..31] of cardinal = (
|
|
$5412, $5125, $5e7c, $5b4b, $45f9, $40ce, $4f97, $4aa0, $77c4, $72f3, $7daa, $789d,
|
|
$662f, $6318, $6c41, $6976, $1689, $13be, $1ce7, $19d0, $0762, $0255, $0d0c, $083b,
|
|
$355f, $3068, $3f31, $3a06, $24b4, $2183, $2eda, $2bed
|
|
);
|
|
|
|
qr_annex_d: array [0..33] of integer = (
|
|
$07c94, $085bc, $09a99, $0a4d3, $0bbf6, $0c762, $0d847, $0e60d, $0f928, $10b78,
|
|
$1145d, $12a17, $13532, $149a6, $15683, $168c9, $177ec, $18ec4, $191e1, $1afab,
|
|
$1b08e, $1cc1a, $1d33f, $1ed75, $1f250, $209d5, $216f0, $228ba, $2379f, $24b0b,
|
|
$2542e, $26a64, $27541, $28c69
|
|
);
|
|
|
|
qr_annex_c1: array [0..31] of integer = (
|
|
$4445, $4172, $4e2b, $4b1c, $55ae, $5099, $5fc0, $5af7, $6793, $62a4, $6dfd, $68ca, $7678, $734f,
|
|
$7c16, $7921, $06de, $03e9, $0cb0, $0987, $1735, $1202, $1d5b, $186c, $2508, $203f, $2f66, $2a51, $34e3,
|
|
$31d4, $3e8d, $3bba
|
|
);
|
|
|
|
qr_align_loopsize: array [0..39] of integer = (
|
|
0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7
|
|
);
|
|
qr_table_e1: array [0..272] of integer = (
|
|
6, 18, 0, 0, 0, 0, 0,
|
|
6, 22, 0, 0, 0, 0, 0,
|
|
6, 26, 0, 0, 0, 0, 0,
|
|
6, 30, 0, 0, 0, 0, 0,
|
|
6, 34, 0, 0, 0, 0, 0,
|
|
6, 22, 38, 0, 0, 0, 0,
|
|
6, 24, 42, 0, 0, 0, 0,
|
|
6, 26, 46, 0, 0, 0, 0,
|
|
6, 28, 50, 0, 0, 0, 0,
|
|
6, 30, 54, 0, 0, 0, 0,
|
|
6, 32, 58, 0, 0, 0, 0,
|
|
6, 34, 62, 0, 0, 0, 0,
|
|
6, 26, 46, 66, 0, 0, 0,
|
|
6, 26, 48, 70, 0, 0, 0,
|
|
6, 26, 50, 74, 0, 0, 0,
|
|
6, 30, 54, 78, 0, 0, 0,
|
|
6, 30, 56, 82, 0, 0, 0,
|
|
6, 30, 58, 86, 0, 0, 0,
|
|
6, 34, 62, 90, 0, 0, 0,
|
|
6, 28, 50, 72, 94, 0, 0,
|
|
6, 26, 50, 74, 98, 0, 0,
|
|
6, 30, 54, 78, 102, 0, 0,
|
|
6, 28, 54, 80, 106, 0, 0,
|
|
6, 32, 58, 84, 110, 0, 0,
|
|
6, 30, 58, 86, 114, 0, 0,
|
|
6, 34, 62, 90, 118, 0, 0,
|
|
6, 26, 50, 74, 98, 122, 0,
|
|
6, 30, 54, 78, 102, 126, 0,
|
|
6, 26, 52, 78, 104, 130, 0,
|
|
6, 30, 56, 82, 108, 134, 0,
|
|
6, 34, 60, 86, 112, 138, 0,
|
|
6, 30, 58, 86, 114, 142, 0,
|
|
6, 34, 62, 90, 118, 146, 0,
|
|
6, 30, 54, 78, 102, 126, 150,
|
|
6, 24, 50, 76, 102, 128, 154,
|
|
6, 28, 54, 80, 106, 132, 158,
|
|
6, 32, 58, 84, 110, 136, 162,
|
|
6, 26, 54, 82, 110, 138, 166,
|
|
6, 30, 58, 86, 114, 142, 170
|
|
);
|
|
|
|
micro_qr_sizes: array [0..3] of integer = (
|
|
11, 13, 15, 17
|
|
);
|
|
|
|
(*
|
|
bullseye_compressed: array [0..1115] of Cardinal = (
|
|
0,0,0,0,0,255,248,0,0,0,0,0,
|
|
0,0,0,0,31,255,255,192,0,0,0,0,
|
|
0,0,0,1,255,255,255,252,0,0,0,0,
|
|
0,0,0,7,255,255,255,255,0,0,0,0,
|
|
0,0,0,31,255,255,255,255,192,0,0,0,
|
|
0,0,0,127,255,255,255,255,240,0,0,0,
|
|
0,0,1,255,255,255,255,255,252,0,0,0,
|
|
0,0,7,255,255,255,255,255,255,0,0,0,
|
|
0,0,15,255,255,0,7,255,255,128,0,0,
|
|
0,0,63,255,240,0,0,127,255,224,0,0,
|
|
0,0,127,255,128,0,0,15,255,240,0,0,
|
|
0,0,255,252,0,0,0,1,255,248,0,0,
|
|
0,1,255,240,0,0,0,0,127,252,0,0,
|
|
0,3,255,224,0,0,0,0,63,254,0,0,
|
|
0,7,255,128,0,0,0,0,15,255,0,0,
|
|
0,15,255,0,0,0,0,0,7,255,128,0,
|
|
0,31,252,0,0,127,240,0,1,255,192,0,
|
|
0,63,248,0,7,255,255,0,0,255,224,0,
|
|
0,127,240,0,63,255,255,224,0,127,240,0,
|
|
0,127,224,0,255,255,255,248,0,63,240,0,
|
|
0,255,192,1,255,255,255,252,0,31,248,0,
|
|
1,255,128,7,255,255,255,255,0,15,252,0,
|
|
1,255,0,15,255,255,255,255,128,7,252,0,
|
|
3,255,0,63,255,255,255,255,224,7,254,0,
|
|
3,254,0,127,255,192,31,255,240,3,254,0,
|
|
7,252,0,255,252,0,1,255,248,1,255,0,
|
|
7,252,1,255,240,0,0,127,252,1,255,0,
|
|
15,248,1,255,192,0,0,31,252,0,255,128,
|
|
15,240,3,255,128,0,0,15,254,0,127,128,
|
|
31,240,7,255,0,0,0,7,255,0,127,192,
|
|
31,224,7,254,0,0,0,3,255,0,63,192,
|
|
63,224,15,252,0,0,0,1,255,128,63,224,
|
|
63,224,31,248,0,63,192,0,255,192,63,224,
|
|
63,192,31,240,0,255,240,0,127,192,31,224,
|
|
63,192,63,224,3,255,252,0,63,224,31,224,
|
|
127,192,63,224,7,255,254,0,63,224,31,240,
|
|
127,128,63,192,15,255,255,0,31,224,15,240,
|
|
127,128,127,192,31,255,255,128,31,240,15,240,
|
|
127,128,127,128,63,255,255,192,15,240,15,240,
|
|
127,128,127,128,63,255,255,192,15,240,15,240,
|
|
255,0,127,128,127,240,255,224,15,240,7,240,
|
|
255,0,255,128,127,192,63,224,15,248,7,240,
|
|
255,0,255,0,255,128,31,240,7,248,7,240,
|
|
255,0,255,0,255,128,31,240,7,248,7,240,
|
|
255,0,255,0,255,0,15,240,7,248,7,240,
|
|
255,0,255,0,255,0,15,240,7,248,7,240,
|
|
255,0,255,0,255,0,15,240,7,248,7,240,
|
|
255,0,255,0,255,0,15,240,7,248,7,240,
|
|
255,0,255,0,255,128,31,240,7,248,7,240,
|
|
255,0,255,0,255,128,31,240,7,248,7,240,
|
|
255,0,255,0,127,192,63,224,7,248,7,240,
|
|
255,0,255,128,127,240,255,224,15,248,7,240,
|
|
255,0,127,128,63,255,255,192,15,240,7,240,
|
|
127,128,127,128,63,255,255,192,15,240,15,240,
|
|
127,128,127,128,31,255,255,128,15,240,15,240,
|
|
127,128,127,192,15,255,255,0,31,240,15,240,
|
|
127,128,63,192,7,255,254,0,31,224,15,240,
|
|
127,192,63,224,3,255,252,0,63,224,31,240,
|
|
63,192,63,224,0,255,240,0,63,224,31,224,
|
|
63,192,31,240,0,63,192,0,127,192,31,224,
|
|
63,224,31,248,0,0,0,0,255,192,63,224,
|
|
63,224,15,252,0,0,0,1,255,128,63,224,
|
|
31,224,7,254,0,0,0,3,255,0,63,192,
|
|
31,240,7,255,0,0,0,7,255,0,127,192,
|
|
15,240,3,255,128,0,0,15,254,0,127,128,
|
|
15,248,1,255,192,0,0,31,252,0,255,128,
|
|
7,252,1,255,240,0,0,127,252,1,255,0,
|
|
7,252,0,255,252,0,1,255,248,1,255,0,
|
|
3,254,0,127,255,192,31,255,240,3,254,0,
|
|
3,255,0,63,255,255,255,255,224,7,254,0,
|
|
1,255,0,15,255,255,255,255,128,7,252,0,
|
|
1,255,128,7,255,255,255,255,0,15,252,0,
|
|
0,255,192,1,255,255,255,252,0,31,248,0,
|
|
0,127,224,0,255,255,255,248,0,63,240,0,
|
|
0,127,240,0,63,255,255,224,0,127,240,0,
|
|
0,63,248,0,7,255,255,0,0,255,224,0,
|
|
0,31,252,0,0,127,240,0,1,255,192,0,
|
|
0,15,255,0,0,0,0,0,7,255,128,0,
|
|
0,7,255,128,0,0,0,0,15,255,0,0,
|
|
0,3,255,224,0,0,0,0,63,254,0,0,
|
|
0,1,255,240,0,0,0,0,127,252,0,0,
|
|
0,0,255,252,0,0,0,1,255,248,0,0,
|
|
0,0,127,255,128,0,0,15,255,240,0,0,
|
|
0,0,63,255,240,0,0,127,255,224,0,0,
|
|
0,0,15,255,255,0,7,255,255,128,0,0,
|
|
0,0,7,255,255,255,255,255,255,0,0,0,
|
|
0,0,1,255,255,255,255,255,252,0,0,0,
|
|
0,0,0,127,255,255,255,255,240,0,0,0,
|
|
0,0,0,31,255,255,255,255,192,0,0,0,
|
|
0,0,0,7,255,255,255,255,0,0,0,0,
|
|
0,0,0,1,255,255,255,252,0,0,0,0,
|
|
0,0,0,0,31,255,255,192,0,0,0,0,
|
|
0,0,0,0,0,255,248,0,0,0,0,0
|
|
);
|
|
|
|
hexagon: array [0..119] of integer = (
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
|
|
0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
|
|
0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
|
|
0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
|
|
0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
);
|
|
|
|
const SSET='0123456789ABCDEF';
|
|
*)
|
|
|
|
function in_alpha(glyph: Integer): Integer;
|
|
var
|
|
retval: Integer = 0;
|
|
cglyph: Char;
|
|
begin
|
|
{INITCODE} retval := 0;
|
|
{INITCODE} cglyph := Char (glyph);
|
|
if IsTrue(((cglyph >= '0')) and ((cglyph <= '9'))) then
|
|
begin
|
|
retval := 1;
|
|
end;
|
|
if IsTrue(((cglyph >= 'A')) and ((cglyph <= 'Z'))) then
|
|
begin
|
|
retval := 1;
|
|
end;
|
|
case cglyph of
|
|
' ',
|
|
'$',
|
|
'%',
|
|
'*',
|
|
'+',
|
|
'-',
|
|
'.',
|
|
'/',
|
|
':': retval := 1;
|
|
end;
|
|
exit (retval);
|
|
end;
|
|
|
|
procedure define_mode(mode: PChar; jisdata: PInteger; length: Integer; gs1: Boolean);
|
|
var
|
|
j: Integer;
|
|
mlen: Integer;
|
|
i: Integer;
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(jisdata[i] > $FF) then
|
|
begin
|
|
mode[i] := 'K';
|
|
end else begin
|
|
mode[i] := 'B';
|
|
if IsTrue(in_alpha (jisdata[i])) then
|
|
begin
|
|
mode[i] := 'A';
|
|
end;
|
|
if IsTrue(gs1) and ((jisdata[i] = integer('['))) then
|
|
begin
|
|
mode[i] := 'A';
|
|
end;
|
|
if IsTrue(((jisdata[i] >= integer('0'))) and ((jisdata[i] <= integer('9')))) then
|
|
begin
|
|
mode[i] := 'N';
|
|
end;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(mode[i] = 'N') then
|
|
begin
|
|
if IsTrue(((((i <> 0)) and ((mode[i - 1] <> 'N')))) or ((i = 0))) then
|
|
begin
|
|
mlen := 0;
|
|
while (((mlen + i) < length)) and ((mode[mlen + i] = 'N')) do
|
|
begin
|
|
Inc (mlen);
|
|
end;
|
|
if IsTrue(mlen < 6) then
|
|
begin
|
|
j := 0;
|
|
while j < mlen do
|
|
begin
|
|
mode[i + j] := 'A';
|
|
Inc (j);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(mode[i] = 'A') then
|
|
begin
|
|
if IsTrue(((((i <> 0)) and ((mode[i - 1] <> 'A')))) or ((i = 0))) then
|
|
begin
|
|
mlen := 0;
|
|
while (((mlen + i) < length)) and ((mode[mlen + i] = 'A')) do
|
|
begin
|
|
Inc (mlen);
|
|
end;
|
|
if IsTrue(mlen < 6) then
|
|
begin
|
|
j := 0;
|
|
while j < mlen do
|
|
begin
|
|
mode[i + j] := 'B';
|
|
Inc (j);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
|
|
function estimate_binary_length(mode: PChar; length: Integer; gs1: Boolean): Integer;
|
|
var
|
|
count: Integer = 0;
|
|
i: Integer = 0;
|
|
current: Char = #0;
|
|
a_count: Integer = 0;
|
|
n_count: Integer = 0;
|
|
begin
|
|
{INITCODE} count := 0;
|
|
{INITCODE} i := 0;
|
|
{INITCODE} current := #0;
|
|
{INITCODE} a_count := 0;
|
|
{INITCODE} n_count := 0;
|
|
if IsTrue(gs1) then
|
|
begin
|
|
count := count + 4;
|
|
end;
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(mode[i] <> current) then
|
|
begin
|
|
case mode[i] of
|
|
'K':
|
|
begin
|
|
count := count + (12 + 4);
|
|
current := 'K';
|
|
end;
|
|
'B':
|
|
begin
|
|
count := count + (16 + 4);
|
|
current := 'B';
|
|
end;
|
|
'A':
|
|
begin
|
|
count := count + (13 + 4);
|
|
current := 'A';
|
|
a_count := 0;
|
|
end;
|
|
'N':
|
|
begin
|
|
count := count + (14 + 4);
|
|
current := 'N';
|
|
n_count := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
case mode[i] of
|
|
'K': count := count + 13;
|
|
'B': count := count + 8;
|
|
'A':
|
|
begin
|
|
Inc (a_count);
|
|
if IsTrue((a_count and 1) = 0) then
|
|
begin
|
|
count := count + 5;
|
|
a_count := 0;
|
|
end else begin
|
|
count := count + 6;
|
|
end;
|
|
end;
|
|
'N':
|
|
begin
|
|
Inc (n_count);
|
|
if IsTrue((n_count mod 3) = 0) then
|
|
begin
|
|
count := count + 3;
|
|
n_count := 0;
|
|
end else begin
|
|
if IsTrue((n_count and 1) = 0) then
|
|
begin
|
|
count := count + 3;
|
|
end else begin
|
|
count := count + 4;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
exit (count);
|
|
end;
|
|
|
|
procedure qr_bscan(binary: PChar; data: Integer; h: Integer);
|
|
begin
|
|
while h<>0 do
|
|
begin
|
|
concat (binary, iif (data and h,'1','0'));
|
|
h := h shr 1;
|
|
end;
|
|
end;
|
|
|
|
procedure qr_bscan(var binary: array of char; data: Integer; h: Integer);
|
|
begin
|
|
qr_bscan(pchar(@binary[0]),data,h);
|
|
end;
|
|
|
|
procedure qr_binary(datastream: PInteger; version: Integer; target_binlen: Integer; mode: PChar; jisdata: PInteger; length: Integer; gs1: Boolean; est_binlen: Integer);
|
|
var
|
|
debug: Integer = 0;
|
|
position: Integer = 0;
|
|
scheme: Integer = 1;
|
|
i: Integer = 1;
|
|
short_data_block_length: Integer = 1;
|
|
padbits: BYTE;
|
|
data_block: Char;
|
|
current_bytes: Integer;
|
|
current_binlen: Integer;
|
|
percent: Integer;
|
|
toggle: Integer;
|
|
binary: array of Char;
|
|
jis: Integer;
|
|
prod: Integer;
|
|
lsb: Integer;
|
|
msb: Integer;
|
|
byte: Integer;
|
|
count: Integer;
|
|
// prod: Integer;
|
|
second: Integer = 0;
|
|
first: Integer = 0;
|
|
// count: Integer;
|
|
// prod: Integer;
|
|
third: Integer = 0;
|
|
// second: Integer = 0;
|
|
// first: Integer = 0;
|
|
begin
|
|
{INITCODE} debug := 0;
|
|
{INITCODE} position := 0;
|
|
{INITCODE} scheme := 1;
|
|
{INITCODE} i := 1;
|
|
{INITCODE} short_data_block_length := 1;
|
|
SetLength(binary,est_binlen + 12);
|
|
|
|
strcpy (binary, '');
|
|
if IsTrue(gs1) then
|
|
begin
|
|
concat (binary, '0101');
|
|
end;
|
|
if IsTrue(version <= 9) then
|
|
begin
|
|
scheme := 1;
|
|
end else begin
|
|
if IsTrue(((version >= 10)) and ((version <= 26))) then
|
|
begin
|
|
scheme := 2;
|
|
end else begin
|
|
if IsTrue(version >= 27) then
|
|
begin
|
|
scheme := 3;
|
|
end;
|
|
end;
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
write( format ('%s',[mode[i]]) );
|
|
Inc (i);
|
|
end;
|
|
write( LineEnding );
|
|
end;
|
|
percent := 0;
|
|
repeat
|
|
data_block := mode[position];
|
|
short_data_block_length := 0;
|
|
repeat
|
|
Inc (short_data_block_length);
|
|
until NotBoolean ((((short_data_block_length + position) < length)) and ((mode[position + short_data_block_length] = data_block)));
|
|
case data_block of
|
|
'K':
|
|
begin
|
|
concat (binary, '1000');
|
|
qr_bscan (binary, short_data_block_length, $20 shl (scheme * 2));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Kanji block (length %d)'+LineEnding+char(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} jis := jisdata[position + i];
|
|
if IsTrue(jis > $9FFF) then
|
|
begin
|
|
jis := jis - $C140;
|
|
end;
|
|
msb := (jis and $FF00) shr 4;
|
|
lsb := (jis and $FF);
|
|
prod := (msb * $C0) + lsb;
|
|
qr_bscan (binary, prod, $1000);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X ',[prod]) );
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write(LineEnding);
|
|
end;
|
|
end;
|
|
'B':
|
|
begin
|
|
concat (binary, '0100');
|
|
qr_bscan (binary, short_data_block_length, iif (scheme > 1,$8000,$80));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Byte block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} byte := jisdata[position + i];
|
|
if IsTrue(gs1) and ((byte = integer('['))) then
|
|
begin
|
|
byte := $1D;
|
|
end;
|
|
qr_bscan (binary, byte, $80);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.2X(%d) ',[byte, byte]) );
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
'A':
|
|
begin
|
|
concat (binary, '0010');
|
|
qr_bscan (binary, short_data_block_length, $40 shl (2 * scheme));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Alpha block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} second := 0;
|
|
{INITCODE} first := 0;
|
|
if IsTrue(percent = 0) then
|
|
begin
|
|
if IsTrue(gs1) and ((jisdata[position + i] = integer('%'))) then
|
|
begin
|
|
first := posn (RHODIUM, '%');
|
|
second := posn (RHODIUM, '%');
|
|
count := 2;
|
|
prod := (first * 45) + second;
|
|
Inc (i);
|
|
end else begin
|
|
if IsTrue(gs1) and ((jisdata[position + i] = integer('['))) then
|
|
begin
|
|
first := posn (RHODIUM, '%');
|
|
end else begin
|
|
first := posn (RHODIUM, Char (jisdata[position + i]));
|
|
end;
|
|
count := 1;
|
|
Inc (i);
|
|
prod := first;
|
|
if IsTrue(mode[position + i] = 'A') then
|
|
begin
|
|
if IsTrue(gs1) and ((jisdata[position + i] = integer('%'))) then
|
|
begin
|
|
second := posn (RHODIUM, '%');
|
|
count := 2;
|
|
prod := (first * 45) + second;
|
|
percent := 1;
|
|
end else begin
|
|
if IsTrue(gs1) and ((jisdata[position + i] = integer('['))) then
|
|
begin
|
|
second := posn (RHODIUM, '%');
|
|
end else begin
|
|
second := posn (RHODIUM, Char (jisdata[position + i]));
|
|
end;
|
|
count := 2;
|
|
Inc (i);
|
|
prod := (first * 45) + second;
|
|
end;
|
|
end;
|
|
end;
|
|
end else begin
|
|
first := posn (RHODIUM, '%');
|
|
count := 1;
|
|
Inc (i);
|
|
prod := first;
|
|
percent := 0;
|
|
if IsTrue(mode[position + i] = 'A') then
|
|
begin
|
|
if IsTrue(gs1) and ((jisdata[position + i] = integer('%'))) then
|
|
begin
|
|
second := posn (RHODIUM, '%');
|
|
count := 2;
|
|
prod := (first * 45) + second;
|
|
percent := 1;
|
|
end else begin
|
|
if IsTrue(gs1) and ((jisdata[position + i] = integer('['))) then
|
|
begin
|
|
second := posn (RHODIUM, '%');
|
|
end else begin
|
|
second := posn (RHODIUM, Char (jisdata[position + i]));
|
|
end;
|
|
count := 2;
|
|
Inc (i);
|
|
prod := (first * 45) + second;
|
|
end;
|
|
end;
|
|
end;
|
|
qr_bscan (binary, prod, iif (count = 2,$400,$20));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X ',[prod]) );
|
|
end;
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
'N':
|
|
begin
|
|
concat (binary, '0001');
|
|
qr_bscan (binary, short_data_block_length, $80 shl (2 * scheme));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Number block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} third := 0;
|
|
{INITCODE} second := 0;
|
|
{INITCODE} first := 0;
|
|
first := posn (NEON, Char (jisdata[position + i]));
|
|
count := 1;
|
|
prod := first;
|
|
if IsTrue(mode[position + i + 1] = 'N') then
|
|
begin
|
|
second := posn (NEON, Char (jisdata[position + i + 1]));
|
|
count := 2;
|
|
prod := (prod * 10) + second;
|
|
if IsTrue(mode[position + i + 2] = 'N') then
|
|
begin
|
|
third := posn (NEON, Char (jisdata[position + i + 2]));
|
|
count := 3;
|
|
prod := (prod * 10) + third;
|
|
end;
|
|
end;
|
|
qr_bscan (binary, prod, 1 shl (3 * count));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X (%d)',[prod, prod]) );
|
|
end;
|
|
i := i + count;
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
end;
|
|
position := position + short_data_block_length;
|
|
until NotBoolean (position < length);
|
|
concat (binary, '0000');
|
|
current_binlen := strlen (binary);
|
|
padbits := 8 - (current_binlen mod 8);
|
|
if IsTrue(padbits = 8) then
|
|
begin
|
|
padbits := 0;
|
|
end;
|
|
current_bytes := (current_binlen + padbits) div 8;
|
|
i := 0;
|
|
while i < padbits do
|
|
begin
|
|
concat (binary, '0');
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
while i < current_bytes do
|
|
begin
|
|
datastream[i] := $00;
|
|
if IsTrue(binary[i * 8] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $80;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 1] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $40;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 2] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $20;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 3] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $10;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 4] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $08;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 5] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $04;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 6] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $02;
|
|
end;
|
|
if IsTrue(binary[i * 8 + 7] = '1') then
|
|
begin
|
|
datastream[i] := datastream[i] + $01;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
toggle := 0;
|
|
i := current_bytes;
|
|
while i < target_binlen do
|
|
begin
|
|
if IsTrue(toggle = 0) then
|
|
begin
|
|
datastream[i] := $EC;
|
|
toggle := 1;
|
|
end else begin
|
|
datastream[i] := $11;
|
|
toggle := 0;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Resulting codewords:'+LineEnding+chr(9),[]) );
|
|
i := 0;
|
|
while i < target_binlen do
|
|
begin
|
|
write( format ('0x%.2X ',[datastream[i]]) );
|
|
Inc (i);
|
|
end;
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
|
|
procedure add_ecc(fullstream: PInteger; datastream: PInteger; version: Integer; data_cw: Integer; blocks: Integer);
|
|
var
|
|
ecc_cw: Integer;
|
|
short_data_block_length: Integer;
|
|
qty_long_blocks: Integer;
|
|
qty_short_blocks: Integer;
|
|
ecc_block_length: Integer;
|
|
debug: Integer = 0;
|
|
posn: Integer = 0;
|
|
length_this_block: Integer = 0;
|
|
j: Integer = 0;
|
|
i: Integer = 0;
|
|
data_block: array of BYTE;
|
|
ecc_block: array of BYTE;
|
|
interleaved_data: array of Integer;
|
|
interleaved_ecc: array of Integer;
|
|
begin
|
|
{INITCODE} ecc_cw := qr_total_codewords[version - 1] - data_cw;
|
|
{INITCODE} short_data_block_length := data_cw div blocks;
|
|
{INITCODE} qty_long_blocks := data_cw mod blocks;
|
|
{INITCODE} qty_short_blocks := blocks - qty_long_blocks;
|
|
{INITCODE} ecc_block_length := ecc_cw div blocks;
|
|
{INITCODE} debug := 0;
|
|
{INITCODE} posn := 0;
|
|
{INITCODE} length_this_block := 0;
|
|
{INITCODE} j := 0;
|
|
{INITCODE} i := 0;
|
|
SetLength(data_block,short_data_block_length + 2);
|
|
SetLength(ecc_block,ecc_block_length + 2);
|
|
SetLength(interleaved_data,data_cw + 2);
|
|
SetLength(interleaved_ecc,ecc_cw + 2);
|
|
posn := 0;
|
|
i := 0;
|
|
while i < blocks do
|
|
begin
|
|
if IsTrue(i < qty_short_blocks) then
|
|
begin
|
|
length_this_block := short_data_block_length;
|
|
end else begin
|
|
length_this_block := short_data_block_length + 1;
|
|
end;
|
|
j := 0;
|
|
while j < ecc_block_length do
|
|
begin
|
|
ecc_block[j] := 0;
|
|
Inc (j);
|
|
end;
|
|
j := 0;
|
|
while j < length_this_block do
|
|
begin
|
|
data_block[j] := BYTE (datastream[posn + j]);
|
|
Inc (j);
|
|
end;
|
|
rs_init_gf ($11D);
|
|
rs_init_code (ecc_block_length, 0);
|
|
rs_encode (length_this_block, @data_block[0], @ecc_block[0]);
|
|
rs_free;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Block %d: ',[i + 1]) );
|
|
j := 0;
|
|
while j < length_this_block do
|
|
begin
|
|
write( format ('%2X ',[data_block[j]]) );
|
|
Inc (j);
|
|
end;
|
|
if IsTrue(i < qty_short_blocks) then
|
|
begin
|
|
write( format (' ',[]) );
|
|
end;
|
|
write( format (' // ',[]) );
|
|
j := 0;
|
|
while j < ecc_block_length do
|
|
begin
|
|
write( format ('%.2X ',[ecc_block[ecc_block_length - j - 1]]) );
|
|
Inc (j);
|
|
end;
|
|
write( LineEnding );
|
|
end;
|
|
j := 0;
|
|
while j < short_data_block_length do
|
|
begin
|
|
interleaved_data[(j * blocks) + i] := Integer (data_block[j]);
|
|
Inc (j);
|
|
end;
|
|
if IsTrue(i >= qty_short_blocks) then
|
|
begin
|
|
interleaved_data[(short_data_block_length * blocks) + (i - qty_short_blocks)] := Integer (data_block[short_data_block_length]);
|
|
end;
|
|
j := 0;
|
|
while j < ecc_block_length do
|
|
begin
|
|
interleaved_ecc[(j * blocks) + i] := Integer (ecc_block[ecc_block_length - j - 1]);
|
|
Inc (j);
|
|
end;
|
|
posn := posn + length_this_block;
|
|
Inc (i);
|
|
end;
|
|
j := 0;
|
|
while j < data_cw do
|
|
begin
|
|
fullstream[j] := interleaved_data[j];
|
|
Inc (j);
|
|
end;
|
|
j := 0;
|
|
while j < ecc_cw do
|
|
begin
|
|
fullstream[j + data_cw] := interleaved_ecc[j];
|
|
Inc (j);
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format (LineEnding+'Data Stream: '+LineEnding,[]) );
|
|
j := 0;
|
|
while j < (data_cw + ecc_cw) do
|
|
begin
|
|
write( format ('%.2X ',[fullstream[j]]) );
|
|
Inc (j);
|
|
end;
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
|
|
procedure place_finder(grid: PBYTE; size: Integer; x: Integer; y: Integer);
|
|
var
|
|
yp: Integer;
|
|
xp: Integer;
|
|
const
|
|
finder: array [0..48] of integer= (
|
|
1, 1, 1, 1, 1, 1, 1,
|
|
1, 0, 0, 0, 0, 0, 1,
|
|
1, 0, 1, 1, 1, 0, 1,
|
|
1, 0, 1, 1, 1, 0, 1,
|
|
1, 0, 1, 1, 1, 0, 1,
|
|
1, 0, 0, 0, 0, 0, 1,
|
|
1, 1, 1, 1, 1, 1, 1
|
|
);
|
|
begin
|
|
xp := 0;
|
|
while xp < 7 do
|
|
begin
|
|
yp := 0;
|
|
while yp < 7 do
|
|
begin
|
|
if IsTrue(finder[xp + (7 * yp)] = 1) then
|
|
begin
|
|
grid[((yp + y) * size) + (xp + x)] := $11;
|
|
end else begin
|
|
grid[((yp + y) * size) + (xp + x)] := $10;
|
|
end;
|
|
Inc (yp);
|
|
end;
|
|
Inc (xp);
|
|
end;
|
|
end;
|
|
|
|
procedure place_align(grid: PBYTE; size: Integer; x: Integer; y: Integer);
|
|
var
|
|
yp: Integer;
|
|
xp: Integer;
|
|
const
|
|
alignment: array [0..24] of integer = (
|
|
1, 1, 1, 1, 1,
|
|
1, 0, 0, 0, 1,
|
|
1, 0, 1, 0, 1,
|
|
1, 0, 0, 0, 1,
|
|
1, 1, 1, 1, 1
|
|
);
|
|
begin
|
|
x := x - 2;
|
|
y := y - 2;
|
|
xp := 0;
|
|
while xp < 5 do
|
|
begin
|
|
yp := 0;
|
|
while yp < 5 do
|
|
begin
|
|
if IsTrue(alignment[xp + (5 * yp)] = 1) then
|
|
begin
|
|
grid[((yp + y) * size) + (xp + x)] := $11;
|
|
end else begin
|
|
grid[((yp + y) * size) + (xp + x)] := $10;
|
|
end;
|
|
Inc (yp);
|
|
end;
|
|
Inc (xp);
|
|
end;
|
|
end;
|
|
|
|
procedure setup_grid(grid: PBYTE; size: Integer; version: Integer);
|
|
var
|
|
toggle: Integer = 1;
|
|
i: Integer = 1;
|
|
ycoord: Integer;
|
|
xcoord: Integer;
|
|
y: Integer;
|
|
x: Integer;
|
|
loopsize: Integer;
|
|
begin
|
|
{INITCODE} toggle := 1;
|
|
{INITCODE} i := 1;
|
|
i := 0;
|
|
while i < size do
|
|
begin
|
|
if IsTrue(toggle = 1) then
|
|
begin
|
|
grid[(6 * size) + i] := $21;
|
|
grid[(i * size) + 6] := $21;
|
|
toggle := 0;
|
|
end else begin
|
|
grid[(6 * size) + i] := $20;
|
|
grid[(i * size) + 6] := $20;
|
|
toggle := 1;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
place_finder (grid, size, 0, 0);
|
|
place_finder (grid, size, 0, size - 7);
|
|
place_finder (grid, size, size - 7, 0);
|
|
i := 0;
|
|
while i < 7 do
|
|
begin
|
|
grid[(7 * size) + i] := $10;
|
|
grid[(i * size) + 7] := $10;
|
|
grid[(7 * size) + (size - 1 - i)] := $10;
|
|
grid[(i * size) + (size - 8)] := $10;
|
|
grid[((size - 8) * size) + i] := $10;
|
|
grid[((size - 1 - i) * size) + 7] := $10;
|
|
Inc (i);
|
|
end;
|
|
grid[(7 * size) + 7] := $10;
|
|
grid[(7 * size) + (size - 8)] := $10;
|
|
grid[((size - 8) * size) + 7] := $10;
|
|
if IsTrue(version <> 1) then
|
|
begin
|
|
loopsize := qr_align_loopsize[version - 1];
|
|
x := 0;
|
|
while x < loopsize do
|
|
begin
|
|
y := 0;
|
|
while y < loopsize do
|
|
begin
|
|
xcoord := qr_table_e1[((version - 2) * 7) + x];
|
|
ycoord := qr_table_e1[((version - 2) * 7) + y];
|
|
if not IsTrue((grid[(ycoord * size) + xcoord] and $10)) then
|
|
begin
|
|
place_align (grid, size, xcoord, ycoord);
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
end;
|
|
i := 0;
|
|
while i < 8 do
|
|
begin
|
|
grid[(8 * size) + i] := grid[(8 * size) + i] + $20;
|
|
grid[(i * size) + 8] := grid[(i * size) + 8] + $20;
|
|
grid[(8 * size) + (size - 1 - i)] := $20;
|
|
grid[((size - 1 - i) * size) + 8] := $20;
|
|
Inc (i);
|
|
end;
|
|
grid[(8 * size) + 8] := grid[(8 * size) + 8] + 20;
|
|
grid[((size - 1 - 7) * size) + 8] := $21;
|
|
if IsTrue(version >= 7) then
|
|
begin
|
|
i := 0;
|
|
while i < 6 do
|
|
begin
|
|
grid[((size - 9) * size) + i] := $20;
|
|
grid[((size - 10) * size) + i] := $20;
|
|
grid[((size - 11) * size) + i] := $20;
|
|
grid[(i * size) + (size - 9)] := $20;
|
|
grid[(i * size) + (size - 10)] := $20;
|
|
grid[(i * size) + (size - 11)] := $20;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function cwbit(datastream: PInteger; i: Integer): Integer;
|
|
var
|
|
word: Integer;
|
|
bit: Integer;
|
|
resultant: Integer = 0;
|
|
begin
|
|
{INITCODE} word := i div 8;
|
|
{INITCODE} bit := i mod 8;
|
|
{INITCODE} resultant := 0;
|
|
case bit of
|
|
0:
|
|
begin
|
|
if IsTrue(datastream[word] and $80) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
1:
|
|
begin
|
|
if IsTrue(datastream[word] and $40) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
2:
|
|
begin
|
|
if IsTrue(datastream[word] and $20) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
3:
|
|
begin
|
|
if IsTrue(datastream[word] and $10) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
4:
|
|
begin
|
|
if IsTrue(datastream[word] and $08) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
5:
|
|
begin
|
|
if IsTrue(datastream[word] and $04) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
6:
|
|
begin
|
|
if IsTrue(datastream[word] and $02) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
7:
|
|
begin
|
|
if IsTrue(datastream[word] and $01) then
|
|
begin
|
|
resultant := 1;
|
|
end else begin
|
|
resultant := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
exit (resultant);
|
|
end;
|
|
|
|
procedure populate_grid(grid: PBYTE; size: Integer; datastream: PInteger; cw: Integer);
|
|
var
|
|
direction: Integer = 1;
|
|
row: Integer = 0;
|
|
y: Integer;
|
|
x: Integer;
|
|
n: Integer;
|
|
i: Integer;
|
|
begin
|
|
{INITCODE} direction := 1;
|
|
{INITCODE} row := 0;
|
|
n := cw * 8;
|
|
y := size - 1;
|
|
i := 0;
|
|
repeat
|
|
x := (size - 2) - (row * 2);
|
|
if IsTrue(x < 6) then
|
|
begin
|
|
Dec (x);
|
|
end;
|
|
if not IsTrue((grid[(y * size) + (x + 1)] and $F0)) then
|
|
begin
|
|
if IsTrue(cwbit (datastream, i)) then
|
|
begin
|
|
grid[(y * size) + (x + 1)] := $01;
|
|
end else begin
|
|
grid[(y * size) + (x + 1)] := $00;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(i < n) then
|
|
begin
|
|
if not IsTrue((grid[(y * size) + x] and $F0)) then
|
|
begin
|
|
if IsTrue(cwbit (datastream, i)) then
|
|
begin
|
|
grid[(y * size) + x] := $01;
|
|
end else begin
|
|
grid[(y * size) + x] := $00;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
if IsTrue(direction) then
|
|
begin
|
|
Dec (y);
|
|
end else begin
|
|
Inc (y);
|
|
end;
|
|
if IsTrue(y = -1) then
|
|
begin
|
|
Inc (row);
|
|
y := 0;
|
|
direction := 0;
|
|
end;
|
|
if IsTrue(y = size) then
|
|
begin
|
|
Inc (row);
|
|
y := size - 1;
|
|
direction := 1;
|
|
end;
|
|
until not (i < n);
|
|
end;
|
|
|
|
function evaluate(grid: PBYTE; size: Integer; pattern: Integer): Integer;
|
|
var
|
|
block: Integer;
|
|
y: Integer;
|
|
x: Integer;
|
|
resultcode: Integer = 0;
|
|
state: Char;
|
|
p: Integer;
|
|
dark_mods: Integer;
|
|
k: Integer;
|
|
percentage: Integer;
|
|
local: array of Char;
|
|
begin
|
|
{INITCODE} resultcode := 0;
|
|
SetLength(local,size * size);
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
case pattern of
|
|
0:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $01) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
1:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $02) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
2:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $04) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
3:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $08) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
4:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $10) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
5:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $20) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
6:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $40) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
7:
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $80) then
|
|
begin
|
|
local[(y * size) + x] := '1';
|
|
end else begin
|
|
local[(y * size) + x] := '0';
|
|
end;
|
|
end;
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
state := local[x];
|
|
block := 0;
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
if IsTrue(local[(y * size) + x] = state) then
|
|
begin
|
|
Inc (block);
|
|
end else begin
|
|
if IsTrue(block > 5) then
|
|
begin
|
|
resultcode := resultcode + ((3 + block));
|
|
end;
|
|
block := 0;
|
|
state := local[(y * size) + x];
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
if IsTrue(block > 5) then
|
|
begin
|
|
resultcode := resultcode + ((3 + block));
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
state := local[y * size];
|
|
block := 0;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
if IsTrue(local[(y * size) + x] = state) then
|
|
begin
|
|
Inc (block);
|
|
end else begin
|
|
if IsTrue(block > 5) then
|
|
begin
|
|
resultcode := resultcode + ((3 + block));
|
|
end;
|
|
block := 0;
|
|
state := local[(y * size) + x];
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
if IsTrue(block > 5) then
|
|
begin
|
|
resultcode := resultcode + ((3 + block));
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < (size - 7) do
|
|
begin
|
|
p := 0;
|
|
if IsTrue(local[(y * size) + x] = '1') then
|
|
begin
|
|
p := p + $40;
|
|
end;
|
|
if IsTrue(local[((y + 1) * size) + x] = '1') then
|
|
begin
|
|
p := p + $20;
|
|
end;
|
|
if IsTrue(local[((y + 2) * size) + x] = '1') then
|
|
begin
|
|
p := p + $10;
|
|
end;
|
|
if IsTrue(local[((y + 3) * size) + x] = '1') then
|
|
begin
|
|
p := p + $08;
|
|
end;
|
|
if IsTrue(local[((y + 4) * size) + x] = '1') then
|
|
begin
|
|
p := p + $04;
|
|
end;
|
|
if IsTrue(local[((y + 5) * size) + x] = '1') then
|
|
begin
|
|
p := p + $02;
|
|
end;
|
|
if IsTrue(local[((y + 6) * size) + x] = '1') then
|
|
begin
|
|
p := p + $01;
|
|
end;
|
|
if IsTrue(p = $5D) then
|
|
begin
|
|
resultcode := resultcode + 40;
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
x := 0;
|
|
while x < (size - 7) do
|
|
begin
|
|
p := 0;
|
|
if IsTrue(local[(y * size) + x] = '1') then
|
|
begin
|
|
p := p + $40;
|
|
end;
|
|
if IsTrue(local[(y * size) + x + 1] = '1') then
|
|
begin
|
|
p := p + $20;
|
|
end;
|
|
if IsTrue(local[(y * size) + x + 2] = '1') then
|
|
begin
|
|
p := p + $10;
|
|
end;
|
|
if IsTrue(local[(y * size) + x + 3] = '1') then
|
|
begin
|
|
p := p + $08;
|
|
end;
|
|
if IsTrue(local[(y * size) + x + 4] = '1') then
|
|
begin
|
|
p := p + $04;
|
|
end;
|
|
if IsTrue(local[(y * size) + x + 5] = '1') then
|
|
begin
|
|
p := p + $02;
|
|
end;
|
|
if IsTrue(local[(y * size) + x + 6] = '1') then
|
|
begin
|
|
p := p + $01;
|
|
end;
|
|
if IsTrue(p = $5D) then
|
|
begin
|
|
resultcode := resultcode + 40;
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
dark_mods := 0;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
if IsTrue(local[(y * size) + x] = '1') then
|
|
begin
|
|
Inc (dark_mods);
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
percentage := 100 * (dark_mods div (size * size));
|
|
if IsTrue(percentage <= 50) then
|
|
begin
|
|
k := ((100 - percentage) - 50) div 5;
|
|
end else begin
|
|
k := (percentage - 50) div 5;
|
|
end;
|
|
resultcode := resultcode + (10 * k);
|
|
exit (resultcode);
|
|
end;
|
|
|
|
function apply_bitmask(grid: PBYTE; size: Integer): Integer;
|
|
var
|
|
y: Integer;
|
|
x: Integer;
|
|
p: BYTE;
|
|
penalty: array [0..8-1] of Integer;
|
|
pattern: Integer;
|
|
best_pattern: Integer;
|
|
best_val: Integer;
|
|
bit: Integer;
|
|
mask: array of BYTE;
|
|
eval: array of BYTE;
|
|
begin
|
|
SetLength(mask,size * size);
|
|
SetLength(eval,size * size);
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
mask[(y * size) + x] := $00;
|
|
if not IsTrue((grid[(y * size) + x] and $F0)) then
|
|
begin
|
|
if IsTrue(((y + x) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $01;
|
|
end;
|
|
if IsTrue((y and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $02;
|
|
end;
|
|
if IsTrue((x mod 3) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $04;
|
|
end;
|
|
if IsTrue(((y + x) mod 3) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $08;
|
|
end;
|
|
if IsTrue((((y div 2) + (x div 3)) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $10;
|
|
end;
|
|
if IsTrue((((y * x) and 1) + ((y * x) mod 3)) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $20;
|
|
end;
|
|
if IsTrue(((((y * x) and 1) + ((y * x) mod 3)) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $40;
|
|
end;
|
|
if IsTrue(((((y + x) and 1) + ((y * x) mod 3)) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $80;
|
|
end;
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $01) then
|
|
begin
|
|
p := $FF;
|
|
end else begin
|
|
p := $00;
|
|
end;
|
|
eval[(y * size) + x] := mask[(y * size) + x] xor p;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
pattern := 0;
|
|
while pattern < 8 do
|
|
begin
|
|
penalty[pattern] := evaluate (@eval[0], size, pattern);
|
|
Inc (pattern);
|
|
end;
|
|
best_pattern := 0;
|
|
best_val := penalty[0];
|
|
pattern := 1;
|
|
while pattern < 8 do
|
|
begin
|
|
if IsTrue(penalty[pattern] < best_val) then
|
|
begin
|
|
best_pattern := pattern;
|
|
best_val := penalty[pattern];
|
|
end;
|
|
Inc (pattern);
|
|
end;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
bit := 0;
|
|
case best_pattern of
|
|
0:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $01) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
1:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $02) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
2:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $04) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
3:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $08) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
4:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $10) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
5:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $20) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
6:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $40) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
7:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $80) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
if IsTrue(bit = 1) then
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $01) then
|
|
begin
|
|
grid[(y * size) + x] := $00;
|
|
end else begin
|
|
grid[(y * size) + x] := $01;
|
|
end;
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
exit (best_pattern);
|
|
end;
|
|
|
|
procedure add_format_info(grid: PBYTE; size: Integer; ecc_level: Integer; pattern: Integer);
|
|
var
|
|
format: Integer;
|
|
seq: Cardinal;
|
|
i: Integer;
|
|
begin
|
|
{INITCODE} format := pattern;
|
|
case ecc_level of
|
|
LEVEL_L: format := format + $08;
|
|
LEVEL_Q: format := format + $18;
|
|
LEVEL_H: format := format + $10;
|
|
end;
|
|
seq := qr_annex_c[format];
|
|
i := 0;
|
|
while i < 6 do
|
|
begin
|
|
grid[(i * size) + 8] := grid[(i * size) + 8] + ((seq shr i) and $01);
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
while i < 8 do
|
|
begin
|
|
grid[(8 * size) + (size - i - 1)] := grid[(8 * size) + (size - i - 1)] + ((seq shr i) and $01);
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
while i < 6 do
|
|
begin
|
|
grid[(8 * size) + (5 - i)] := grid[(8 * size) + (5 - i)] + ((seq shr (i + 9)) and $01);
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
while i < 7 do
|
|
begin
|
|
grid[(((size - 7) + i) * size) + 8] := grid[(((size - 7) + i) * size) + 8] + ((seq shr (i + 8)) and $01);
|
|
Inc (i);
|
|
end;
|
|
grid[(7 * size) + 8] := grid[(7 * size) + 8] + ((seq shr 6) and $01);
|
|
grid[(8 * size) + 8] := grid[(8 * size) + 8] + ((seq shr 7) and $01);
|
|
grid[(8 * size) + 7] := grid[(8 * size) + 7] + ((seq shr 8) and $01);
|
|
end;
|
|
|
|
procedure add_version_info(grid: PBYTE; size: Integer; version: Integer);
|
|
var
|
|
i: Integer;
|
|
version_data: cardinal;
|
|
begin
|
|
{INITCODE} version_data := qr_annex_d[version - 7];
|
|
i := 0;
|
|
while i < 6 do
|
|
begin
|
|
grid[((size - 11) * size) + i] := grid[((size - 11) * size) + i] + ((version_data shr (i * 3)) and $01);
|
|
grid[((size - 10) * size) + i] := grid[((size - 10) * size) + i] + ((version_data shr ((i * 3) + 1)) and $01);
|
|
grid[((size - 9) * size) + i] := grid[((size - 9) * size) + i] + ((version_data shr ((i * 3) + 2)) and $01);
|
|
grid[(i * size) + (size - 11)] := grid[(i * size) + (size - 11)] + ((version_data shr (i * 3)) and $01);
|
|
grid[(i * size) + (size - 10)] := grid[(i * size) + (size - 10)] + ((version_data shr ((i * 3) + 1)) and $01);
|
|
grid[(i * size) + (size - 9)] := grid[(i * size) + (size - 9)] + ((version_data shr ((i * 3) + 2)) and $01);
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
|
|
function qr_code(symbol: PointerTo_zint_symbol; source: PBYTE; length: Integer): Integer;
|
|
var
|
|
est_binlen: Integer;
|
|
glyph: Integer;
|
|
j: Integer;
|
|
i: Integer;
|
|
error_number: Integer;
|
|
size: Integer;
|
|
blocks: Integer;
|
|
target_binlen: Integer;
|
|
max_cw: Integer;
|
|
version: Integer;
|
|
autosize: Integer;
|
|
ecc_level: Integer;
|
|
gs1: Boolean;
|
|
bitmask: Integer;
|
|
utfdata: array of Integer;
|
|
jisdata: array of Integer;
|
|
mode: array of Char;
|
|
datastream: array of Integer;
|
|
fullstream: array of Integer;
|
|
grid: array of BYTE;
|
|
begin
|
|
SetLength(utfdata,length + 1);
|
|
SetLength(jisdata,length + 1);
|
|
SetLength(mode,length + 1);
|
|
|
|
gs1 := (symbol^.input_mode = GS1_MODE);
|
|
case symbol^.input_mode of
|
|
DATA_MODE:
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
jisdata[i] := Integer (source[i]);
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
otherwise
|
|
begin
|
|
error_number := utf8toutf16 (symbol, source, @utfdata[0], @length);
|
|
if IsTrue(error_number <> 0) then
|
|
begin
|
|
exit (error_number);
|
|
end;
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(utfdata[i] <= $FF) then
|
|
begin
|
|
jisdata[i] := utfdata[i];
|
|
end else begin
|
|
j := 0;
|
|
glyph := 0;
|
|
repeat
|
|
if IsTrue(sjis_lookup[j * 2] = utfdata[i]) then
|
|
begin
|
|
glyph := sjis_lookup[(j * 2) + 1];
|
|
end;
|
|
Inc (j);
|
|
until NotBoolean (((j < 6843)) and ((glyph = 0)));
|
|
if IsTrue(glyph = 0) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Invalid character in input data');
|
|
exit (ERROR_INVALID_DATA);
|
|
end;
|
|
jisdata[i] := glyph;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
end;
|
|
define_mode (@mode[0], @jisdata[0], length, gs1);
|
|
est_binlen := estimate_binary_length (@mode[0], length, gs1);
|
|
ecc_level := LEVEL_L;
|
|
max_cw := 2956;
|
|
if IsTrue(((symbol^.option_1 >= 1)) and ((symbol^.option_1 <= 4))) then
|
|
begin
|
|
case symbol^.option_1 of
|
|
1:
|
|
begin
|
|
ecc_level := LEVEL_L;
|
|
max_cw := 2956;
|
|
end;
|
|
2:
|
|
begin
|
|
ecc_level := LEVEL_M;
|
|
max_cw := 2334;
|
|
end;
|
|
3:
|
|
begin
|
|
ecc_level := LEVEL_Q;
|
|
max_cw := 1666;
|
|
end;
|
|
4:
|
|
begin
|
|
ecc_level := LEVEL_H;
|
|
max_cw := 1276;
|
|
end;
|
|
end;
|
|
end;
|
|
if IsTrue(est_binlen > (8 * max_cw)) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Input too long for selected error correction level');
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
autosize := 40;
|
|
i := 39;
|
|
while i >= 0 do
|
|
begin
|
|
case ecc_level of
|
|
LEVEL_L:
|
|
begin
|
|
if IsTrue((8 * qr_data_codewords_L[i]) >= est_binlen) then
|
|
begin
|
|
autosize := i + 1;
|
|
end;
|
|
end;
|
|
LEVEL_M:
|
|
begin
|
|
if IsTrue((8 * qr_data_codewords_M[i]) >= est_binlen) then
|
|
begin
|
|
autosize := i + 1;
|
|
end;
|
|
end;
|
|
LEVEL_Q:
|
|
begin
|
|
if IsTrue((8 * qr_data_codewords_Q[i]) >= est_binlen) then
|
|
begin
|
|
autosize := i + 1;
|
|
end;
|
|
end;
|
|
LEVEL_H:
|
|
begin
|
|
if IsTrue((8 * qr_data_codewords_H[i]) >= est_binlen) then
|
|
begin
|
|
autosize := i + 1;
|
|
end;
|
|
end;
|
|
end;
|
|
Dec (i);
|
|
end;
|
|
if IsTrue(((symbol^.option_2 >= 1)) and ((symbol^.option_2 <= 40))) then
|
|
begin
|
|
if IsTrue(symbol^.option_2 > autosize) then
|
|
begin
|
|
version := symbol^.option_2;
|
|
end else begin
|
|
version := autosize;
|
|
end;
|
|
end else begin
|
|
version := autosize;
|
|
end;
|
|
if IsTrue(est_binlen <= qr_data_codewords_M[version - 1]) then
|
|
begin
|
|
ecc_level := LEVEL_M;
|
|
end;
|
|
if IsTrue(est_binlen <= qr_data_codewords_Q[version - 1]) then
|
|
begin
|
|
ecc_level := LEVEL_Q;
|
|
end;
|
|
if IsTrue(est_binlen <= qr_data_codewords_H[version - 1]) then
|
|
begin
|
|
ecc_level := LEVEL_H;
|
|
end;
|
|
target_binlen := qr_data_codewords_L[version - 1];
|
|
SetLength(datastream,target_binlen + 1);
|
|
blocks := qr_blocks_L[version - 1];
|
|
case ecc_level of
|
|
LEVEL_M:
|
|
begin
|
|
target_binlen := qr_data_codewords_M[version - 1];
|
|
blocks := qr_blocks_M[version - 1];
|
|
end;
|
|
LEVEL_Q:
|
|
begin
|
|
target_binlen := qr_data_codewords_Q[version - 1];
|
|
blocks := qr_blocks_Q[version - 1];
|
|
end;
|
|
LEVEL_H:
|
|
begin
|
|
target_binlen := qr_data_codewords_H[version - 1];
|
|
blocks := qr_blocks_H[version - 1];
|
|
end;
|
|
end;
|
|
SetLength(fullstream,qr_total_codewords[version - 1] + 1);
|
|
qr_binary (@datastream[0], version, target_binlen, @mode[0], @jisdata[0], length, gs1, est_binlen);
|
|
add_ecc (@fullstream[0], @datastream[0], version, target_binlen, blocks);
|
|
size := qr_sizes[version - 1];
|
|
SetLength(grid,size * size);
|
|
i := 0;
|
|
while i < size do
|
|
begin
|
|
j := 0;
|
|
while j < size do
|
|
begin
|
|
grid[(i * size) + j] := 0;
|
|
Inc (j);
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
setup_grid (@grid[0], size, version);
|
|
populate_grid (@grid[0], size, @fullstream[0], qr_total_codewords[version - 1]);
|
|
bitmask := apply_bitmask (@grid[0], size);
|
|
add_format_info (@grid[0], size, ecc_level, bitmask);
|
|
if IsTrue(version >= 7) then
|
|
begin
|
|
add_version_info (@grid[0], size, version);
|
|
end;
|
|
symbol^.width := size;
|
|
symbol^.rows := size;
|
|
i := 0;
|
|
while i < size do
|
|
begin
|
|
j := 0;
|
|
while j < size do
|
|
begin
|
|
if IsTrue(grid[(i * size) + j] and $01) then
|
|
begin
|
|
set_module (symbol, i, j);
|
|
end;
|
|
Inc (j);
|
|
end;
|
|
symbol^.row_height[i] := 1;
|
|
Inc (i);
|
|
end;
|
|
exit (0);
|
|
end;
|
|
|
|
|
|
function micro_qr_intermediate(binary: PChar; jisdata: PInteger; mode: PChar; length: Integer; kanji_used: PInteger; alphanum_used: PInteger; byte_used: PInteger): Integer;
|
|
var
|
|
debug: Integer = 0;
|
|
position: Integer = 0;
|
|
i: Integer;
|
|
short_data_block_length: Integer;
|
|
data_block: Char;
|
|
buffer: array [0..2-1] of Char;
|
|
jis: Integer;
|
|
prod: Integer;
|
|
lsb: Integer;
|
|
msb: Integer;
|
|
byte: Integer;
|
|
count: Integer;
|
|
// prod: Integer;
|
|
second: Integer = 0;
|
|
first: Integer = 0;
|
|
// count: Integer;
|
|
// prod: Integer;
|
|
third: Integer = 0;
|
|
// second: Integer = 0;
|
|
// first: Integer = 0;
|
|
begin
|
|
{INITCODE} debug := 0;
|
|
{INITCODE} position := 0;
|
|
strcpy (binary, '');
|
|
if IsTrue(debug) then
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
write( format ('%c',[mode[i]]) );
|
|
Inc (i);
|
|
end;
|
|
write( LineEnding );
|
|
end;
|
|
repeat
|
|
if IsTrue(sysutils.strlen (binary) > 128) then
|
|
begin
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
data_block := mode[position];
|
|
short_data_block_length := 0;
|
|
repeat
|
|
Inc (short_data_block_length);
|
|
until NotBoolean ((((short_data_block_length + position) < length)) and ((mode[position + short_data_block_length] = data_block)));
|
|
case data_block of
|
|
'K':
|
|
begin
|
|
concat (binary, 'K');
|
|
kanji_used^ := 1;
|
|
buffer[0] := char(short_data_block_length);
|
|
buffer[1] := #0;
|
|
concat (binary, buffer);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Kanji block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} jis := jisdata[position + i];
|
|
if IsTrue(jis > $9FFF) then
|
|
begin
|
|
jis := jis - $C140;
|
|
end;
|
|
msb := (jis and $FF00) shr 4;
|
|
lsb := (jis and $FF);
|
|
prod := (msb * $C0) + lsb;
|
|
qr_bscan (binary, prod, $1000);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X ',[prod]) );
|
|
end;
|
|
if IsTrue(sysutils.strlen (binary) > 128) then
|
|
begin
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
'B':
|
|
begin
|
|
concat (binary, 'B');
|
|
byte_used^ := 1;
|
|
buffer[0] := char(short_data_block_length);
|
|
buffer[1] := #0;
|
|
concat (binary, buffer);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Byte block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} byte := jisdata[position + i];
|
|
qr_bscan (binary, byte, $80);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X ',[byte]) );
|
|
end;
|
|
if IsTrue(sysutils.strlen (binary) > 128) then
|
|
begin
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
'A':
|
|
begin
|
|
concat (binary, 'A');
|
|
alphanum_used^ := 1;
|
|
buffer[0] := char(short_data_block_length);
|
|
buffer[1] := #0;
|
|
concat (binary, buffer);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Alpha block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} second := 0;
|
|
{INITCODE} first := 0;
|
|
first := posn (RHODIUM, Char (jisdata[position + i]));
|
|
count := 1;
|
|
prod := first;
|
|
if IsTrue(mode[position + i + 1] = 'A') then
|
|
begin
|
|
second := posn (RHODIUM, Char (jisdata[position + i + 1]));
|
|
count := 2;
|
|
prod := (first * 45) + second;
|
|
end;
|
|
qr_bscan (binary, prod, 1 shl (5 * count));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X ',[prod]) );
|
|
end;
|
|
if IsTrue(sysutils.strlen (binary) > 128) then
|
|
begin
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
i := i + 2;
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
'N':
|
|
begin
|
|
concat (binary, 'N');
|
|
buffer[0] := char(short_data_block_length);
|
|
buffer[1] := #0;
|
|
concat (binary, buffer);
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('Number block (length %d)'+LineEnding+chr(9),[short_data_block_length]) );
|
|
end;
|
|
i := 0;
|
|
while i < short_data_block_length do
|
|
begin
|
|
{INITCODE} third := 0;
|
|
{INITCODE} second := 0;
|
|
{INITCODE} first := 0;
|
|
first := posn (NEON, Char (jisdata[position + i]));
|
|
count := 1;
|
|
prod := first;
|
|
if IsTrue(mode[position + i + 1] = 'N') then
|
|
begin
|
|
second := posn (NEON, Char (jisdata[position + i + 1]));
|
|
count := 2;
|
|
prod := (prod * 10) + second;
|
|
end;
|
|
if IsTrue(mode[position + i + 2] = 'N') then
|
|
begin
|
|
third := posn (NEON, Char (jisdata[position + i + 2]));
|
|
count := 3;
|
|
prod := (prod * 10) + third;
|
|
end;
|
|
qr_bscan (binary, prod, 1 shl (3 * count));
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( format ('0x%.4X (%d)',[prod, prod]) );
|
|
end;
|
|
if IsTrue(sysutils.strlen (binary) > 128) then
|
|
begin
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
i := i + 3;
|
|
end;
|
|
if IsTrue(debug) then
|
|
begin
|
|
write( LineEnding );
|
|
end;
|
|
end;
|
|
end;
|
|
position := position + short_data_block_length;
|
|
until not (position < length - 1);
|
|
exit (0);
|
|
end;
|
|
|
|
procedure get_bitlength(count: PInteger; stream: PChar);
|
|
var
|
|
i: Integer;
|
|
length: Integer;
|
|
begin
|
|
length := sysutils.strlen (stream);
|
|
i := 0;
|
|
while i < 4 do
|
|
begin
|
|
count[i] := 0;
|
|
Inc (i);
|
|
end;
|
|
i := 0;
|
|
repeat
|
|
if IsTrue(((stream[i] = '0')) or ((stream[i] = '1'))) then
|
|
begin
|
|
Inc (count[0]);
|
|
Inc (count[1]);
|
|
Inc (count[2]);
|
|
Inc (count[3]);
|
|
Inc (i);
|
|
end else begin
|
|
case stream[i] of
|
|
'K':
|
|
begin
|
|
count[2] := count[2] + 5;
|
|
count[3] := count[3] + 7;
|
|
i := i + 2;
|
|
end;
|
|
'B':
|
|
begin
|
|
count[2] := count[2] + 6;
|
|
count[3] := count[3] + 8;
|
|
i := i + 2;
|
|
end;
|
|
'A':
|
|
begin
|
|
count[1] := count[1] + 4;
|
|
count[2] := count[2] + 6;
|
|
count[3] := count[3] + 8;
|
|
i := i + 2;
|
|
end;
|
|
'N':
|
|
begin
|
|
count[0] := count[0] + 3;
|
|
count[1] := count[1] + 5;
|
|
count[2] := count[2] + 7;
|
|
count[3] := count[3] + 9;
|
|
i := i + 2;
|
|
end;
|
|
end;
|
|
end;
|
|
until not (i < length);
|
|
end;
|
|
|
|
procedure microqr_expand_binary(binary_stream: PChar; full_stream: PChar; version: Integer);
|
|
var
|
|
length: Integer;
|
|
i: Integer;
|
|
begin
|
|
length := sysutils.strlen (binary_stream);
|
|
i := 0;
|
|
repeat
|
|
case binary_stream[i] of
|
|
'1':
|
|
begin
|
|
concat (full_stream, '1');
|
|
Inc (i);
|
|
end;
|
|
'0':
|
|
begin
|
|
concat (full_stream, '0');
|
|
Inc (i);
|
|
end;
|
|
'N':
|
|
begin
|
|
case version of
|
|
1: concat (full_stream, '0');
|
|
2: concat (full_stream, '00');
|
|
3: concat (full_stream, '000');
|
|
end;
|
|
qr_bscan (full_stream, integer(binary_stream[i + 1]), 4 shl version);
|
|
i := i + 2;
|
|
end;
|
|
'A':
|
|
begin
|
|
case version of
|
|
1: concat (full_stream, '1');
|
|
2: concat (full_stream, '01');
|
|
3: concat (full_stream, '001');
|
|
end;
|
|
qr_bscan (full_stream, integer(binary_stream[i + 1]), 2 shl version);
|
|
i := i + 2;
|
|
end;
|
|
'B':
|
|
begin
|
|
case version of
|
|
2: concat (full_stream, '10');
|
|
3: concat (full_stream, '010');
|
|
end;
|
|
qr_bscan (full_stream, integer(binary_stream[i + 1]), 2 shl version);
|
|
i := i + 2;
|
|
end;
|
|
'K':
|
|
begin
|
|
case version of
|
|
2: concat (full_stream, '11');
|
|
3: concat (full_stream, '011');
|
|
end;
|
|
qr_bscan (full_stream, integer(binary_stream[i + 1]), 1 shl version);
|
|
i := i + 2;
|
|
end;
|
|
end;
|
|
until not (i < length);
|
|
end;
|
|
|
|
procedure micro_qr_m1(binary_data: PChar);
|
|
var
|
|
latch: Integer;
|
|
i: Integer;
|
|
remainder: Integer;
|
|
bits_left: Integer;
|
|
bits_total: Integer;
|
|
ecc_codewords: Integer;
|
|
data_codewords: Integer;
|
|
ecc_blocks: array [0..3-1] of BYTE;
|
|
data_blocks: array [0..4-1] of BYTE;
|
|
begin
|
|
bits_total := 20;
|
|
latch := 0;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left <= 3) then
|
|
begin
|
|
i := 0;
|
|
while i < bits_left do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
latch := 1;
|
|
end else begin
|
|
concat (binary_data, '000');
|
|
end;
|
|
if IsTrue(latch = 0) then
|
|
begin
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left <= 4) then
|
|
begin
|
|
i := 0;
|
|
while i < bits_left do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
latch := 1;
|
|
end;
|
|
end;
|
|
if IsTrue(latch = 0) then
|
|
begin
|
|
remainder := 8 - (sysutils.strlen (binary_data) mod 8);
|
|
if IsTrue(remainder = 8) then
|
|
begin
|
|
remainder := 0;
|
|
end;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left > 4) then
|
|
begin
|
|
remainder := (bits_left - 4) div 8;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
if IsTrue(i and 1) then begin
|
|
concat (binary_data, '00010001');
|
|
end else begin
|
|
concat (binary_data, '11101100');
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
concat (binary_data, '0000');
|
|
end;
|
|
data_codewords := 3;
|
|
ecc_codewords := 2;
|
|
i := 0;
|
|
while i < (data_codewords - 1) do
|
|
begin
|
|
data_blocks[i] := 0;
|
|
if IsTrue(binary_data[i * 8] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $80;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 1] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $40;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 2] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $20;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 3] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $10;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 4] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $08;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 5] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $04;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 6] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $02;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 7] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $01;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
data_blocks[2] := 0;
|
|
if IsTrue(binary_data[16] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $08;
|
|
end;
|
|
if IsTrue(binary_data[17] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $04;
|
|
end;
|
|
if IsTrue(binary_data[18] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $02;
|
|
end;
|
|
if IsTrue(binary_data[19] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $01;
|
|
end;
|
|
rs_init_gf ($11D);
|
|
rs_init_code (ecc_codewords, 0);
|
|
rs_encode (data_codewords, data_blocks, ecc_blocks);
|
|
rs_free;
|
|
i := 0;
|
|
while i < ecc_codewords do
|
|
begin
|
|
qr_bscan (binary_data, ecc_blocks[ecc_codewords - i - 1], $80);
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
|
|
procedure micro_qr_m2(binary_data: PChar; ecc_mode: Integer);
|
|
var
|
|
latch: Integer;
|
|
i: Integer;
|
|
remainder: Integer;
|
|
bits_left: Integer;
|
|
bits_total: Integer;
|
|
ecc_codewords: Integer;
|
|
data_codewords: Integer;
|
|
ecc_blocks: array [0..7-1] of BYTE;
|
|
data_blocks: array [0..6-1] of BYTE;
|
|
begin
|
|
latch := 0;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
bits_total := 40;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
bits_total := 32;
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left <= 5) then
|
|
begin
|
|
i := 0;
|
|
while i < bits_left do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
latch := 1;
|
|
end else begin
|
|
concat (binary_data, '00000');
|
|
end;
|
|
if IsTrue(latch = 0) then
|
|
begin
|
|
remainder := 8 - (sysutils.strlen (binary_data) mod 8);
|
|
if IsTrue(remainder = 8) then
|
|
begin
|
|
remainder := 0;
|
|
end;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
remainder := bits_left div 8;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, iif (i and 1,'00010001','11101100'));
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
data_codewords := 5;
|
|
ecc_codewords := 5;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
data_codewords := 4;
|
|
ecc_codewords := 6;
|
|
end;
|
|
i := 0;
|
|
while i < data_codewords do
|
|
begin
|
|
data_blocks[i] := 0;
|
|
if IsTrue(binary_data[i * 8] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $80;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 1] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $40;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 2] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $20;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 3] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $10;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 4] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $08;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 5] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $04;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 6] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $02;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 7] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $01;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
rs_init_gf ($11D);
|
|
rs_init_code (ecc_codewords, 0);
|
|
rs_encode (data_codewords, data_blocks, ecc_blocks);
|
|
rs_free;
|
|
i := 0;
|
|
while i < ecc_codewords do
|
|
begin
|
|
qr_bscan (binary_data, ecc_blocks[ecc_codewords - i - 1], $80);
|
|
Inc (i);
|
|
end;
|
|
exit;
|
|
end;
|
|
|
|
procedure micro_qr_m3(binary_data: PChar; ecc_mode: Integer);
|
|
var
|
|
latch: Integer;
|
|
i: Integer;
|
|
remainder: Integer;
|
|
bits_left: Integer;
|
|
bits_total: Integer;
|
|
ecc_codewords: Integer;
|
|
data_codewords: Integer;
|
|
ecc_blocks: array [0..9-1] of BYTE;
|
|
data_blocks: array [0..12-1] of BYTE;
|
|
begin
|
|
latch := 0;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
bits_total := 84;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
bits_total := 68;
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left <= 7) then
|
|
begin
|
|
i := 0;
|
|
while i < bits_left do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
latch := 1;
|
|
end else begin
|
|
concat (binary_data, '0000000');
|
|
end;
|
|
if IsTrue(latch = 0) then
|
|
begin
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left <= 4) then
|
|
begin
|
|
i := 0;
|
|
while i < bits_left do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
latch := 1;
|
|
end;
|
|
end;
|
|
if IsTrue(latch = 0) then
|
|
begin
|
|
remainder := 8 - (sysutils.strlen (binary_data) mod 8);
|
|
if IsTrue(remainder = 8) then
|
|
begin
|
|
remainder := 0;
|
|
end;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left > 4) then
|
|
begin
|
|
remainder := (bits_left - 4) div 8;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, iif (i and 1,'00010001','11101100'));
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
concat (binary_data, '0000');
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
data_codewords := 11;
|
|
ecc_codewords := 6;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
data_codewords := 9;
|
|
ecc_codewords := 8;
|
|
end;
|
|
i := 0;
|
|
while i < (data_codewords - 1) do
|
|
begin
|
|
data_blocks[i] := 0;
|
|
if IsTrue(binary_data[i * 8] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $80;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 1] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $40;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 2] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $20;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 3] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $10;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 4] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $08;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 5] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $04;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 6] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $02;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 7] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $01;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
data_blocks[11] := 0;
|
|
if IsTrue(binary_data[80] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $08;
|
|
end;
|
|
if IsTrue(binary_data[81] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $04;
|
|
end;
|
|
if IsTrue(binary_data[82] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $02;
|
|
end;
|
|
if IsTrue(binary_data[83] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $01;
|
|
end;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
data_blocks[9] := 0;
|
|
if IsTrue(binary_data[64] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $08;
|
|
end;
|
|
if IsTrue(binary_data[65] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $04;
|
|
end;
|
|
if IsTrue(binary_data[66] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $02;
|
|
end;
|
|
if IsTrue(binary_data[67] = '1') then
|
|
begin
|
|
data_blocks[2] := data_blocks[2] + $01;
|
|
end;
|
|
end;
|
|
rs_init_gf ($11D);
|
|
rs_init_code (ecc_codewords, 0);
|
|
rs_encode (data_codewords, data_blocks, ecc_blocks);
|
|
rs_free;
|
|
i := 0;
|
|
while i < ecc_codewords do
|
|
begin
|
|
qr_bscan (binary_data, ecc_blocks[ecc_codewords - i - 1], $80);
|
|
Inc (i);
|
|
end;
|
|
exit;
|
|
end;
|
|
|
|
procedure micro_qr_m4(binary_data: PChar; ecc_mode: Integer);
|
|
var
|
|
latch: Integer;
|
|
i: Integer;
|
|
remainder: Integer;
|
|
bits_left: Integer;
|
|
bits_total: Integer;
|
|
ecc_codewords: Integer;
|
|
data_codewords: Integer;
|
|
ecc_blocks: array [0..15-1] of BYTE;
|
|
data_blocks: array [0..17-1] of BYTE;
|
|
begin
|
|
latch := 0;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
bits_total := 128;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
bits_total := 112;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_Q) then
|
|
begin
|
|
bits_total := 80;
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
if IsTrue(bits_left <= 9) then
|
|
begin
|
|
i := 0;
|
|
while i < bits_left do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
latch := 1;
|
|
end else begin
|
|
concat (binary_data, '000000000');
|
|
end;
|
|
if IsTrue(latch = 0) then
|
|
begin
|
|
remainder := 8 - (sysutils.strlen (binary_data) mod 8);
|
|
if IsTrue(remainder = 8) then
|
|
begin
|
|
remainder := 0;
|
|
end;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, '0');
|
|
Inc (i);
|
|
end;
|
|
bits_left := bits_total - sysutils.strlen (binary_data);
|
|
remainder := bits_left div 8;
|
|
i := 0;
|
|
while i < remainder do
|
|
begin
|
|
concat (binary_data, iif (i and 1,'00010001','11101100'));
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_L) then
|
|
begin
|
|
data_codewords := 16;
|
|
ecc_codewords := 8;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_M) then
|
|
begin
|
|
data_codewords := 14;
|
|
ecc_codewords := 10;
|
|
end;
|
|
if IsTrue(ecc_mode = LEVEL_Q) then
|
|
begin
|
|
data_codewords := 10;
|
|
ecc_codewords := 14;
|
|
end;
|
|
i := 0;
|
|
while i < data_codewords do
|
|
begin
|
|
data_blocks[i] := 0;
|
|
if IsTrue(binary_data[i * 8] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $80;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 1] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $40;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 2] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $20;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 3] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $10;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 4] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $08;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 5] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $04;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 6] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $02;
|
|
end;
|
|
if IsTrue(binary_data[(i * 8) + 7] = '1') then
|
|
begin
|
|
data_blocks[i] := data_blocks[i] + $01;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
rs_init_gf ($11D);
|
|
rs_init_code (ecc_codewords, 0);
|
|
rs_encode (data_codewords, data_blocks, ecc_blocks);
|
|
rs_free;
|
|
i := 0;
|
|
while i < ecc_codewords do
|
|
begin
|
|
qr_bscan (binary_data, ecc_blocks[ecc_codewords - i - 1], $80);
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
|
|
procedure micro_setup_grid(grid: PBYTE; size: Integer);
|
|
var
|
|
toggle: Integer = 1;
|
|
i: Integer = 1;
|
|
begin
|
|
{INITCODE} toggle := 1;
|
|
{INITCODE} i := 1;
|
|
i := 0;
|
|
while i < size do
|
|
begin
|
|
if IsTrue(toggle = 1) then
|
|
begin
|
|
grid[i] := $21;
|
|
grid[(i * size)] := $21;
|
|
toggle := 0;
|
|
end else begin
|
|
grid[i] := $20;
|
|
grid[(i * size)] := $20;
|
|
toggle := 1;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
place_finder (grid, size, 0, 0);
|
|
i := 0;
|
|
while i < 7 do
|
|
begin
|
|
grid[(7 * size) + i] := $10;
|
|
grid[(i * size) + 7] := $10;
|
|
Inc (i);
|
|
end;
|
|
grid[(7 * size) + 7] := $10;
|
|
i := 0;
|
|
while i < 8 do
|
|
begin
|
|
grid[(8 * size) + i] := grid[(8 * size) + i] + $20;
|
|
grid[(i * size) + 8] := grid[(i * size) + 8] + $20;
|
|
Inc (i);
|
|
end;
|
|
grid[(8 * size) + 8] := grid[(8 * size) + 8] + 20;
|
|
end;
|
|
|
|
procedure micro_populate_grid(grid: PBYTE; size: Integer; full_stream: PChar);
|
|
var
|
|
direction: Integer = 1;
|
|
row: Integer = 0;
|
|
y: Integer;
|
|
x: Integer;
|
|
n: Integer;
|
|
i: Integer;
|
|
begin
|
|
{INITCODE} direction := 1;
|
|
{INITCODE} row := 0;
|
|
n := sysutils.strlen (full_stream);
|
|
y := size - 1;
|
|
i := 0;
|
|
repeat
|
|
x := (size - 2) - (row * 2);
|
|
if not IsTrue((grid[(y * size) + (x + 1)] and $F0)) then
|
|
begin
|
|
if IsTrue(full_stream[i] = '1') then
|
|
begin
|
|
grid[(y * size) + (x + 1)] := $01;
|
|
end else begin
|
|
grid[(y * size) + (x + 1)] := $00;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(i < n) then
|
|
begin
|
|
if not IsTrue((grid[(y * size) + x] and $F0)) then
|
|
begin
|
|
if IsTrue(full_stream[i] = '1') then
|
|
begin
|
|
grid[(y * size) + x] := $01;
|
|
end else begin
|
|
grid[(y * size) + x] := $00;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
if IsTrue(direction) then
|
|
begin
|
|
Dec (y);
|
|
end else begin
|
|
Inc (y);
|
|
end;
|
|
if IsTrue(y = 0) then
|
|
begin
|
|
Inc (row);
|
|
y := 1;
|
|
direction := 0;
|
|
end;
|
|
if IsTrue(y = size) then
|
|
begin
|
|
Inc (row);
|
|
y := size - 1;
|
|
direction := 1;
|
|
end;
|
|
until not (i < n);
|
|
end;
|
|
|
|
function micro_evaluate(grid: PBYTE; size: Integer; pattern: Integer): Integer;
|
|
var
|
|
retval: Integer;
|
|
filter: Integer = 0;
|
|
i: Integer = 0;
|
|
sum2: Integer = 0;
|
|
sum1: Integer = 0;
|
|
begin
|
|
{INITCODE} filter := 0;
|
|
{INITCODE} i := 0;
|
|
{INITCODE} sum2 := 0;
|
|
{INITCODE} sum1 := 0;
|
|
case pattern of
|
|
0: filter := $01;
|
|
1: filter := $02;
|
|
2: filter := $04;
|
|
3: filter := $08;
|
|
end;
|
|
sum1 := 0;
|
|
sum2 := 0;
|
|
i := 1;
|
|
while i < size do
|
|
begin
|
|
if IsTrue(grid[(i * size) + size - 1] and filter) then
|
|
begin
|
|
Inc (sum1);
|
|
end;
|
|
if IsTrue(grid[((size - 1) * size) + i] and filter) then
|
|
begin
|
|
Inc (sum2);
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(sum1 <= sum2) then
|
|
begin
|
|
retval := (sum1 * 16) + sum2;
|
|
end else begin
|
|
retval := (sum2 * 16) + sum1;
|
|
end;
|
|
exit (retval);
|
|
end;
|
|
|
|
function micro_apply_bitmask(grid: PBYTE; size: Integer): Integer;
|
|
var
|
|
y: Integer;
|
|
x: Integer;
|
|
p: BYTE;
|
|
value: array [0..8-1] of Integer;
|
|
pattern: Integer;
|
|
best_pattern: Integer;
|
|
best_val: Integer;
|
|
bit: Integer;
|
|
mask: array of BYTE;
|
|
eval: array of BYTE;
|
|
begin
|
|
SetLength(mask,size * size);
|
|
SetLength(eval,size * size);
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
mask[(y * size) + x] := $00;
|
|
if not IsTrue((grid[(y * size) + x] and $F0)) then
|
|
begin
|
|
if IsTrue((y and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $01;
|
|
end;
|
|
if IsTrue((((y div 2) + (x div 3)) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $02;
|
|
end;
|
|
if IsTrue(((((y * x) and 1) + ((y * x) mod 3)) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $04;
|
|
end;
|
|
if IsTrue(((((y + x) and 1) + ((y * x) mod 3)) and 1) = 0) then
|
|
begin
|
|
mask[(y * size) + x] := mask[(y * size) + x] + $08;
|
|
end;
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $01) then
|
|
begin
|
|
p := $FF;
|
|
end else begin
|
|
p := $00;
|
|
end;
|
|
eval[(y * size) + x] := mask[(y * size) + x] xor p;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
pattern := 0;
|
|
while pattern < 8 do
|
|
begin
|
|
value[pattern] := micro_evaluate (@eval[0], size, pattern);
|
|
Inc (pattern);
|
|
end;
|
|
best_pattern := 0;
|
|
best_val := value[0];
|
|
pattern := 1;
|
|
while pattern < 4 do
|
|
begin
|
|
if IsTrue(value[pattern] > best_val) then
|
|
begin
|
|
best_pattern := pattern;
|
|
best_val := value[pattern];
|
|
end;
|
|
Inc (pattern);
|
|
end;
|
|
x := 0;
|
|
while x < size do
|
|
begin
|
|
y := 0;
|
|
while y < size do
|
|
begin
|
|
bit := 0;
|
|
case best_pattern of
|
|
0:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $01) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
1:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $02) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
2:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $04) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
3:
|
|
begin
|
|
if IsTrue(mask[(y * size) + x] and $08) then
|
|
begin
|
|
bit := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
if IsTrue(bit = 1) then
|
|
begin
|
|
if IsTrue(grid[(y * size) + x] and $01) then
|
|
begin
|
|
grid[(y * size) + x] := $00;
|
|
end else begin
|
|
grid[(y * size) + x] := $01;
|
|
end;
|
|
end;
|
|
Inc (y);
|
|
end;
|
|
Inc (x);
|
|
end;
|
|
exit (best_pattern);
|
|
end;
|
|
|
|
function microqr(symbol: PointerTo_zint_symbol; source: PBYTE; length: Integer): Integer;
|
|
var
|
|
size: Integer;
|
|
glyph: Integer;
|
|
j: Integer;
|
|
i: Integer;
|
|
binary_stream: array [0..200-1] of Char;
|
|
full_stream: array [0..200-1] of Char;
|
|
utfdata: array [0..40-1] of Integer;
|
|
jisdata: array [0..40-1] of Integer;
|
|
mode: array [0..40-1] of Char;
|
|
byte_used: Integer = 0;
|
|
alphanum_used: Integer = 0;
|
|
kanji_used: Integer = 0;
|
|
error_number: Integer = 0;
|
|
version_valid: array [0..4-1] of Integer;
|
|
binary_count: array [0..4-1] of Integer;
|
|
version: Integer;
|
|
autoversion: Integer;
|
|
ecc_level: Integer;
|
|
format_full: Integer;
|
|
format: Integer;
|
|
bitmask: Integer;
|
|
a_count: Integer;
|
|
n_count: Integer;
|
|
grid: array of BYTE;
|
|
begin
|
|
{INITCODE} byte_used := 0;
|
|
{INITCODE} alphanum_used := 0;
|
|
{INITCODE} kanji_used := 0;
|
|
{INITCODE} error_number := 0;
|
|
if IsTrue(length > 35) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Input data too long');
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
i := 0;
|
|
while i < 4 do
|
|
begin
|
|
version_valid[i] := 1;
|
|
Inc (i);
|
|
end;
|
|
case symbol^.input_mode of
|
|
DATA_MODE:
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
jisdata[i] := Integer (source[i]);
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
otherwise
|
|
begin
|
|
error_number := utf8toutf16 (symbol, source, utfdata, @length);
|
|
if IsTrue(error_number <> 0) then
|
|
begin
|
|
exit (error_number);
|
|
end;
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(utfdata[i] <= $FF) then
|
|
begin
|
|
jisdata[i] := utfdata[i];
|
|
end else begin
|
|
j := 0;
|
|
glyph := 0;
|
|
repeat
|
|
if IsTrue(sjis_lookup[j * 2] = utfdata[i]) then
|
|
begin
|
|
glyph := sjis_lookup[(j * 2) + 1];
|
|
end;
|
|
Inc (j);
|
|
until not (((j < 6843)) and ((glyph = 0)));
|
|
if IsTrue(glyph = 0) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Invalid character in input data');
|
|
exit (ERROR_INVALID_DATA);
|
|
end;
|
|
jisdata[i] := glyph;
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
end;
|
|
define_mode (mode, jisdata, length, false);
|
|
n_count := 0;
|
|
a_count := 0;
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
if IsTrue(((jisdata[i] >= integer('0'))) and ((jisdata[i] <= integer('9')))) then
|
|
begin
|
|
Inc (n_count);
|
|
end;
|
|
if IsTrue(in_alpha (jisdata[i])) then
|
|
begin
|
|
Inc (a_count);
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
if IsTrue(a_count = length) then
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
mode[i] := 'A';
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
if IsTrue(n_count = length) then
|
|
begin
|
|
i := 0;
|
|
while i < length do
|
|
begin
|
|
mode[i] := 'N';
|
|
Inc (i);
|
|
end;
|
|
end;
|
|
error_number := micro_qr_intermediate (binary_stream, jisdata, mode, length, @kanji_used, @alphanum_used, @byte_used);
|
|
if IsTrue(error_number <> 0) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Input data too long');
|
|
exit (error_number);
|
|
end;
|
|
get_bitlength (binary_count, binary_stream);
|
|
if IsTrue(byte_used) then
|
|
begin
|
|
version_valid[0] := 0;
|
|
version_valid[1] := 0;
|
|
end;
|
|
if IsTrue(alphanum_used) then
|
|
begin
|
|
version_valid[0] := 0;
|
|
end;
|
|
if IsTrue(kanji_used) then
|
|
begin
|
|
version_valid[0] := 0;
|
|
version_valid[1] := 0;
|
|
end;
|
|
if IsTrue(binary_count[0] > 20) then
|
|
begin
|
|
version_valid[0] := 0;
|
|
end;
|
|
if IsTrue(binary_count[1] > 40) then
|
|
begin
|
|
version_valid[1] := 0;
|
|
end;
|
|
if IsTrue(binary_count[2] > 84) then
|
|
begin
|
|
version_valid[2] := 0;
|
|
end;
|
|
if IsTrue(binary_count[3] > 128) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Input data too long');
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
ecc_level := LEVEL_L;
|
|
if IsTrue(((symbol^.option_1 >= 1)) and ((symbol^.option_2 <= 4))) then
|
|
begin
|
|
ecc_level := symbol^.option_1;
|
|
end;
|
|
if IsTrue(ecc_level = LEVEL_H) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Error correction level H not available');
|
|
exit (ERROR_INVALID_OPTION);
|
|
end;
|
|
if IsTrue(ecc_level = LEVEL_Q) then
|
|
begin
|
|
version_valid[0] := 0;
|
|
version_valid[1] := 0;
|
|
version_valid[2] := 0;
|
|
if IsTrue(binary_count[3] > 80) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Input data too long');
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
end;
|
|
if IsTrue(ecc_level = LEVEL_M) then
|
|
begin
|
|
version_valid[0] := 0;
|
|
if IsTrue(binary_count[1] > 32) then
|
|
begin
|
|
version_valid[1] := 0;
|
|
end;
|
|
if IsTrue(binary_count[2] > 68) then
|
|
begin
|
|
version_valid[2] := 0;
|
|
end;
|
|
if IsTrue(binary_count[3] > 112) then
|
|
begin
|
|
strcpy (symbol^.errtxt, 'Input data too long');
|
|
exit (ERROR_TOO_LONG);
|
|
end;
|
|
end;
|
|
autoversion := 3;
|
|
if IsTrue(version_valid[2]) then
|
|
begin
|
|
autoversion := 2;
|
|
end;
|
|
if IsTrue(version_valid[1]) then
|
|
begin
|
|
autoversion := 1;
|
|
end;
|
|
if IsTrue(version_valid[0]) then
|
|
begin
|
|
autoversion := 0;
|
|
end;
|
|
version := autoversion;
|
|
if IsTrue(((symbol^.option_2 >= 1)) and ((symbol^.option_2 <= 4))) then
|
|
begin
|
|
if IsTrue(symbol^.option_2 >= autoversion) then
|
|
begin
|
|
version := symbol^.option_2;
|
|
end;
|
|
end;
|
|
if IsTrue(version = 3) then
|
|
begin
|
|
if IsTrue(binary_count[3] <= 112) then
|
|
begin
|
|
ecc_level := LEVEL_M;
|
|
end;
|
|
if IsTrue(binary_count[3] <= 80) then
|
|
begin
|
|
ecc_level := LEVEL_Q;
|
|
end;
|
|
end;
|
|
if IsTrue(version = 2) then
|
|
begin
|
|
if IsTrue(binary_count[2] <= 68) then
|
|
begin
|
|
ecc_level := LEVEL_M;
|
|
end;
|
|
end;
|
|
if IsTrue(version = 1) then
|
|
begin
|
|
if IsTrue(binary_count[1] <= 32) then
|
|
begin
|
|
ecc_level := LEVEL_M;
|
|
end;
|
|
end;
|
|
full_stream[0]:=#0;
|
|
strcpy (full_stream, '');
|
|
microqr_expand_binary (binary_stream, full_stream, version);
|
|
case version of
|
|
0: micro_qr_m1 (full_stream);
|
|
1: micro_qr_m2 (full_stream, ecc_level);
|
|
2: micro_qr_m3 (full_stream, ecc_level);
|
|
3: micro_qr_m4 (full_stream, ecc_level);
|
|
end;
|
|
size := micro_qr_sizes[version];
|
|
SetLength(grid,size * size);
|
|
i := 0;
|
|
while i < size do
|
|
begin
|
|
j := 0;
|
|
while j < size do
|
|
begin
|
|
grid[(i * size) + j] := 0;
|
|
Inc (j);
|
|
end;
|
|
Inc (i);
|
|
end;
|
|
micro_setup_grid (@grid[0], size);
|
|
micro_populate_grid (@grid[0], size, full_stream);
|
|
bitmask := micro_apply_bitmask (@grid[0], size);
|
|
format := 0;
|
|
case version of
|
|
1:
|
|
begin
|
|
case ecc_level of
|
|
1: format := 1;
|
|
2: format := 2;
|
|
end;
|
|
end;
|
|
2:
|
|
begin
|
|
case ecc_level of
|
|
1: format := 3;
|
|
2: format := 4;
|
|
end;
|
|
end;
|
|
3:
|
|
begin
|
|
case ecc_level of
|
|
1: format := 5;
|
|
2: format := 6;
|
|
3: format := 7;
|
|
end;
|
|
end;
|
|
end;
|
|
format_full := qr_annex_c1[(format shl 2) + bitmask];
|
|
if IsTrue(format_full and $4000) then
|
|
begin
|
|
grid[(8 * size) + 1] := grid[(8 * size) + 1] + $01;
|
|
end;
|
|
if IsTrue(format_full and $2000) then
|
|
begin
|
|
grid[(8 * size) + 2] := grid[(8 * size) + 2] + $01;
|
|
end;
|
|
if IsTrue(format_full and $1000) then
|
|
begin
|
|
grid[(8 * size) + 3] := grid[(8 * size) + 3] + $01;
|
|
end;
|
|
if IsTrue(format_full and $800) then
|
|
begin
|
|
grid[(8 * size) + 4] := grid[(8 * size) + 4] + $01;
|
|
end;
|
|
if IsTrue(format_full and $400) then
|
|
begin
|
|
grid[(8 * size) + 5] := grid[(8 * size) + 5] + $01;
|
|
end;
|
|
if IsTrue(format_full and $200) then
|
|
begin
|
|
grid[(8 * size) + 6] := grid[(8 * size) + 6] + $01;
|
|
end;
|
|
if IsTrue(format_full and $100) then
|
|
begin
|
|
grid[(8 * size) + 7] := grid[(8 * size) + 7] + $01;
|
|
end;
|
|
if IsTrue(format_full and $80) then
|
|
begin
|
|
grid[(8 * size) + 8] := grid[(8 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $40) then
|
|
begin
|
|
grid[(7 * size) + 8] := grid[(7 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $20) then
|
|
begin
|
|
grid[(6 * size) + 8] := grid[(6 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $10) then
|
|
begin
|
|
grid[(5 * size) + 8] := grid[(5 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $08) then
|
|
begin
|
|
grid[(4 * size) + 8] := grid[(4 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $04) then
|
|
begin
|
|
grid[(3 * size) + 8] := grid[(3 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $02) then
|
|
begin
|
|
grid[(2 * size) + 8] := grid[(2 * size) + 8] + $01;
|
|
end;
|
|
if IsTrue(format_full and $01) then
|
|
begin
|
|
grid[(1 * size) + 8] := grid[(1 * size) + 8] + $01;
|
|
end;
|
|
symbol^.width := size;
|
|
symbol^.rows := size;
|
|
i := 0;
|
|
while i < size do
|
|
begin
|
|
j := 0;
|
|
while j < size do
|
|
begin
|
|
if IsTrue(grid[(i * size) + j] and $01) then
|
|
begin
|
|
set_module (symbol, i, j);
|
|
end;
|
|
Inc (j);
|
|
end;
|
|
symbol^.row_height[i] := 1;
|
|
Inc (i);
|
|
end;
|
|
exit (0);
|
|
end;
|
|
|
|
end.
|