この記事は【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