この記事は【Kuin Advent Calendar 2016】の9日目の記事です。
【記事中で紹介しているコードについて】
コンパイルが通らない場合など、不具合があれば、@tatt61880まで連絡いただけると助かります。よろしくお願いいたします。
{
文字列からQRコードを作成します。
下記のサイトの QR_Image_Source.zip を参考にさせていただきました。
コメントにC++のコードとの対応関係を書いている場合があります。
ソースコードを公開してくださっていることを感謝いたします。
http://www.psytec.co.jp/freesoft/02/
上記のライセンスに関しては、
・本ソフトウェアの配布は自由です。
・ソースコードの一部または全部の使用、及び改変しての使用を認めます。
・ソースコードを使用する際に弊社に許可を求める必要はなく、また弊社名の記載も不要です。
とのことです。
QRコードは株式会社デンソーウェーブの登録商標です。
http://www.qrcode.com/faq.html
}
func main()
var data: []bit8 :: #[0]bit8
const inputData: []char :: "Hello, QR!! (Created by Kuin)"
for i(0, ^inputData - 1)
do data :~ [inputData[i] $ bit8]
end for
var qrEncode: @QrEncode :: #@QrEncode
do qrEncode.encodeData(@QR_LEVEL_H, 0, false, -1, data, 0)
const size: int :: 220
const margin: int :: 10
const wndSize: int :: size + 2 * margin
var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, wndSize, wndSize, "Hello, QR!")
var drawMain: wnd@Draw :: wnd@makeDraw(wndMain, 0, 0, wndSize, wndSize, %scale, %scale, false)
while(wnd@act())
do draw@rect(0.0, 0.0, wndSize $ float, wndSize $ float, 0xFF6188FF)
do qrEncode.draw(margin $ float, margin $float, size $ float, false)
do draw@render(30)
end while
end func
const x00: bit8 :: 0x00b8 {'\x00'}
const x11: bit8 :: 0x11b8 {'\x11'}
const x20: bit8 :: 0x20b8 {'\x20'}
const x30: bit8 :: 0x30b8 {'\x30'}
{誤り訂正レベル}
const QR_LEVEL_L: int :: 0
const QR_LEVEL_M: int :: 1
const QR_LEVEL_Q: int :: 2
const QR_LEVEL_H: int :: 3
{データモード}
const QR_MODE_NUMERAL: bit8 :: 0b8
const QR_MODE_ALPHABET: bit8 :: 1b8
const QR_MODE_8BIT: bit8 :: 2b8
const QR_MODE_KANJI: bit8 :: 3b8
{バージョン(型番)グループ}
const QR_VRESION_S: int :: 0 { 1 ~ 9}
const QR_VRESION_M: int :: 1 {10 ~ 26}
const QR_VRESION_L: int :: 2 {27 ~ 40}
const MAX_ALLCODEWORD: int :: 3706 {総コードワード数最大値}
const MAX_DATACODEWORD: int :: 2956 {データコードワード最大値(バージョン40-L)}
const MAX_CODEBLOCK: int :: 153 {ブロックデータコードワード数最大値(RSコードワードを含む)}
const MAX_MODULESIZE: int :: 177 {一辺モジュール数最大値}
{ビットマップ描画時マージン}
const QR_MARGIN: int :: 4
{QRコードバージョン(型番)関連情報}
{struct QR_VERSIONINFO}
class QrVersionInfo()
var nVersionNo: int {バージョン(型番)番号(1~40)}
+var ncAllCodeWord: int {総コードワード数}
{以下配列添字は誤り訂正率(0 = L, 1 = M, 2 = Q, 3 = H)}
+var ncDataCodeWord: []int {データコードワード数(総コードワード数 - RSコードワード数)}
+var ncAlignPoint: int {アライメントパターン座標数}
+var nAlignPoint: []int {アライメントパターン中心座標}
+var rsBlockInfo1: []RsBlockInfo {RSブロック情報(1)}
+var rsBlockInfo2: []RsBlockInfo {RSブロック情報(2)}
+func init(nVersionNo: int, ncAllCodeWord: int, ncDataCodeWord: []int, ncAlignPoint: int, nAlignPoint: []int, rsBlockInfo1: []int, rsBlockInfo2: []int): @QrVersionInfo
do me.nVersionNo :: nVersionNo
do me.ncAllCodeWord :: ncAllCodeWord
do me.ncDataCodeWord :: #[4]int
do me.ncDataCodeWord :: ##ncDataCodeWord
do me.ncAlignPoint :: ncAlignPoint
do me.nAlignPoint :: #[6]int
do me.nAlignPoint :: ##nAlignPoint
do me.rsBlockInfo1 :: #[4]RsBlockInfo
do me.rsBlockInfo2 :: #[4]RsBlockInfo
for i(0, 3)
do me.rsBlockInfo1[i] :: (#RsBlockInfo).init(rsBlockInfo1, 3 * i)
do me.rsBlockInfo2[i] :: (#RsBlockInfo).init(rsBlockInfo2, 3 * i)
end for
ret me
end func
{struct RS_BLOCKINFO}
class RsBlockInfo()
+var ncRSBlock: int {RSブロック数}
+var ncBlockAllCodeWord: int {ブロック内コードワード数}
+var ncBlockDataCodeWord: int {データコードワード数(コードワード数 - RSコードワード数)}
+func init(rsBlockInfo: []int, n: int): RsBlockInfo
do me.ncRSBlock :: rsBlockInfo[n]
do me.ncBlockAllCodeWord :: rsBlockInfo[n + 1]
do me.ncBlockDataCodeWord :: rsBlockInfo[n + 2]
ret me
end func
end class
end class
var qrVersionInfo: []@QrVersionInfo
var byExpToInt: []bit8
var byIntToExp: []bit8
var byRSExp: [][]int
var nIndicatorLenNumeral: []int
var nIndicatorLenAlphabet: []int
var nIndicatorLen8Bit: []int
var nIndicatorLenKanji: []int
{static変数の初期化用}
var initializeFlag: bool
func initialize()
{QRコードバージョン(型番)情報}
do @qrVersionInfo :: #[41]@QrVersionInfo
do @qrVersionInfo[ 1] :: (#@QrVersionInfo).init( 1, 26,[ 19, 16, 13, 9],0,[ 0, 0, 0, 0, 0, 0],[ 1, 26, 19, 1,26,16, 1,26,13, 1,26, 9],[ 0, 0, 0, 0,0 , 0, 0, 0, 0, 0, 0, 0])
do @qrVersionInfo[ 2] :: (#@QrVersionInfo).init( 2, 44,[ 34, 28, 22, 16],1,[18, 0, 0, 0, 0, 0],[ 1, 44, 34, 1,44,28, 1,44,22, 1,44,16],[ 0, 0, 0, 0,0 , 0, 0, 0, 0, 0, 0, 0])
do @qrVersionInfo[ 3] :: (#@QrVersionInfo).init( 3, 70,[ 55, 44, 34, 26],1,[22, 0, 0, 0, 0, 0],[ 1, 70, 55, 1,70,44, 2,35,17, 2,35,13],[ 0, 0, 0, 0,0 , 0, 0, 0, 0, 0, 0, 0])
do @qrVersionInfo[ 4] :: (#@QrVersionInfo).init( 4, 100,[ 80, 64, 48, 36],1,[26, 0, 0, 0, 0, 0],[ 1,100, 80, 2,50,32, 2,50,24, 4,25, 9],[ 0, 0, 0, 0,0 , 0, 0, 0, 0, 0, 0, 0])
do @qrVersionInfo[ 5] :: (#@QrVersionInfo).init( 5, 134,[ 108, 86, 62, 46],1,[30, 0, 0, 0, 0, 0],[ 1,134,108, 2,67,43, 2,33,15, 2,33,11],[ 0, 0, 0, 0,0 , 0, 2,34,16, 2,34,12])
do @qrVersionInfo[ 6] :: (#@QrVersionInfo).init( 6, 172,[ 136, 108, 76, 60],1,[34, 0, 0, 0, 0, 0],[ 2, 86, 68, 4,43,27, 4,43,19, 4,43,15],[ 0, 0, 0, 0,0 , 0, 0, 0, 0, 0, 0, 0])
do @qrVersionInfo[ 7] :: (#@QrVersionInfo).init( 7, 196,[ 156, 124, 88, 66],2,[22,38, 0, 0, 0, 0],[ 2, 98, 78, 4,49,31, 2,32,14, 4,39,13],[ 0, 0, 0, 0,0 , 0, 4,33,15, 1,40,14])
do @qrVersionInfo[ 8] :: (#@QrVersionInfo).init( 8, 242,[ 194, 154, 110, 86],2,[24,42, 0, 0, 0, 0],[ 2,121, 97, 2,60,38, 4,40,18, 4,40,14],[ 0, 0, 0, 2,61,39, 2,41,19, 2,41,15])
do @qrVersionInfo[ 9] :: (#@QrVersionInfo).init( 9, 292,[ 232, 182, 132, 100],2,[26,46, 0, 0, 0, 0],[ 2,146,116, 3,58,36, 4,36,16, 4,36,12],[ 0, 0, 0, 2,59,37, 4,37,17, 4,37,13])
do @qrVersionInfo[10] :: (#@QrVersionInfo).init(10, 346,[ 274, 216, 154, 122],2,[28,50, 0, 0, 0, 0],[ 2, 86, 68, 4,69,43, 6,43,19, 6,43,15],[ 2, 87, 69, 1,70,44, 2,44,20, 2,44,16])
do @qrVersionInfo[11] :: (#@QrVersionInfo).init(11, 404,[ 324, 254, 180, 140],2,[30,54, 0, 0, 0, 0],[ 4,101, 81, 1,80,50, 4,50,22, 3,36,12],[ 0, 0, 0, 4,81,51, 4,51,23, 8,37,13])
do @qrVersionInfo[12] :: (#@QrVersionInfo).init(12, 466,[ 370, 290, 206, 158],2,[32,58, 0, 0, 0, 0],[ 2,116, 92, 6,58,36, 4,46,20, 7,42,14],[ 2,117, 93, 2,59,37, 6,47,21, 4,43,15])
do @qrVersionInfo[13] :: (#@QrVersionInfo).init(13, 532,[ 428, 334, 244, 180],2,[34,62, 0, 0, 0, 0],[ 4,133,107, 8,59,37, 8,44,20,12,33,11],[ 0, 0, 0, 1,60,38, 4,45,21, 4,34,12])
do @qrVersionInfo[14] :: (#@QrVersionInfo).init(14, 581,[ 461, 365, 261, 197],3,[26,46,66, 0, 0, 0],[ 3,145,115, 4,64,40,11,36,16,11,36,12],[ 1,146,116, 5,65,41, 5,37,17, 5,37,13])
do @qrVersionInfo[15] :: (#@QrVersionInfo).init(15, 655,[ 523, 415, 295, 223],3,[26,48,70, 0, 0, 0],[ 5,109, 87, 5,65,41, 5,54,24,11,36,12],[ 1,110, 88, 5,66,42, 7,55,25, 7,37,13])
do @qrVersionInfo[16] :: (#@QrVersionInfo).init(16, 733,[ 589, 453, 325, 253],3,[26,50,74, 0, 0, 0],[ 5,122, 98, 7,73,45,15,43,19, 3,45,15],[ 1,123, 99, 3,74,46, 2,44,20,13,46,16])
do @qrVersionInfo[17] :: (#@QrVersionInfo).init(17, 815,[ 647, 507, 367, 283],3,[30,54,78, 0, 0, 0],[ 1,135,107,10,74,46, 1,50,22, 2,42,14],[ 5,136,108, 1,75,47,15,51,23,17,43,15])
do @qrVersionInfo[18] :: (#@QrVersionInfo).init(18, 901,[ 721, 563, 397, 313],3,[30,56,82, 0, 0, 0],[ 5,150,120, 9,69,43,17,50,22, 2,42,14],[ 1,151,121, 4,70,44, 1,51,23,19,43,15])
do @qrVersionInfo[19] :: (#@QrVersionInfo).init(19, 991,[ 795, 627, 445, 341],3,[30,58,86, 0, 0, 0],[ 3,141,113, 3,70,44,17,47,21, 9,39,13],[ 4,142,114,11,71,45, 4,48,22,16,40,14])
do @qrVersionInfo[20] :: (#@QrVersionInfo).init(20,1085,[ 861, 669, 485, 385],3,[34,62,90, 0, 0, 0],[ 3,135,107, 3,67,41,15,54,24,15,43,15],[ 5,136,108,13,68,42, 5,55,25,10,44,16])
do @qrVersionInfo[21] :: (#@QrVersionInfo).init(21,1156,[ 932, 714, 512, 406],4,[28,50,72, 94, 0, 0],[ 4,144,116,17,68,42,17,50,22,19,46,16],[ 4,145,117, 0, 0, 0, 6,51,23, 6,47,17])
do @qrVersionInfo[22] :: (#@QrVersionInfo).init(22,1258,[1006, 782, 568, 442],4,[26,50,74, 98, 0, 0],[ 2,139,111,17,74,46, 7,54,24,34,37,13],[ 7,140,112, 0, 0, 0,16,55,25, 0, 0, 0])
do @qrVersionInfo[23] :: (#@QrVersionInfo).init(23,1364,[1094, 860, 614, 464],4,[30,54,78,102, 0, 0],[ 4,151,121, 4,75,47,11,54,24,16,45,15],[ 5,152,122,14,76,48,14,55,25,14,46,16])
do @qrVersionInfo[24] :: (#@QrVersionInfo).init(24,1474,[1174, 914, 664, 514],4,[28,54,80,106, 0, 0],[ 6,147,117, 6,73,45,11,54,24,30,46,16],[ 4,148,118,14,74,46,16,55,25, 2,47,17])
do @qrVersionInfo[25] :: (#@QrVersionInfo).init(25,1588,[1276,1000, 718, 538],4,[32,58,84,110, 0, 0],[ 8,132,106, 8,75,47, 7,54,24,22,45,15],[ 4,133,107,13,76,48,22,55,25,13,46,16])
do @qrVersionInfo[26] :: (#@QrVersionInfo).init(26,1706,[1370,1062, 754, 596],4,[30,58,86,114, 0, 0],[10,142,114,19,74,46,28,50,22,33,46,16],[ 2,143,115, 4,75,47, 6,51,23, 4,47,17])
do @qrVersionInfo[27] :: (#@QrVersionInfo).init(27,1828,[1468,1128, 808, 628],4,[34,62,90,118, 0, 0],[ 8,152,122,22,73,45, 8,53,23,12,45,15],[ 4,153,123, 3,74,46,26,54,24,28,46,16])
do @qrVersionInfo[28] :: (#@QrVersionInfo).init(28,1921,[1531,1193, 871, 661],5,[26,50,74, 98,122, 0],[ 3,147,117, 3,73,45, 4,54,24,11,45,15],[10,148,118,23,74,46,31,55,25,31,46,16])
do @qrVersionInfo[29] :: (#@QrVersionInfo).init(29,2051,[1631,1267, 911, 701],5,[30,54,78,102,126, 0],[ 7,146,116,21,73,45, 1,53,23,19,45,15],[ 7,147,117, 7,74,46,37,54,24,26,46,16])
do @qrVersionInfo[30] :: (#@QrVersionInfo).init(30,2185,[1735,1373, 985, 745],5,[26,52,78,104,130, 0],[ 5,145,115,19,75,47,15,54,24,23,45,15],[10,146,116,10,76,48,25,55,25,25,46,16])
do @qrVersionInfo[31] :: (#@QrVersionInfo).init(31,2323,[1843,1455,1033, 793],5,[30,56,82,108,134, 0],[13,145,115, 2,74,46,42,54,24,23,45,15],[ 3,146,116,29,75,47, 1,55,25,28,46,16])
do @qrVersionInfo[32] :: (#@QrVersionInfo).init(32,2465,[1955,1541,1115, 845],5,[34,60,86,112,138, 0],[17,145,115,10,74,46,10,54,24,19,45,15],[ 0, 0, 0,23,75,47,35,55,25,35,46,16])
do @qrVersionInfo[33] :: (#@QrVersionInfo).init(33,2611,[2071,1631,1171, 901],5,[30,58,86,114,142, 0],[17,145,115,14,74,46,29,54,24,11,45,15],[ 1,146,116,21,75,47,19,55,25,46,46,16])
do @qrVersionInfo[34] :: (#@QrVersionInfo).init(34,2761,[2191,1725,1231, 961],5,[34,62,90,118,146, 0],[13,145,115,14,74,46,44,54,24,59,46,16],[ 6,146,116,23,75,47, 7,55,25, 1,47,17])
do @qrVersionInfo[35] :: (#@QrVersionInfo).init(35,2876,[2306,1812,1286, 986],6,[30,54,78,102,126,150],[12,151,121,12,75,47,39,54,24,22,45,15],[ 7,152,122,26,76,48,14,55,25,41,46,16])
do @qrVersionInfo[36] :: (#@QrVersionInfo).init(36,3034,[2434,1914,1354,1054],6,[24,50,76,102,128,154],[ 6,151,121, 6,75,47,46,54,24, 2,45,15],[14,152,122,34,76,48,10,55,25,64,46,16])
do @qrVersionInfo[37] :: (#@QrVersionInfo).init(37,3196,[2566,1992,1426,1096],6,[28,54,80,106,132,158],[17,152,122,29,74,46,49,54,24,24,45,15],[ 4,153,123,14,75,47,10,55,25,46,46,16])
do @qrVersionInfo[38] :: (#@QrVersionInfo).init(38,3362,[2702,2102,1502,1142],6,[32,58,84,110,136,162],[ 4,152,122,13,74,46,48,54,24,42,45,15],[18,153,123,32,75,47,14,55,25,32,46,16])
do @qrVersionInfo[39] :: (#@QrVersionInfo).init(39,3532,[2812,2216,1582,1222],6,[26,54,82,110,138,166],[20,147,117,40,75,47,43,54,24,10,45,15],[ 4,148,118, 7,76,48,22,55,25,67,46,16])
do @qrVersionInfo[40] :: (#@QrVersionInfo).init(40,3706,[2956,2334,1666,1276],6,[30,58,86,114,142,170],[19,148,118,18,75,47,34,54,24,20,45,15],[ 6,149,119,31,76,48,34,55,25,61,46,16])
{GF(2^8)α指数→整数変換テーブル}
do @byExpToInt :: [1b8, 2b8, 4b8, 8b8, 16b8, 32b8, 64b8, 128b8, 29b8, 58b8, 116b8, 232b8, 205b8, 135b8, 19b8, 38b8,
| 76b8, 152b8, 45b8, 90b8, 180b8, 117b8, 234b8, 201b8, 143b8, 3b8, 6b8, 12b8, 24b8, 48b8, 96b8, 192b8,
| 157b8, 39b8, 78b8, 156b8, 37b8, 74b8, 148b8, 53b8, 106b8, 212b8, 181b8, 119b8, 238b8, 193b8, 159b8, 35b8,
| 70b8, 140b8, 5b8, 10b8, 20b8, 40b8, 80b8, 160b8, 93b8, 186b8, 105b8, 210b8, 185b8, 111b8, 222b8, 161b8,
| 95b8, 190b8, 97b8, 194b8, 153b8, 47b8, 94b8, 188b8, 101b8, 202b8, 137b8, 15b8, 30b8, 60b8, 120b8, 240b8,
| 253b8, 231b8, 211b8, 187b8, 107b8, 214b8, 177b8, 127b8, 254b8, 225b8, 223b8, 163b8, 91b8, 182b8, 113b8, 226b8,
| 217b8, 175b8, 67b8, 134b8, 17b8, 34b8, 68b8, 136b8, 13b8, 26b8, 52b8, 104b8, 208b8, 189b8, 103b8, 206b8,
| 129b8, 31b8, 62b8, 124b8, 248b8, 237b8, 199b8, 147b8, 59b8, 118b8, 236b8, 197b8, 151b8, 51b8, 102b8, 204b8,
| 133b8, 23b8, 46b8, 92b8, 184b8, 109b8, 218b8, 169b8, 79b8, 158b8, 33b8, 66b8, 132b8, 21b8, 42b8, 84b8,
| 168b8, 77b8, 154b8, 41b8, 82b8, 164b8, 85b8, 170b8, 73b8, 146b8, 57b8, 114b8, 228b8, 213b8, 183b8, 115b8,
| 230b8, 209b8, 191b8, 99b8, 198b8, 145b8, 63b8, 126b8, 252b8, 229b8, 215b8, 179b8, 123b8, 246b8, 241b8, 255b8,
| 227b8, 219b8, 171b8, 75b8, 150b8, 49b8, 98b8, 196b8, 149b8, 55b8, 110b8, 220b8, 165b8, 87b8, 174b8, 65b8,
| 130b8, 25b8, 50b8, 100b8, 200b8, 141b8, 7b8, 14b8, 28b8, 56b8, 112b8, 224b8, 221b8, 167b8, 83b8, 166b8,
| 81b8, 162b8, 89b8, 178b8, 121b8, 242b8, 249b8, 239b8, 195b8, 155b8, 43b8, 86b8, 172b8, 69b8, 138b8, 9b8,
| 18b8, 36b8, 72b8, 144b8, 61b8, 122b8, 244b8, 245b8, 247b8, 243b8, 251b8, 235b8, 203b8, 139b8, 11b8, 22b8,
| 44b8, 88b8, 176b8, 125b8, 250b8, 233b8, 207b8, 131b8, 27b8, 54b8, 108b8, 216b8, 173b8, 71b8, 142b8, 1b8]
{GF(2^8)α整数→指数変換テーブル}
do @byIntToExp :: [0b8, 0b8, 1b8, 25b8, 2b8, 50b8, 26b8, 198b8, 3b8, 223b8, 51b8, 238b8, 27b8, 104b8, 199b8, 75b8,
| 4b8, 100b8, 224b8, 14b8, 52b8, 141b8, 239b8, 129b8, 28b8, 193b8, 105b8, 248b8, 200b8, 8b8, 76b8, 113b8,
| 5b8, 138b8, 101b8, 47b8, 225b8, 36b8, 15b8, 33b8, 53b8, 147b8, 142b8, 218b8, 240b8, 18b8, 130b8, 69b8,
| 29b8, 181b8, 194b8, 125b8, 106b8, 39b8, 249b8, 185b8, 201b8, 154b8, 9b8, 120b8, 77b8, 228b8, 114b8, 166b8,
| 6b8, 191b8, 139b8, 98b8, 102b8, 221b8, 48b8, 253b8, 226b8, 152b8, 37b8, 179b8, 16b8, 145b8, 34b8, 136b8,
| 54b8, 208b8, 148b8, 206b8, 143b8, 150b8, 219b8, 189b8, 241b8, 210b8, 19b8, 92b8, 131b8, 56b8, 70b8, 64b8,
| 30b8, 66b8, 182b8, 163b8, 195b8, 72b8, 126b8, 110b8, 107b8, 58b8, 40b8, 84b8, 250b8, 133b8, 186b8, 61b8,
| 202b8, 94b8, 155b8, 159b8, 10b8, 21b8, 121b8, 43b8, 78b8, 212b8, 229b8, 172b8, 115b8, 243b8, 167b8, 87b8,
| 7b8, 112b8, 192b8, 247b8, 140b8, 128b8, 99b8, 13b8, 103b8, 74b8, 222b8, 237b8, 49b8, 197b8, 254b8, 24b8,
| 227b8, 165b8, 153b8, 119b8, 38b8, 184b8, 180b8, 124b8, 17b8, 68b8, 146b8, 217b8, 35b8, 32b8, 137b8, 46b8,
| 55b8, 63b8, 209b8, 91b8, 149b8, 188b8, 207b8, 205b8, 144b8, 135b8, 151b8, 178b8, 220b8, 252b8, 190b8, 97b8,
| 242b8, 86b8, 211b8, 171b8, 20b8, 42b8, 93b8, 158b8, 132b8, 60b8, 57b8, 83b8, 71b8, 109b8, 65b8, 162b8,
| 31b8, 45b8, 67b8, 216b8, 183b8, 123b8, 164b8, 118b8, 196b8, 23b8, 73b8, 236b8, 127b8, 12b8, 111b8, 246b8,
| 108b8, 161b8, 59b8, 82b8, 41b8, 157b8, 85b8, 170b8, 251b8, 96b8, 134b8, 177b8, 187b8, 204b8, 62b8, 90b8,
| 203b8, 89b8, 95b8, 176b8, 156b8, 169b8, 160b8, 81b8, 11b8, 245b8, 22b8, 235b8, 122b8, 117b8, 44b8, 215b8,
| 79b8, 174b8, 213b8, 233b8, 230b8, 231b8, 173b8, 232b8, 116b8, 214b8, 244b8, 234b8, 168b8, 80b8, 88b8, 175b8]
{誤り訂正生成多項式α係数}
var byRSExp7 : []int :: [ 87,229,146,149,238,102, 21]
var byRSExp10: []int :: [251, 67, 46, 61,118, 70, 64, 94, 32, 45]
var byRSExp13: []int :: [ 74,152,176,100, 86,100,106,104,130,218,206,140, 78]
var byRSExp15: []int :: [ 8,183, 61, 91,202, 37, 51, 58, 58,237,140,124, 5, 99,105]
var byRSExp16: []int :: [120,104,107,109,102,161, 76, 3, 91,191,147,169,182,194,225,120]
var byRSExp17: []int :: [ 43,139,206, 78, 43,239,123,206,214,147, 24, 99,150, 39,243,163,136]
var byRSExp18: []int :: [215,234,158, 94,184, 97,118,170, 79,187,152,148,252,179, 5, 98, 96,153]
var byRSExp20: []int :: [ 17, 60, 79, 50, 61,163, 26,187,202,180,221,225, 83,239,156,164,212,212,188,190]
var byRSExp22: []int :: [210,171,247,242, 93,230, 14,109,221, 53,200, 74, 8,172, 98, 80,219,134,160,105,165,231]
var byRSExp24: []int :: [229,121,135, 48,211,117,251,126,159,180,169,152,192,226,228,218,111, 0,117,232, 87, 96,227, 21]
var byRSExp26: []int :: [173,125,158, 2,103,182,118, 17,145,201,111, 28,165, 53,161, 21,245,142, 13,102, 48,227,153,145,218, 70]
var byRSExp28: []int :: [168,223,200,104,224,234,108,180,110,190,195,147,205, 27,232,201, 21, 43,245, 87, 42,195,212,119,242, 37, 9,123]
var byRSExp30: []int :: [ 41,173,145,152,216, 31,179,182, 50, 48,110, 86,239, 96,222,125, 42,173,226,193,224,130,156, 37,251,216,238, 40,192,180]
var byRSExp32: []int :: [ 10, 6,106,190,249,167, 4, 67,209,138,138, 32,242,123, 89, 27,120,185, 80,156, 38, 69,171, 60, 28,222, 80, 52,254,185,220,241]
var byRSExp34: []int :: [111, 77,146, 94, 26, 21,108, 19,105, 94,113,193, 86,140,163,125, 58,158,229,239,218,103, 56, 70,114, 61,183,129,167, 13, 98, 62,129, 51]
var byRSExp36: []int :: [200,183, 98, 16,172, 31,246,234, 60,152,115, 0,167,152,113,248,238,107, 18, 63,218, 37, 87,210,105,177,120, 74,121,196,117,251,113,233, 30,120]
var byRSExp38: []int :: [159, 34, 38,228,230, 59,243, 95, 49,218,176,164, 20, 65, 45,111, 39, 81, 49,118,113,222,193,250,242,168,217, 41,164,247,177, 30,238, 18,120,153, 60,193]
var byRSExp40: []int :: [ 59,116, 79,161,252, 98,128,205,128,161,247, 57,163, 56,235,106, 53, 26,187,174,226,104,170, 7,175, 35,181,114, 88, 41, 47,163,125,134, 72, 20,232, 53, 35, 15]
var byRSExp42: []int :: [250,103,221,230, 25, 18,137,231, 0, 3, 58,242,221,191,110, 84,230, 8,188,106, 96,147, 15,131,139, 34,101,223, 39,101,213,199,237,254,201,123,171,162,194,117, 50, 96]
var byRSExp44: []int :: [190, 7, 61,121, 71,246, 69, 55,168,188, 89,243,191, 25, 72,123, 9,145, 14,247, 1,238, 44, 78,143, 62,224,126,118,114, 68,163, 52,194,217,147,204,169, 37,130,113,102, 73,181]
var byRSExp46: []int :: [112, 94, 88,112,253,224,202,115,187, 99, 89, 5, 54,113,129, 44, 58, 16,135,216,169,211, 36, 1, 4, 96, 60,241, 73,104,234, 8,249,245,119,174, 52, 25,157,224, 43,202,223, 19, 82, 15]
var byRSExp48: []int :: [228, 25,196,130,211,146, 60, 24,251, 90, 39,102,240, 61,178, 63, 46,123,115, 18,221,111,135,160,182,205,107,206, 95,150,120,184, 91, 21,247,156,140,238,191, 11, 94,227, 84, 50,163, 39, 34,108]
var byRSExp50: []int :: [232,125,157,161,164, 9,118, 46,209, 99,203,193, 35, 3,209,111,195,242,203,225, 46, 13, 32,160,126,209,130,160,242,215,242, 75, 77, 42,189, 32,113, 65,124, 69,228,114,235,175,124,170,215,232,133,205]
var byRSExp52: []int :: [116, 50, 86,186, 50,220,251, 89,192, 46, 86,127,124, 19,184,233,151,215, 22, 14, 59,145, 37,242,203,134,254, 89,190, 94, 59, 65,124,113,100,233,235,121, 22, 76, 86, 97, 39,242,200,220,101, 33,239,254,116, 51]
var byRSExp54: []int :: [183, 26,201, 87,210,221,113, 21, 46, 65, 45, 50,238,184,249,225,102, 58,209,218,109,165, 26, 95,184,192, 52,245, 35,254,238,175,172, 79,123, 25,122, 43,120,108,215, 80,128,201,235, 8,153, 59,101, 31,198, 76, 31,156]
var byRSExp56: []int :: [106,120,107,157,164,216,112,116, 2, 91,248,163, 36,201,202,229, 6,144,254,155,135,208,170,209, 12,139,127,142,182,249,177,174,190, 28, 10, 85,239,184,101,124,152,206, 96, 23,163, 61, 27,196,247,151,154,202,207, 20, 61, 10]
var byRSExp58: []int :: [ 82,116, 26,247, 66, 27, 62,107,252,182,200,185,235, 55,251,242,210,144,154,237,176,141,192,248,152,249,206, 85,253,142, 65,165,125, 23, 24, 30,122,240,214, 6,129,218, 29,145,127,134,206,245,117, 29, 41, 63,159,142,233,125,148,123]
var byRSExp60: []int :: [107,140, 26, 12, 9,141,243,197,226,197,219, 45,211,101,219,120, 28,181,127, 6,100,247, 2,205,198, 57,115,219,101,109,160, 82, 37, 38,238, 49,160,209,121, 86, 11,124, 30,181, 84, 25,194, 87, 65,102,190,220, 70, 27,209, 16, 89, 7, 33,240]
var byRSExp62: []int :: [ 65,202,113, 98, 71,223,248,118,214, 94, 0,122, 37, 23, 2,228, 58,121, 7,105,135, 78,243,118, 70, 76,223, 89, 72, 50, 70,111,194, 17,212,126,181, 35,221,117,235, 11,229,149,147,123,213, 40,115, 6,200,100, 26,246,182,218,127,215, 36,186,110,106]
var byRSExp64: []int :: [ 45, 51,175, 9, 7,158,159, 49, 68,119, 92,123,177,204,187,254,200, 78,141,149,119, 26,127, 53,160, 93,199,212, 29, 24,145,156,208,150,218,209, 4,216, 91, 47,184,146, 47,140,195,195,125,242,238, 63, 99,108,140,230,242, 31,204, 11,178,243,217,156,213,231]
var byRSExp66: []int :: [ 5,118,222,180,136,136,162, 51, 46,117, 13,215, 81, 17,139,247,197,171, 95,173, 65,137,178, 68,111, 95,101, 41, 72,214,169,197, 95, 7, 44,154, 77,111,236, 40,121,143, 63, 87, 80,253,240,126,217, 77, 34,232,106, 50,168, 82, 76,146, 67,106,171, 25,132, 93, 45,105]
var byRSExp68: []int :: [247,159,223, 33,224, 93, 77, 70, 90,160, 32,254, 43,150, 84,101,190,205,133, 52, 60,202,165,220,203,151, 93, 84, 15, 84,253,173,160, 89,227, 52,199, 97, 95,231, 52,177, 41,125,137,241,166,225,118, 2, 54, 32, 82,215,175,198, 43,238,235, 27,101,184,127, 3, 5, 8,163,238]
do @byRSExp :: [ null, null, null, null, null, null, null, byRSExp7, null, null,
| byRSExp10, null, null, byRSExp13, null, byRSExp15, byRSExp16, byRSExp17, byRSExp18, null,
| byRSExp20, null, byRSExp22, null, byRSExp24, null, byRSExp26, null, byRSExp28, null,
| byRSExp30, null, byRSExp32, null, byRSExp34, null, byRSExp36, null, byRSExp38, null,
| byRSExp40, null, byRSExp42, null, byRSExp44, null, byRSExp46, null, byRSExp48, null,
| byRSExp50, null, byRSExp52, null, byRSExp54, null, byRSExp56, null, byRSExp58, null,
| byRSExp60, null, byRSExp62, null, byRSExp64, null, byRSExp66, null, byRSExp68]
{文字数インジケータビット長(バージョングループ別, {S, M, L})}
do @nIndicatorLenNumeral :: [10, 12, 14]
do @nIndicatorLenAlphabet :: [ 9, 11, 13]
do @nIndicatorLen8Bit :: [ 8, 16, 16]
do @nIndicatorLenKanji :: [ 8, 10, 12]
end func
class QrEncode()
var m_nLevel: int {誤り訂正レベル}
var m_nVersion: int {バージョン(型番)}
var m_bAutoExtent: int {バージョン(型番)自動拡張指定フラグ}
var m_nMaskingNo: int {マスキングパターン番号}
var m_nSymbleSize: int
var m_byModuleData: [][]bit8 {[x][y]}
{
bit5:機能モジュール(マスキング対象外)フラグ
bit4:機能モジュール描画データ
bit1:エンコードデータ
bit0:マスク後エンコード描画データ
20hとの論理和により機能モジュール判定、11hとの論理和により描画(最終的にはBOOL値化)
}
var m_ncDataCodeWordBit: int {データコードワードビット長}
var m_byDataCodeWord: []bit8 {入力データエンコードエリア}
var m_ncDataBlock: int
var m_byBlockMode: []bit8
var m_nBlockLength: []int
var m_ncAllCodeWord: int {総コードワード数(RS誤り訂正データを含む)}
var m_byAllCodeWord: []bit8 {総コードワード算出エリア}
var m_byRSWork: []bit8 {RSコードワード算出ワーク}
func init(): @QrEncode
if(@initializeFlag = false)
do @initializeFlag :: true
do @initialize()
end if
do me.m_nLevel :: 0
do me.m_nVersion :: 0
do me.m_bAutoExtent :: 0
do me.m_nMaskingNo :: 0
do me.m_nSymbleSize :: 0
do me.m_byModuleData :: #[@MAX_MODULESIZE, @MAX_MODULESIZE]bit8
do me.m_ncDataCodeWordBit :: 0
do me.m_byDataCodeWord :: #[@MAX_DATACODEWORD]bit8
do me.m_ncDataBlock :: 0
do me.m_byBlockMode :: #[@MAX_DATACODEWORD]bit8
do me.m_nBlockLength :: #[@MAX_DATACODEWORD]int
do me.m_ncAllCodeWord :: 0
do me.m_byAllCodeWord :: #[@MAX_ALLCODEWORD]bit8
do me.m_byRSWork :: #[@MAX_CODEBLOCK]bit8
ret me
end func
{
用 途:データエンコード
引 数:誤り訂正レベル、型番(0=自動)、型番自動拡張フラグ、マスキング番号(-1=自動)、エンコードしたいデータ、エンコードしたいデータの長さ(0=自動)
戻り値:エンコード成功時=true、データなし、または容量オーバー時=false
}
+func encodeData(nLevel: int, nVersion: int, bAutoExtent: bool, nMaskingNo: int, lpsSource: []bit8, ncSource: int): bool
do me.init()
do me.m_nLevel :: nLevel
do me.m_nMaskingNo :: nMaskingNo
{データ長が指定されていない場合は lstrlen によって取得}
var ncLength: int :: ncSource > 0 ?(ncSource, ^lpsSource)
if(ncLength = 0)
ret false {データなし}
end if
{バージョン(型番)チェック}
var nEncodeVersion: int :: me.getEncodeVersion(nVersion, lpsSource, ncLength)
if(nEncodeVersion = 0)
ret false {容量オーバー}
end if
if(nVersion = 0)
{型番自動}
do me.m_nVersion :: nEncodeVersion
else
if(nEncodeVersion <= nVersion)
do me.m_nVersion :: nVersion
else
if(bAutoExtent)
do me.m_nVersion :: nEncodeVersion {バージョン(型番)自動拡張}
else
ret false {容量オーバー}
end if
end if
end if
{ターミネータコード"0000"付加}
var ncDataCodeWord: int :: @qrVersionInfo[me.m_nVersion].ncDataCodeWord[nLevel]
var ncTerminater: int :: lib@min(4, (ncDataCodeWord * 8) - me.m_ncDataCodeWordBit)
if(ncTerminater > 0)
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, 0b16, ncTerminater)
end if
{パディングコード"11101100, 00010001"付加}
const x_ec : bit8 :: 0xECb8
var byPaddingCode: bit8 :: x_ec
for i((me.m_ncDataCodeWordBit + 7) / 8, ncDataCodeWord - 1)
do me.m_byDataCodeWord[i] :: byPaddingCode
do byPaddingCode :: ((byPaddingCode = x_ec) ?(@x11, x_ec))
end for
{総コードワード算出エリアクリア}
do me.m_ncAllCodeWord :: @qrVersionInfo[me.m_nVersion].ncAllCodeWord
{ do ZeroMemory(me.m_byAllCodeWord, me.m_ncAllCodeWord) }
do me.m_byAllCodeWord :: #[@MAX_ALLCODEWORD]bit8 {総コードワード算出エリア}
var nDataCwIndex: int :: 0 {データコードワード処理位置}
{データブロック分割数}
var ncBlock1: int :: @qrVersionInfo[me.m_nVersion].rsBlockInfo1[nLevel].ncRSBlock
var ncBlock2: int :: @qrVersionInfo[me.m_nVersion].rsBlockInfo2[nLevel].ncRSBlock
var ncBlockSum: int :: ncBlock1 + ncBlock2
var nBlockNo: int :: 0 {処理中ブロック番号}
{ブロック別データコードワード数}
var ncDataCw1: int :: @qrVersionInfo[me.m_nVersion].rsBlockInfo1[nLevel].ncBlockDataCodeWord
var ncDataCw2: int :: @qrVersionInfo[me.m_nVersion].rsBlockInfo2[nLevel].ncBlockDataCodeWord
{データコードワードインターリーブ配置}
for i(0, ncBlock1 - 1)
for j(0, ncDataCw1 - 1)
do me.m_byAllCodeWord[(ncBlockSum * j) + nBlockNo] :: me.m_byDataCodeWord[nDataCwIndex]
do nDataCwIndex :+ 1
end for
do nBlockNo :+ 1
end for
for i(0, ncBlock2 - 1)
for j(0, ncDataCw2 - 1)
if(j < ncDataCw1)
do me.m_byAllCodeWord[(ncBlockSum * j) + nBlockNo] :: me.m_byDataCodeWord[nDataCwIndex]
else
{2種目ブロック端数分配置}
do me.m_byAllCodeWord[(ncBlockSum * ncDataCw1) + i] :: me.m_byDataCodeWord[nDataCwIndex]
end if
do nDataCwIndex :+ 1
end for
do nBlockNo :+ 1
end for
{ブロック別RSコードワード数(※現状では同数)}
var ncRSCw1: int :: @qrVersionInfo[me.m_nVersion].rsBlockInfo1[nLevel].ncBlockAllCodeWord - ncDataCw1
var ncRSCw2: int :: @qrVersionInfo[me.m_nVersion].rsBlockInfo2[nLevel].ncBlockAllCodeWord - ncDataCw2
{RSコードワード算出}
do nDataCwIndex :: 0
do nBlockNo :: 0
for i(0, ncBlock1 - 1)
{ do ZeroMemory(me.m_byRSWork, sizeof(me.m_byRSWork)) }
do me.m_byRSWork :: #[@MAX_CODEBLOCK]bit8 {RSコードワード算出ワーク}
do @memmove(me.m_byRSWork, me.m_byDataCodeWord, nDataCwIndex, ncDataCw1)
do me.GetRSCodeWord(me.m_byRSWork, ncDataCw1, ncRSCw1)
{RSコードワード配置}
for j(0, ncRSCw1 - 1)
do me.m_byAllCodeWord[ncDataCodeWord + (ncBlockSum * j) + nBlockNo] :: me.m_byRSWork[j]
end for
do nDataCwIndex :+ ncDataCw1
do nBlockNo :+ 1
end for
for i(0, ncBlock2 - 1)
{ do ZeroMemory(me.m_byRSWork, sizeof(me.m_byRSWork)) }
do me.m_byRSWork :: #[@MAX_CODEBLOCK]bit8 {RSコードワード算出ワーク}
do @memmove(me.m_byRSWork, me.m_byDataCodeWord, nDataCwIndex, ncDataCw2)
do me.GetRSCodeWord(me.m_byRSWork, ncDataCw2, ncRSCw2)
{RSコードワード配置}
for j(0, ncRSCw2 - 1)
do me.m_byAllCodeWord[ncDataCodeWord + (ncBlockSum * j) + nBlockNo] :: me.m_byRSWork[j]
end for
do nDataCwIndex :+ ncDataCw2
do nBlockNo :+ 1
end for
do me.m_nSymbleSize :: me.m_nVersion * 4 + 17
{モジュール配置}
do me.formatModule()
ret true
end func
{
用 途:エンコード時バージョン(型番)取得
引 数:調査開始バージョン、エンコードデータ、エンコードデータ長
戻り値:バージョン番号(容量オーバー時=0)
}
func getEncodeVersion(nVersion: int, lpsSource: []bit8, ncLength: int): int
var nVerGroup: int :: nVersion >= 27 ?(@QR_VRESION_L, (nVersion >= 10 ?(@QR_VRESION_M, @QR_VRESION_S)))
for i(nVerGroup, @QR_VRESION_L)
if(me.EncodeSourceData(lpsSource, ncLength, i))
if(i = @QR_VRESION_S)
for j(1, 9)
if((me.m_ncDataCodeWordBit + 7) / 8 <= @qrVersionInfo[j].ncDataCodeWord[me.m_nLevel])
ret j
end if
end for
elif(i = @QR_VRESION_M)
for j(10, 26)
if((me.m_ncDataCodeWordBit + 7) / 8 <= @qrVersionInfo[j].ncDataCodeWord[me.m_nLevel])
ret j
end if
end for
elif(i = @QR_VRESION_L)
for j(27, 40)
if((me.m_ncDataCodeWordBit + 7) / 8 <= @qrVersionInfo[j].ncDataCodeWord[me.m_nLevel])
ret j
end if
end for
end if
end if
end for
ret 0
end func
{
用 途:入力データエンコード
引 数:入力データ、入力データ長、バージョン(型番)グループ
戻り値:エンコード成功時=true
}
func EncodeSourceData(lpsSource: []bit8, ncLength: int, nVerGroup: int): bool
{ do ZeroMemory(me.m_nBlockLength, sizeof(me.m_nBlockLength)) }
do me.m_nBlockLength :: #[@MAX_DATACODEWORD]int
{どのモードが何文字(バイト)継続しているかを調査}
do me.m_ncDataBlock :: 0
for i(0, ncLength - 1)
var byMode: bit8
if(i < ncLength - 1 & me.IsKanjiData(lpsSource[i], lpsSource[i + 1]))
do byMode :: @QR_MODE_KANJI
elif(me.IsNumeralData(lpsSource[i]))
do byMode :: @QR_MODE_NUMERAL
elif(me.IsAlphabetData(lpsSource[i]))
do byMode :: @QR_MODE_ALPHABET
else
do byMode :: @QR_MODE_8BIT
end if
if(i = 0)
do me.m_byBlockMode[0] :: byMode
end if
if(me.m_byBlockMode[me.m_ncDataBlock] <> byMode)
do me.m_ncDataBlock :+ 1
do me.m_byBlockMode[me.m_ncDataBlock] :: byMode
end if
if(byMode = @QR_MODE_KANJI)
do me.m_nBlockLength[me.m_ncDataBlock] :+ 2
do i :+ 1
else
do me.m_nBlockLength[me.m_ncDataBlock] :+ 1
end if
end for
do me.m_ncDataBlock :+ 1
{隣接する英数字モードブロックと数字モードブロックの並びをを条件により結合}
var ncSrcBits: int {元のビット長}
var ncDstBits: int {単一の英数字モードブロック化した場合のビット長}
var nBlock: int :: 0
while a(nBlock < me.m_ncDataBlock - 1)
var ncJoinFront: int {前8ビットバイトモードブロックと結合した場合のビット長}
var ncJoinBehind: int {後8ビットバイトモードブロックと結合した場合のビット長}
var nJoinPosition: int :: 0 {8ビットバイトモードブロックとの結合:-1=前と結合、0=結合しない、1=後ろと結合}
{「数字-英数字」または「英数字-数字」の並び}
if( (me.m_byBlockMode[nBlock] = @QR_MODE_NUMERAL & me.m_byBlockMode[nBlock + 1] = @QR_MODE_ALPHABET) |
|(me.m_byBlockMode[nBlock] = @QR_MODE_ALPHABET & me.m_byBlockMode[nBlock + 1] = @QR_MODE_NUMERAL))
{元のビット長と単一の英数字モードブロック化した場合のビット長を比較}
do ncSrcBits :: me.GetBitLength(me.m_byBlockMode[nBlock ], me.m_nBlockLength[nBlock ], nVerGroup) +
| me.GetBitLength(me.m_byBlockMode[nBlock + 1], me.m_nBlockLength[nBlock + 1], nVerGroup)
do ncDstBits :: me.GetBitLength(@QR_MODE_ALPHABET, me.m_nBlockLength[nBlock] + me.m_nBlockLength[nBlock + 1], nVerGroup)
if(ncSrcBits > ncDstBits)
{前後に8ビットバイトモードブロックがある場合、それらとの結合が有利かどうかをチェック}
if(nBlock >= 1 & me.m_byBlockMode[nBlock - 1] = @QR_MODE_8BIT)
{前に8ビットバイトモードブロックあり}
do ncJoinFront :: me.GetBitLength(@QR_MODE_8BIT, me.m_nBlockLength[nBlock - 1] + me.m_nBlockLength[nBlock], nVerGroup) +
| me.GetBitLength(me.m_byBlockMode[nBlock + 1], me.m_nBlockLength[nBlock + 1], nVerGroup)
if(ncJoinFront > ncDstBits + me.GetBitLength(@QR_MODE_8BIT, me.m_nBlockLength[nBlock - 1], nVerGroup))
do ncJoinFront :: 0 {8ビットバイトモードブロックとは結合しない}
end if
else
do ncJoinFront :: 0
end if
if(nBlock < me.m_ncDataBlock - 2 & me.m_byBlockMode[nBlock + 2] = @QR_MODE_8BIT)
{後ろに8ビットバイトモードブロックあり}
do ncJoinBehind :: me.GetBitLength(me.m_byBlockMode[nBlock], me.m_nBlockLength[nBlock], nVerGroup) +
| me.GetBitLength(@QR_MODE_8BIT, me.m_nBlockLength[nBlock + 1] + me.m_nBlockLength[nBlock + 2], nVerGroup)
if(ncJoinBehind > ncDstBits + me.GetBitLength(@QR_MODE_8BIT, me.m_nBlockLength[nBlock + 2], nVerGroup))
do ncJoinBehind :: 0 {8ビットバイトモードブロックとは結合しない}
end if
else
do ncJoinBehind :: 0
end if
if(ncJoinFront <> 0 & ncJoinBehind <> 0)
{前後両方に8ビットバイトモードブロックがある場合はデータ長が短くなる方を優先}
do nJoinPosition :: (ncJoinFront < ncJoinBehind) ?(-1, 1)
else
do nJoinPosition :: (ncJoinFront <> 0) ?(-1, (ncJoinBehind <> 0) ?(1, 0))
end if
if(nJoinPosition <> 0)
{8ビットバイトモードブロックとの結合}
if(nJoinPosition = -1)
do me.m_nBlockLength[nBlock - 1] :+ me.m_nBlockLength[nBlock]
{後続をシフト}
for i(nBlock, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
else
do me.m_byBlockMode[nBlock + 1] :: @QR_MODE_8BIT
do me.m_nBlockLength[nBlock + 1] :+ me.m_nBlockLength[nBlock + 2]
{後続をシフト}
for i(nBlock + 2, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
end if
do me.m_ncDataBlock :- 1
else
{英数字と数字の並びを単一の英数字モードブロックに統合}
if(nBlock < me.m_ncDataBlock - 2 & me.m_byBlockMode[nBlock + 2] = @QR_MODE_ALPHABET)
{結合しようとするブロックの後ろに続く英数字モードブロックを結合}
do me.m_nBlockLength[nBlock + 1] :+ me.m_nBlockLength[nBlock + 2]
{後続をシフト}
for i(nBlock + 2, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
do me.m_ncDataBlock :- 1
end if
do me.m_byBlockMode[nBlock] :: @QR_MODE_ALPHABET
do me.m_nBlockLength[nBlock] :+ me.m_nBlockLength[nBlock + 1]
{後続をシフト}
for i(nBlock + 1, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
do me.m_ncDataBlock :- 1
if(nBlock >= 1 & me.m_byBlockMode[nBlock - 1] = @QR_MODE_ALPHABET)
{結合したブロックの前の英数字モードブロックを結合}
do me.m_nBlockLength[nBlock - 1] :+ me.m_nBlockLength[nBlock]
{後続をシフト}
for i(nBlock, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
do me.m_ncDataBlock :- 1
end if
end if
skip a {現在位置のブロックを再調査}
end if
end if
do nBlock :+ 1 {次ブロックを調査}
end while
{連続する短いモードブロックを8ビットバイトモードブロック化}
do nBlock :: 0
while a(nBlock < me.m_ncDataBlock - 1)
do ncSrcBits :: me.GetBitLength(me.m_byBlockMode[nBlock ], me.m_nBlockLength[nBlock ], nVerGroup) +
| me.GetBitLength(me.m_byBlockMode[nBlock + 1], me.m_nBlockLength[nBlock + 1], nVerGroup)
do ncDstBits :: me.GetBitLength(@QR_MODE_8BIT, me.m_nBlockLength[nBlock] + me.m_nBlockLength[nBlock + 1], nVerGroup)
{前に8ビットバイトモードブロックがある場合、重複するインジケータ分を減算}
if(nBlock >= 1 & me.m_byBlockMode[nBlock - 1] = @QR_MODE_8BIT)
do ncDstBits :- (4 + @nIndicatorLen8Bit[nVerGroup])
end if
{後ろに8ビットバイトモードブロックがある場合、重複するインジケータ分を減算}
if(nBlock < me.m_ncDataBlock - 2 & me.m_byBlockMode[nBlock + 2] = @QR_MODE_8BIT)
do ncDstBits :- (4 + @nIndicatorLen8Bit[nVerGroup])
end if
if(ncSrcBits > ncDstBits)
if(nBlock >= 1 & me.m_byBlockMode[nBlock - 1] = @QR_MODE_8BIT)
{結合するブロックの前にある8ビットバイトモードブロックを結合}
do me.m_nBlockLength[nBlock - 1] :+ me.m_nBlockLength[nBlock]
{後続をシフト}
for i(nBlock, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
do me.m_ncDataBlock :- 1
do nBlock :- 1
end if
if(nBlock < me.m_ncDataBlock - 2 & me.m_byBlockMode[nBlock + 2] = @QR_MODE_8BIT)
{結合するブロックの後ろにある8ビットバイトモードブロックを結合}
do me.m_nBlockLength[nBlock + 1] :+ me.m_nBlockLength[nBlock + 2]
{後続をシフト}
for i(nBlock + 2, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
do me.m_ncDataBlock :- 1
end if
do me.m_byBlockMode[nBlock] :: @QR_MODE_8BIT
do me.m_nBlockLength[nBlock] :+ me.m_nBlockLength[nBlock + 1]
{後続をシフト}
for i(nBlock + 1, me.m_ncDataBlock - 2)
do me.m_byBlockMode[i] :: me.m_byBlockMode[i + 1]
do me.m_nBlockLength[i] :: me.m_nBlockLength[i + 1]
end for
do me.m_ncDataBlock :- 1
{結合したブロックの前から再調査}
if(nBlock >= 1)
do nBlock :- 1
end if
skip a
end if
do nBlock :+ 1 {次ブロックを調査}
end while
{ビット配列化}
var ncComplete: int :: 0 {処理済データカウンタ}
var wBinCode: bit16
do me.m_ncDataCodeWordBit :: 0 {ビット単位処理カウンタ}
{ do ZeroMemory(me.m_byDataCodeWord, @MAX_DATACODEWORD) }
do me.m_byDataCodeWord :: #[@MAX_DATACODEWORD]bit8 {入力データエンコードエリア}
var i: int :: 0
while(i < me.m_ncDataBlock & me.m_ncDataCodeWordBit <> -1)
if(me.m_byBlockMode[i] = @QR_MODE_NUMERAL) {数字モード}
{インジケータ(0001b)}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, 1b16, 4)
{文字数セット}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, me.m_nBlockLength[i] $ bit16, @nIndicatorLenNumeral[nVerGroup])
{ビット列保存}
for j(0, me.m_nBlockLength[i] - 1, 3)
if(j < me.m_nBlockLength[i] - 2)
do wBinCode :: ( ((lpsSource[ncComplete + j ] $ int - '0' $ int) * 100) +
| ((lpsSource[ncComplete + j + 1] $ int - '0' $ int) * 10) +
| (lpsSource[ncComplete + j + 2] $ int - '0' $ int)) $ bit16
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, wBinCode, 10)
elif(j = me.m_nBlockLength[i] - 2)
{端数2バイト}
do wBinCode :: ( ((lpsSource[ncComplete + j ] $ int - '0' $ int) * 10) +
| (lpsSource[ncComplete + j + 1] $ int - '0' $ int)) $ bit16
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, wBinCode, 7)
elif(j = me.m_nBlockLength[i] - 1)
{端数1バイト}
do wBinCode :: (lpsSource[ncComplete + j ] $ int - '0' $ int) $ bit16
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, wBinCode, 4)
end if
end for
do ncComplete :+ me.m_nBlockLength[i]
elif(me.m_byBlockMode[i] = @QR_MODE_ALPHABET) {英数字モード}
{モードインジケータ(0010b)}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, 2b16, 4)
{文字数セット}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, me.m_nBlockLength[i] $ bit16, @nIndicatorLenAlphabet[nVerGroup])
{ビット列保存}
for j(0, me.m_nBlockLength[i] - 1, 2)
if(j < me.m_nBlockLength[i] - 1)
do wBinCode :: ((me.AlphabetToBinaly(lpsSource[ncComplete + j ]) * 45) +
| me.AlphabetToBinaly(lpsSource[ncComplete + j + 1])) $ bit16
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, wBinCode, 11)
else
{端数1バイト}
do wBinCode :: me.AlphabetToBinaly(lpsSource[ncComplete + j]) $ bit16
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, wBinCode, 6)
end if
end for
do ncComplete :+ me.m_nBlockLength[i]
elif(me.m_byBlockMode[i] = @QR_MODE_8BIT) {8ビットバイトモード}
{モードインジケータ(0100b)}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, 4b16, 4)
{文字数セット}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, me.m_nBlockLength[i] $ bit16, @nIndicatorLen8Bit[nVerGroup])
{ビット列保存}
for j(0, me.m_nBlockLength[i] - 1)
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, lpsSource[ncComplete + j] $ bit16, 8)
end for
do ncComplete :+ me.m_nBlockLength[i]
else {me.m_byBlockMode[i] = @QR_MODE_KANJI} {漢字モード}
{モードインジケータ(1000b)}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, 8b16, 4)
{文字数セット}
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, (me.m_nBlockLength[i] / 2) $ bit16, @nIndicatorLenKanji[nVerGroup])
{漢字モードでビット列保存}
for j(0, me.m_nBlockLength[i] - 1, 2)
do wBinCode :: me.KanjiToBinaly((lpsSource[ncComplete + j] $ bit16).shl(8) + lpsSource[ncComplete + j + 1] $ bit16)
do me.m_ncDataCodeWordBit :: me.SetBitStream(me.m_ncDataCodeWordBit, wBinCode, 13)
end for
do ncComplete :+ me.m_nBlockLength[i]
end if
do i :+ 1
end while
ret (me.m_ncDataCodeWordBit <> -1)
end func
{
用 途:ビット長取得
引 数:データモード種別、データ長、バージョン(型番)グループ
戻り値:データビット長
備 考:漢字モードでのデータ長引数は文字数ではなくバイト数
}
func GetBitLength(nMode: bit8, ncData: int, nVerGroup: int): int
var ncBits: int :: 0
switch (nMode)
case @QR_MODE_NUMERAL
do ncBits :: 4 + @nIndicatorLenNumeral[nVerGroup] + (10 * (ncData / 3))
switch(ncData % 3)
case 1
do ncBits :+ 4
case 2
do ncBits :+ 7
default {case (0)}
end switch
case @QR_MODE_ALPHABET
do ncBits :: 4 + @nIndicatorLenAlphabet[nVerGroup] + (11 * (ncData / 2)) + (6 * (ncData % 2))
case @QR_MODE_8BIT
do ncBits :: 4 + @nIndicatorLen8Bit[nVerGroup] + ( 8 * ncData)
default {case @QR_MODE_KANJI}
do ncBits :: 4 + @nIndicatorLenKanji[nVerGroup] + (13 * (ncData / 2))
end switch
ret ncBits
end func
{
用 途:ビットセット
引 数:挿入位置、ビット配列データ、データビット長(最大16)
戻り値:次回挿入位置(バッファオーバー時=-1)
備 考:me.m_byDataCodeWord に結果をセット(要ゼロ初期化)
}
func SetBitStream(nIndex: int, wData: bit16, ncData: int): int
if(nIndex = -1 | nIndex + ncData > @MAX_DATACODEWORD * 8)
ret -1
end if
for i(0, ncData - 1)
if(wData.and((1b16).shl(ncData - i - 1)) <> 0b16)
do me.m_byDataCodeWord[(nIndex + i) / 8] :: me.m_byDataCodeWord[(nIndex + i) / 8].or((1b8).shl(7 - ((nIndex + i) % 8)))
end if
end for
ret nIndex + ncData
end func
{
用 途:数字モード該当チェック
引 数:調査文字
戻り値:該当時=true
}
func IsNumeralData(c: bit8): bool
switch(c $ char)
case '0' to '9'
ret true
end switch
ret false
end func
{
用 途:英数字モード該当チェック
引 数:調査文字
戻り値:該当時=true
}
func IsAlphabetData(c: bit8): bool
switch(c $ char)
case '0' to '9'
ret true
case 'A' to 'Z'
ret true
case ' ', '$', '%', '*', '+', '-', '.', '/', ':'
ret true
end switch
ret false
end func
{
用 途:漢字モード該当チェック
引 数:調査文字(16ビット文字)
戻り値:該当時=true
備 考:EBBFh 以降の S-JIS は対象外
}
func IsKanjiData(c1: bit8, c2: bit8): bool
if( ((c1 >= 0x81b8 & c1 <= 0x9Fb8) | (c1 >= 0xE0b8 & c1 <= 0xEBb8)) & (c2 >= 0x40b8))
if((c1 = 0x9Fb8 & c2 > 0xFCb8) | (c1 = 0xEBb8 & c2 > 0xBFb8))
ret false
end if
ret true
end if
ret false
end func
{
用 途:英数字モード文字のバイナリ化
引 数:対象文字
戻り値:バイナリ値
}
func AlphabetToBinaly(c: bit8): int
switch(c $ char)
case '0' to '9'
ret (c $ int - '0' $ int)
case 'A' to 'Z'
ret (c $ int - 'A' $ int + 10)
case ' '
ret 36
case '$'
ret 37
case '%'
ret 38
case '*'
ret 39
case '+'
ret 40
case '-'
ret 41
case '.'
ret 42
case '/'
ret 43
default
ret 44 {case ':'}
end switch
end func
{
用 途:漢字モード文字のバイナリ化
引 数:対象文字
戻り値:バイナリ値
}
func KanjiToBinaly(wc: bit16): bit16
switch(wc)
case 0x8140b16 to 0x9FFCb16
do wc :: (wc $ int - 0x8140) $ bit16
default {case 0xe040 to 0xebbf}
do wc :: (wc $ int - 0xC140) $ bit16
end switch
ret wc.shr(8) * 0xC0b16 + wc.and(0x00FFb16)
end func
{
用 途:RS誤り訂正コードワード取得
引 数:データコードワードアドレス、データコードワード長、RSコードワード長
備 考:総コードワード分のエリアを確保してから呼び出し
}
func GetRSCodeWord(lpbyRSWork: []bit8, ncDataCodeWord: int, ncRSCodeWord: int)
for(1, ncDataCodeWord)
if(lpbyRSWork[0] <> @x00)
var nExpFirst: bit8 :: @byIntToExp[lpbyRSWork[0] $ int] {初項係数より乗数算出}
for j(0, ncRSCodeWord - 1)
{各項乗数に初項乗数を加算(% 255 → α^255 = 1}
var nExpElement: bit8 :: (((@byRSExp[ncRSCodeWord][j] + nExpFirst $ int)) % 255) $ bit8
{排他論理和による剰余算出}
do lpbyRSWork[j] :: lpbyRSWork[j + 1].xor(@byExpToInt[nExpElement $ int])
end for
{残り桁をシフト}
for j(ncRSCodeWord, ncDataCodeWord + ncRSCodeWord - 2)
do lpbyRSWork[j] :: lpbyRSWork[j + 1]
end for
else
{残り桁をシフト}
for j(0, ncDataCodeWord + ncRSCodeWord - 2)
do lpbyRSWork[j] :: lpbyRSWork[j + 1]
end for
end if
end for
end func
{
用 途:モジュールへのデータ配置
戻り値:一辺のモジュール数
}
func formatModule()
{ do ZeroMemory(me.m_byModuleData, sizeof(me.m_byModuleData)) }
do me.m_byModuleData :: #[@MAX_MODULESIZE, @MAX_MODULESIZE]bit8
{機能モジュール配置}
do me.setFunctionModule()
{データパターン配置}
do me.setCodeWordPattern()
if(me.m_nMaskingNo = -1)
{最適マスキングパターン選択}
do me.m_nMaskingNo :: 0
do me.SetMaskingPattern(me.m_nMaskingNo) {マスキング}
do me.SetFormatInfoPattern(me.m_nMaskingNo) {フォーマット情報パターン配置}
var nMinPenalty: int :: me.countPenalty()
for i(1, 7)
do me.SetMaskingPattern(i) {マスキング}
do me.SetFormatInfoPattern(i) {フォーマット情報パターン配置}
var nPenalty: int :: me.countPenalty()
if(nPenalty < nMinPenalty)
do nMinPenalty :: nPenalty
do me.m_nMaskingNo :: i
end if
end for
end if
do me.SetMaskingPattern(me.m_nMaskingNo) {マスキング}
do me.SetFormatInfoPattern(me.m_nMaskingNo) {フォーマット情報パターン配置}
{モジュールパターンをブール値に変換}
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 1)
do me.m_byModuleData[i][j] :: (me.m_byModuleData[i][j].and(@x11) <> @x00) $ bit8
end for
end for
end func
{
用 途:機能モジュール配置
備 考:フォーマット情報は機能モジュール登録のみ(実データは空白)
}
func setFunctionModule()
{位置検出パターン}
do me.SetFinderPattern(0, 0)
do me.SetFinderPattern(me.m_nSymbleSize - 7, 0)
do me.SetFinderPattern(0, me.m_nSymbleSize - 7)
{位置検出パターンセパレータ}
for i(0, 7)
do me.m_byModuleData[i][7] :: @x20
do me.m_byModuleData[7][i] :: @x20
do me.m_byModuleData[me.m_nSymbleSize - 8 ][i] :: @x20
do me.m_byModuleData[me.m_nSymbleSize - 8 + i][7] :: @x20
do me.m_byModuleData[i][me.m_nSymbleSize - 8 ] :: @x20
do me.m_byModuleData[7][me.m_nSymbleSize - 8 + i] :: @x20
end for
{フォーマット情報記述位置を機能モジュール部として登録}
for i(0, 8)
do me.m_byModuleData[i][8] :: @x20
do me.m_byModuleData[8][i] :: @x20
end for
for i(0, 7)
do me.m_byModuleData[me.m_nSymbleSize - 8 + i][8] :: @x20
do me.m_byModuleData[8][me.m_nSymbleSize - 8 + i] :: @x20
end for
{バージョン情報パターン}
do me.SetVersionPattern()
{位置合わせパターン}
for i(0, @qrVersionInfo[me.m_nVersion].ncAlignPoint - 1)
do me.SetAlignmentPattern(@qrVersionInfo[me.m_nVersion].nAlignPoint[i], 6)
do me.SetAlignmentPattern(6, @qrVersionInfo[me.m_nVersion].nAlignPoint[i])
for j(0, @qrVersionInfo[me.m_nVersion].ncAlignPoint - 1)
do me.SetAlignmentPattern(@qrVersionInfo[me.m_nVersion].nAlignPoint[i], @qrVersionInfo[me.m_nVersion].nAlignPoint[j])
end for
end for
{タイミングパターン}
for i(8, me.m_nSymbleSize - 9)
do me.m_byModuleData[i][6] :: ((i % 2) = 0) ?(@x30, @x20)
do me.m_byModuleData[6][i] :: ((i % 2) = 0) ?(@x30, @x20)
end for
end func
{
用 途:位置検出パターン配置
引 数:配置左上座標
}
func SetFinderPattern(x: int, y: int)
var byPattern: []bit8 :: [0x7Fb8, {1111111b}
| 0x41b8, {1000001b}
| 0x5Db8, {1011101b}
| 0x5Db8, {1011101b}
| 0x5Db8, {1011101b}
| 0x41b8, {1000001b}
| 0x7Fb8] {1111111b}
for i(0, 6)
for j(0, 6)
do me.m_byModuleData[x + j][y + i] :: (byPattern[i].and((1b8).shl(6 - j)) <> @x00) ?(@x30, @x20)
end for
end for
end func
{
用 途:位置合わせパターン配置
引 数:配置中央座標
}
func SetAlignmentPattern(x: int, y: int)
var byPattern: []bit8 :: [0x1Fb8, {11111b}
| 0x11b8, {10001b}
| 0x15b8, {10101b}
| 0x11b8, {10001b}
| 0x1Fb8] {11111b}
if(me.m_byModuleData[x][y].and(@x20) <> @x00)
ret {機能モジュールと重複するため除外}
end if
{左上隅座標に変換}
do x :- 2
do y :- 2
for i(0, 4)
for j(0, 4)
do me.m_byModuleData[x + j][y + i] :: (byPattern[i].and((1b8).shl(4 - j)) <> @x00) ?(@x30, @x20)
end for
end for
end func
{
用 途:バージョン(型番)情報パターン配置
備 考:拡張BCH(18,6)符号を誤り訂正として使用
}
func SetVersionPattern()
if(me.m_nVersion <= 6)
ret
end if
var nVerData: bit64 :: (me.m_nVersion $ bit64).shl(12)
{剰余ビット算出}
for i(0, 5)
if(nVerData.and((1b64).shl(17 - i)) <> 0b64)
do nVerData :: nVerData.xor((0x1F25b64).shl(5 - i))
end if
end for
do nVerData :+ (me.m_nVersion $ bit64).shl(12)
for i(0, 5)
for j(0, 2)
do me.m_byModuleData[i][me.m_nSymbleSize - 11 + j] :: (nVerData.and((1b64).shl(i * 3 + j)) <> 0b64) ?(@x30, @x20)
do me.m_byModuleData[me.m_nSymbleSize - 11 + j][i] :: me.m_byModuleData[i][me.m_nSymbleSize - 11 + j]
end for
end for
end func
{
用 途:データパターン配置
}
func setCodeWordPattern()
var x: int :: me.m_nSymbleSize
var y: int :: me.m_nSymbleSize - 1
var nCoef_x:int :: 1 {x軸配置向き}
var nCoef_y:int :: 1 {y軸配置向き}
for i(0, me.m_ncAllCodeWord - 1)
for j(0, 7)
while(me.m_byModuleData[x][y].and(0x20b8) <> @x00, skip) {機能モジュールを除外}
do x :+ nCoef_x
do nCoef_x :* -1
if(nCoef_x < 0)
do y :+ nCoef_y
if(y < 0 | y = me.m_nSymbleSize)
do y :: (y < 0) ?(0, me.m_nSymbleSize - 1)
do nCoef_y :* -1
do x :- 2
if(x = 6) {タイミングパターン}
do x :- 1
end if
end if
end if
end while
do me.m_byModuleData[x][y] :: (me.m_byAllCodeWord[i].and((1b8).shl(7 - j)) <> @x00) ?(0x02b8, 0x00b8)
end for
end for
end func
{
用 途:マスキングパターン配置
引 数:マスキングパターン番号
}
func SetMaskingPattern(nPatternNo: int)
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 1)
if(! (me.m_byModuleData[j][i].and(@x20) <> @x00)) {機能モジュールを除外}
var bMask: bool
switch (nPatternNo)
case 0
do bMask :: ((i + j) % 2 = 0)
case 1
do bMask :: (i % 2 = 0)
case 2
do bMask :: (j % 3 = 0)
case 3
do bMask :: ((i + j) % 3 = 0)
case 4
do bMask :: (((i / 2) + (j / 3)) % 2 = 0)
case 5
do bMask :: (((i * j) % 2) + ((i * j) % 3) = 0)
case 6
do bMask :: ((((i * j) % 2) + ((i * j) % 3)) % 2 = 0)
default {case 7}
do bMask :: ((((i * j) % 3) + ((i + j) % 2)) % 2 = 0)
end switch
do me.m_byModuleData[j][i] :: me.m_byModuleData[j][i].and(0xFEb8).or(((me.m_byModuleData[j][i].and(0x02b8) $ int > 1) $ bit8).xor(bMask $ bit8))
end if
end for
end for
end func
{
用 途:フォーマット情報配置
引 数:マスキングパターン番号
}
func SetFormatInfoPattern(nPatternNo: int)
var nFormatInfo: int
switch(me.m_nLevel)
case @QR_LEVEL_M
do nFormatInfo :: 0x00 {00nnnb}
case @QR_LEVEL_L
do nFormatInfo :: 0x08 {01nnnb}
case @QR_LEVEL_Q
do nFormatInfo :: 0x18 {11nnnb}
default {case @QR_LEVEL_H}
do nFormatInfo :: 0x10 {10nnnb}
end switch
do nFormatInfo :+ nPatternNo
var nFormatData: bit64 :: (nFormatInfo $ bit64).shl(10)
{剰余ビット算出}
for i(0, 4)
if(nFormatData.and((1b64).shl(14 - i)) <> 0b64)
do nFormatData :: nFormatData.xor((0x0537b64).shl(4 - i)) {10100110111b}
end if
end for
do nFormatData :+ (nFormatInfo $ bit64).shl(10)
{マスキング}
do nFormatData :: nFormatData.xor(0x5412b64) {101010000010010b}
{左上位置検出パターン周り配置}
for i(0, 5)
do me.m_byModuleData[8][i] :: (nFormatData.and((1b64).shl(i)) <> 0b64) ?(@x30, @x20)
end for
do me.m_byModuleData[8][7] :: (nFormatData.and((1b64).shl(6)) <> 0b64) ?(@x30, @x20)
do me.m_byModuleData[8][8] :: (nFormatData.and((1b64).shl(7)) <> 0b64) ?(@x30, @x20)
do me.m_byModuleData[7][8] :: (nFormatData.and((1b64).shl(8)) <> 0b64) ?(@x30, @x20)
for i(9, 14)
do me.m_byModuleData[14 - i][8] :: (nFormatData.and((1b64).shl(i)) <> 0b64) ?(@x30, @x20)
end for
{右上位置検出パターン下配置}
for i(0, 7)
do me.m_byModuleData[me.m_nSymbleSize - 1 - i][8] :: (nFormatData.and((1b64).shl(i)) <> 0b64) ?(@x30, @x20)
end for
{左下位置検出パターン右配置}
do me.m_byModuleData[8][me.m_nSymbleSize - 8] :: @x30 {固定暗モジュール}
for i(8, 14)
do me.m_byModuleData[8][me.m_nSymbleSize - 15 + i] :: (nFormatData.and((1b64).shl(i)) <> 0b64) ?(@x30, @x20)
end for
end func
{
用 途:マスク後ペナルティスコア算出
}
func countPenalty(): int
var nPenalty: int :: 0
{同色の列の隣接モジュール}
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 5)
var nCount: int :: 1
var k: int
for k_(j + 1, me.m_nSymbleSize - 1)
do k :: k_
if((me.m_byModuleData[i][j].and(@x11) = @x00) = ((me.m_byModuleData[i][k_].and(@x11) = @x00)))
do nCount :+ 1
else
break k_
end if
end for
if(nCount >= 5)
do nPenalty :+ 3 + (nCount - 5)
end if
do j :: k - 1
end for
end for
{同色の行の隣接モジュール}
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 5)
var nCount: int :: 1
var k: int
for k_(j + 1, me.m_nSymbleSize - 1)
do k :: k_
if((me.m_byModuleData[j][i].and(@x11) = @x00) = ((me.m_byModuleData[k_][i].and(@x11) = @x00)))
do nCount :+ 1
else
break k_
end if
end for
if(nCount >= 5)
do nPenalty :+ 3 + (nCount - 5)
end if
do j :: k - 1
end for
end for
{同色のモジュールブロック(2×2)}
for i(0, me.m_nSymbleSize - 2)
for j(0, me.m_nSymbleSize - 2)
if( ((me.m_byModuleData[i][j].and(@x11) = @x00) = (me.m_byModuleData[i + 1][j ].and(@x11) = @x00)) &
|((me.m_byModuleData[i][j].and(@x11) = @x00) = (me.m_byModuleData[i ][j + 1].and(@x11) = @x00)) &
|((me.m_byModuleData[i][j].and(@x11) = @x00) = (me.m_byModuleData[i + 1][j + 1].and(@x11) = @x00)))
do nPenalty :+ 3
end if
end for
end for
{同一列における 1:1:3:1:1 比率(暗:明:暗:明:暗)のパターン}
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 7)
if(((j = 0) | (!(me.m_byModuleData[i][j - 1].and(@x11) <> @x00))) & {明 または シンボル外}
| ( me.m_byModuleData[i][j ].and(@x11) <> @x00) & {暗 - 1}
| (!(me.m_byModuleData[i][j + 1].and(@x11) <> @x00)) & {明 - 1}
| ( me.m_byModuleData[i][j + 2].and(@x11) <> @x00) & {暗 ┐ }
| ( me.m_byModuleData[i][j + 3].and(@x11) <> @x00) & {暗 │3}
| ( me.m_byModuleData[i][j + 4].and(@x11) <> @x00) & {暗 ┘ }
| (!(me.m_byModuleData[i][j + 5].and(@x11) <> @x00)) & {明 - 1}
| ( me.m_byModuleData[i][j + 6].and(@x11) <> @x00) & {暗 - 1}
|((j = me.m_nSymbleSize - 7) | (!(me.m_byModuleData[i][j + 7].and(@x11) <> @x00)))) {明 または シンボル外}
{前または後に4以上の明パターン}
if( ((j < 2 | !(me.m_byModuleData[i][j - 2].and(@x11) <> @x00)) &
| (j < 3 | !(me.m_byModuleData[i][j - 3].and(@x11) <> @x00)) &
| (j < 4 | !(me.m_byModuleData[i][j - 4].and(@x11) <> @x00))) |
|((j >= me.m_nSymbleSize - 8 | !(me.m_byModuleData[i][j + 8].and(@x11) <> @x00)) &
| (j >= me.m_nSymbleSize - 9 | !(me.m_byModuleData[i][j + 9].and(@x11) <> @x00)) &
| (j >= me.m_nSymbleSize - 10 | !(me.m_byModuleData[i][j +10].and(@x11) <> @x00))))
do nPenalty :+ 40
end if
end if
end for
end for
{同一行における 1:1:3:1:1 比率(暗:明:暗:明:暗)のパターン}
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 7)
if(((j = 0) | (!(me.m_byModuleData[j - 1][i].and(@x11) <> @x00))) & {明 または シンボル外}
| ( me.m_byModuleData[j ][i].and(@x11) <> @x00) & {暗 - 1}
| (!(me.m_byModuleData[j + 1][i].and(@x11) <> @x00)) & {明 - 1}
| ( me.m_byModuleData[j + 2][i].and(@x11) <> @x00) & {暗 ┐ }
| ( me.m_byModuleData[j + 3][i].and(@x11) <> @x00) & {暗 │3}
| ( me.m_byModuleData[j + 4][i].and(@x11) <> @x00) & {暗 ┘ }
| (!(me.m_byModuleData[j + 5][i].and(@x11) <> @x00)) & {明 - 1}
| ( me.m_byModuleData[j + 6][i].and(@x11) <> @x00) & {暗 - 1}
|((j = me.m_nSymbleSize - 7) | (!(me.m_byModuleData[j + 7][i].and(@x11) <> @x00)))) {明 または シンボル外}
{前または後に4以上の明パターン}
if( ((j < 2 | !(me.m_byModuleData[j - 2][i].and(@x11) <> @x00)) &
| (j < 3 | !(me.m_byModuleData[j - 3][i].and(@x11) <> @x00)) &
| (j < 4 | !(me.m_byModuleData[j - 4][i].and(@x11) <> @x00))) |
|((j >= me.m_nSymbleSize - 8 | !(me.m_byModuleData[j + 8][i].and(@x11) <> @x00)) &
| (j >= me.m_nSymbleSize - 9 | !(me.m_byModuleData[j + 9][i].and(@x11) <> @x00)) &
| (j >= me.m_nSymbleSize - 10 | !(me.m_byModuleData[j +10][i].and(@x11) <> @x00))))
do nPenalty :+ 40
end if
end if
end for
end for
{全体に対する暗モジュールの占める割合}
var nCount: int :: 0
for i(0, me.m_nSymbleSize - 1)
for j(0, me.m_nSymbleSize - 1)
if(! (me.m_byModuleData[i][j].and(@x11) <> @x00))
do nCount :+ 1
end if
end for
end for
do nPenalty :+ ((50 - ((nCount * 100) / (me.m_nSymbleSize * me.m_nSymbleSize))).abs() / 5) * 10
ret nPenalty
end func
+*func toStr(): []char
var retVal: []char :: ""
for y(0, me.m_nSymbleSize - 1)
for x(0, me.m_nSymbleSize - 1)
if(me.m_byModuleData[x][y] <> @x00)
do retVal :~ "0"
else
do retVal :~ " "
end if
end for
do retVal :~ "\n"
end for
ret retVal
end func
+func draw(x0: float, y0: float, size: float, bCellSizeMode: bool)
var cellSize: float
if(bCellSizeMode)
do cellSize :: size
else
do cellSize :: size / (me.m_nSymbleSize + 2 * @QR_MARGIN) $ float
end if
do draw@rect(x0, y0, (me.m_nSymbleSize + 2 * @QR_MARGIN) $ float * cellSize, (me.m_nSymbleSize + 2 * @QR_MARGIN) $ float * cellSize, 0xFFFFFFFF)
for x(0, me.m_nSymbleSize - 1)
for y(0, me.m_nSymbleSize - 1)
if(me.m_byModuleData[x][y] <> @x00)
do draw@rect(x0 + (x + @QR_MARGIN) $ float * cellSize, y0 + (y + @QR_MARGIN) $ float * cellSize, cellSize, cellSize, 0xFF000000)
else
do draw@rect(x0 + (x + @QR_MARGIN) $ float * cellSize, y0 + (y + @QR_MARGIN) $ float * cellSize, cellSize, cellSize, 0xFFFFFFFF)
end if
end for
end for
end func
end class
func memmove(toByte8s: []bit8, fromByte8s: []bit8, startIndex: int, num: int)
var i: int :: 0
for j(startIndex, startIndex + num - 1)
do toByte8s[i] :: fromByte8s[j]
do i :+ 1
end for
end func