QRCodeDataBlockReader.cs
上传用户:tjjgrl
上传日期:2019-04-04
资源大小:1010k
文件大小:13k
源码类别:

电子政务应用

开发平台:

C#

  1. using System;
  2. using QRCodeDecoder = ThoughtWorks.QRCode.Codec.QRCodeDecoder;
  3. using InvalidDataBlockException = ThoughtWorks.QRCode.ExceptionHandler.InvalidDataBlockException;
  4. using DebugCanvas = ThoughtWorks.QRCode.Codec.Util.DebugCanvas;
  5. using SystemUtils = ThoughtWorks.QRCode.Codec.Util.SystemUtils;
  6. namespace ThoughtWorks.QRCode.Codec.Reader
  7. {
  8. public class QRCodeDataBlockReader
  9. {
  10. virtual internal int NextMode
  11. {
  12. get
  13. {
  14. //canvas.println("data blocks:"+ (blocks.length - numErrorCorrectionCode));
  15. if ((blockPointer > blocks.Length - numErrorCorrectionCode - 2))
  16. return 0;
  17. else
  18. return getNextBits(4);
  19. }
  20. }
  21. virtual public sbyte[] DataByte
  22. {
  23. get
  24. {
  25. canvas.println("Reading data blocks.");
  26. System.IO.MemoryStream output = new System.IO.MemoryStream();
  27. try
  28. {
  29. do 
  30. {
  31. int mode = NextMode;
  32. //canvas.println("mode: " + mode);
  33. if (mode == 0)
  34. {
  35. if (output.Length > 0)
  36. break;
  37. else
  38. throw new InvalidDataBlockException("Empty data block");
  39. }
  40. //if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
  41. // break;
  42. //}
  43. if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI)
  44. {
  45. /* canvas.println("Invalid mode: " + mode);
  46. mode = guessMode(mode);
  47. canvas.println("Guessed mode: " + mode); */
  48. throw new InvalidDataBlockException("Invalid mode: " + mode + " in (block:" + blockPointer + " bit:" + bitPointer + ")");
  49. }
  50. dataLength = getDataLength(mode);
  51. if (dataLength < 1)
  52. throw new InvalidDataBlockException("Invalid data length: " + dataLength);
  53. //canvas.println("length: " + dataLength);
  54. switch (mode)
  55. {
  56. case MODE_NUMBER: 
  57. //canvas.println("Mode: Figure");
  58. sbyte[] temp_sbyteArray;
  59. temp_sbyteArray = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getFigureString(dataLength)));
  60. output.Write(SystemUtils.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);
  61. break;
  62. case MODE_ROMAN_AND_NUMBER: 
  63. //canvas.println("Mode: Roman&Figure");
  64. sbyte[] temp_sbyteArray2;
  65. temp_sbyteArray2 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getRomanAndFigureString(dataLength)));
  66. output.Write(SystemUtils.ToByteArray(temp_sbyteArray2), 0, temp_sbyteArray2.Length);
  67. break;
  68. case MODE_8BIT_BYTE: 
  69. //canvas.println("Mode: 8bit Byte");
  70. sbyte[] temp_sbyteArray3;
  71. temp_sbyteArray3 = get8bitByteArray(dataLength);
  72. output.Write(SystemUtils.ToByteArray(temp_sbyteArray3), 0, temp_sbyteArray3.Length);
  73. break;
  74. case MODE_KANJI: 
  75. //canvas.println("Mode: Kanji");
  76. sbyte[] temp_sbyteArray4;
  77. temp_sbyteArray4 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getKanjiString(dataLength)));
  78. output.Write(SystemUtils.ToByteArray(temp_sbyteArray4), 0, temp_sbyteArray4.Length);
  79. break;
  80. }
  81. //
  82. //canvas.println("DataLength: " + dataLength);
  83. //Console.out.println(dataString);
  84. }
  85. while (true);
  86. }
  87. catch (System.IndexOutOfRangeException e)
  88. {
  89. SystemUtils.WriteStackTrace(e, Console.Error);
  90. throw new InvalidDataBlockException("Data Block Error in (block:" + blockPointer + " bit:" + bitPointer + ")");
  91. }
  92. catch (System.IO.IOException e)
  93. {
  94. throw new InvalidDataBlockException(e.Message);
  95. }
  96. return SystemUtils.ToSByteArray(output.ToArray());
  97. }
  98. }
  99. virtual public String DataString
  100. {
  101. get
  102. {
  103. canvas.println("Reading data blocks...");
  104. String dataString = "";
  105. do 
  106. {
  107. int mode = NextMode;
  108. canvas.println("mode: " + mode);
  109. if (mode == 0)
  110. break;
  111. //if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
  112. // break;
  113. //}
  114. if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI)
  115. {
  116. // mode = guessMode(mode);
  117. // do not guesswork
  118. //Console.out.println("guessed mode: " + mode);
  119. }
  120. dataLength = getDataLength(mode);
  121. canvas.println(System.Convert.ToString(blocks[blockPointer]));
  122. System.Console.Out.WriteLine("length: " + dataLength);
  123. switch (mode)
  124. {
  125. case MODE_NUMBER: 
  126. //canvas.println("Mode: Figure");
  127. dataString += getFigureString(dataLength);
  128. break;
  129. case MODE_ROMAN_AND_NUMBER: 
  130. //canvas.println("Mode: Roman&Figure");
  131. dataString += getRomanAndFigureString(dataLength);
  132. break;
  133. case MODE_8BIT_BYTE: 
  134. //canvas.println("Mode: 8bit Byte");
  135. dataString += get8bitByteString(dataLength);
  136. break;
  137. case MODE_KANJI: 
  138. //canvas.println("Mode: Kanji");
  139. dataString += getKanjiString(dataLength);
  140. break;
  141. }
  142. //canvas.println("DataLength: " + dataLength);
  143. //Console.out.println(dataString);
  144. }
  145. while (true);
  146. System.Console.Out.WriteLine("");
  147. return dataString;
  148. }
  149. }
  150. internal int[] blocks;
  151. internal int dataLengthMode;
  152. internal int blockPointer;
  153. internal int bitPointer;
  154. internal int dataLength;
  155. internal int numErrorCorrectionCode;
  156. internal DebugCanvas canvas;
  157. const  int MODE_NUMBER = 1;
  158.     const int MODE_ROMAN_AND_NUMBER = 2;
  159.     const int MODE_8BIT_BYTE = 4;
  160.     const int MODE_KANJI = 8;
  161.     int[][] sizeOfDataLengthInfo = new int[][] { new int[] { 10, 9, 8, 8 }, new int[] { 12, 11, 16, 10 }, new int[] { 14, 13, 16, 12 } };
  162. public QRCodeDataBlockReader(int[] blocks, int version, int numErrorCorrectionCode)
  163. {
  164. blockPointer = 0;
  165. bitPointer = 7;
  166. dataLength = 0;
  167. this.blocks = blocks;
  168. this.numErrorCorrectionCode = numErrorCorrectionCode;
  169. if (version <= 9)
  170. dataLengthMode = 0;
  171. else if (version >= 10 && version <= 26)
  172. dataLengthMode = 1;
  173. else if (version >= 27 && version <= 40)
  174. dataLengthMode = 2;
  175. canvas = QRCodeDecoder.Canvas;
  176. }
  177. internal virtual int getNextBits(int numBits)
  178. {
  179. int bits = 0;
  180. if (numBits < bitPointer + 1)
  181. {
  182. // next word fits into current data block
  183. int mask = 0;
  184. for (int i = 0; i < numBits; i++)
  185. {
  186. mask += (1 << i);
  187. }
  188. mask <<= (bitPointer - numBits + 1);
  189. bits = (blocks[blockPointer] & mask) >> (bitPointer - numBits + 1);
  190. bitPointer -= numBits;
  191. return bits;
  192. }
  193. else if (numBits < bitPointer + 1 + 8)
  194. {
  195. // next word crosses 2 data blocks
  196. int mask1 = 0;
  197. for (int i = 0; i < bitPointer + 1; i++)
  198. {
  199. mask1 += (1 << i);
  200. }
  201. bits = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1));
  202.                 blockPointer++;
  203. bits += ((blocks[blockPointer]) >> (8 - (numBits - (bitPointer + 1))));
  204. bitPointer = bitPointer - numBits % 8;
  205. if (bitPointer < 0)
  206. {
  207. bitPointer = 8 + bitPointer;
  208. }
  209. return bits;
  210. }
  211. else if (numBits < bitPointer + 1 + 16)
  212. {
  213. // next word crosses 3 data blocks
  214. int mask1 = 0; // mask of first block
  215. int mask3 = 0; // mask of 3rd block
  216. //bitPointer + 1 : number of bits of the 1st block
  217. //8 : number of the 2nd block (note that use already 8bits because next word uses 3 data blocks)
  218. //numBits - (bitPointer + 1 + 8) : number of bits of the 3rd block 
  219. for (int i = 0; i < bitPointer + 1; i++)
  220. {
  221. mask1 += (1 << i);
  222. }
  223. int bitsFirstBlock = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1));
  224. blockPointer++;
  225. int bitsSecondBlock = blocks[blockPointer] << (numBits - (bitPointer + 1 + 8));
  226. blockPointer++;
  227. for (int i = 0; i < numBits - (bitPointer + 1 + 8); i++)
  228. {
  229. mask3 += (1 << i);
  230. }
  231. mask3 <<= 8 - (numBits - (bitPointer + 1 + 8));
  232. int bitsThirdBlock = (blocks[blockPointer] & mask3) >> (8 - (numBits - (bitPointer + 1 + 8)));
  233. bits = bitsFirstBlock + bitsSecondBlock + bitsThirdBlock;
  234. bitPointer = bitPointer - (numBits - 8) % 8;
  235. if (bitPointer < 0)
  236. {
  237. bitPointer = 8 + bitPointer;
  238. }
  239. return bits;
  240. }
  241. else
  242. {
  243. System.Console.Out.WriteLine("ERROR!");
  244. return 0;
  245. }
  246. }
  247. internal virtual int guessMode(int mode)
  248. {
  249. //correct modes: 0001 0010 0100 1000
  250. //possible data: 0000 0011 0101 1001 0110 1010 1100
  251. //               0111 1101 1011 1110 1111
  252. // MODE_NUMBER = 1;
  253. // MODE_ROMAN_AND_NUMBER = 2;
  254. // MODE_8BIT_BYTE = 4;
  255. // MODE_KANJI = 8;
  256. switch (mode)
  257. {
  258. case 3: 
  259. return MODE_NUMBER;
  260. case 5: 
  261. return MODE_8BIT_BYTE;
  262. case 6: 
  263. return MODE_8BIT_BYTE;
  264. case 7: 
  265. return MODE_8BIT_BYTE;
  266. case 9: 
  267. return MODE_KANJI;
  268. case 10: 
  269. return MODE_KANJI;
  270. case 11: 
  271. return MODE_KANJI;
  272. case 12: 
  273. return MODE_8BIT_BYTE;
  274. case 13: 
  275. return MODE_8BIT_BYTE;
  276. case 14: 
  277. return MODE_8BIT_BYTE;
  278. case 15: 
  279. return MODE_8BIT_BYTE;
  280. default: 
  281. return MODE_KANJI;
  282. }
  283. }
  284. internal virtual int getDataLength(int modeIndicator)
  285. {
  286. int index = 0;
  287. while (true)
  288. {
  289. if ((modeIndicator >> index) == 1)
  290. break;
  291. index++;
  292. }
  293. return getNextBits(sizeOfDataLengthInfo[dataLengthMode][index]);
  294. }
  295. internal virtual String getFigureString(int dataLength)
  296. {
  297. int length = dataLength;
  298. int intData = 0;
  299. String strData = "";
  300. do 
  301. {
  302. if (length >= 3)
  303. {
  304. intData = getNextBits(10);
  305. if (intData < 100)
  306. strData += "0";
  307. if (intData < 10)
  308. strData += "0";
  309. length -= 3;
  310. }
  311. else if (length == 2)
  312. {
  313. intData = getNextBits(7);
  314. if (intData < 10)
  315. strData += "0";
  316. length -= 2;
  317. }
  318. else if (length == 1)
  319. {
  320. intData = getNextBits(4);
  321. length -= 1;
  322. }
  323. strData += System.Convert.ToString(intData);
  324. }
  325. while (length > 0);
  326. return strData;
  327. }
  328. internal virtual String getRomanAndFigureString(int dataLength)
  329. {
  330. int length = dataLength;
  331. int intData = 0;
  332. String strData = "";
  333. char[] tableRomanAndFigure = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':'};
  334. do 
  335. {
  336. if (length > 1)
  337. {
  338. intData = getNextBits(11);
  339. int firstLetter = intData / 45;
  340. int secondLetter = intData % 45;
  341. strData += System.Convert.ToString(tableRomanAndFigure[firstLetter]);
  342. strData += System.Convert.ToString(tableRomanAndFigure[secondLetter]);
  343. length -= 2;
  344. }
  345. else if (length == 1)
  346. {
  347. intData = getNextBits(6);
  348. strData += System.Convert.ToString(tableRomanAndFigure[intData]);
  349. length -= 1;
  350. }
  351. }
  352. while (length > 0);
  353. return strData;
  354. }
  355. public virtual sbyte[] get8bitByteArray(int dataLength)
  356. {
  357. int length = dataLength;
  358. int intData = 0;
  359. System.IO.MemoryStream output = new System.IO.MemoryStream();
  360. do 
  361. {
  362.                 canvas.println("Length: " + length);
  363. intData = getNextBits(8);
  364. output.WriteByte((byte) intData);
  365. length--;
  366. }
  367. while (length > 0);
  368. return SystemUtils.ToSByteArray(output.ToArray());
  369. }
  370. internal virtual String get8bitByteString(int dataLength)
  371. {
  372. int length = dataLength;
  373. int intData = 0;
  374. String strData = "";
  375. do 
  376. {
  377. intData = getNextBits(8);
  378. strData += (char) intData;
  379. length--;
  380. }
  381. while (length > 0);
  382. return strData;
  383. }
  384. internal virtual String getKanjiString(int dataLength)
  385. {
  386. int length = dataLength;
  387. int intData = 0;
  388. String unicodeString = "";
  389. do 
  390. {
  391. intData = getNextBits(13);
  392. int lowerByte = intData % 0xC0;
  393. int higherByte = intData / 0xC0;
  394. int tempWord = (higherByte << 8) + lowerByte;
  395. int shiftjisWord = 0;
  396. if (tempWord + 0x8140 <= 0x9FFC)
  397. {
  398. // between 8140 - 9FFC on Shift_JIS character set
  399. shiftjisWord = tempWord + 0x8140;
  400. }
  401. else
  402. {
  403. // between E040 - EBBF on Shift_JIS character set
  404. shiftjisWord = tempWord + 0xC140;
  405. }
  406. sbyte[] tempByte = new sbyte[2];
  407. tempByte[0] = (sbyte) (shiftjisWord >> 8);
  408. tempByte[1] = (sbyte) (shiftjisWord & 0xFF);
  409. unicodeString += new String(SystemUtils.ToCharArray(SystemUtils.ToByteArray(tempByte)));
  410. length--;
  411. }
  412. while (length > 0);
  413. return unicodeString;
  414. }
  415. }
  416. }