QRCodeDataBlockReader.cs
资源名称:QRCodeLib.rar [点击查看]
上传用户:tjjgrl
上传日期:2019-04-04
资源大小:1010k
文件大小:13k
源码类别:
电子政务应用
开发平台:
C#
- using System;
- using QRCodeDecoder = ThoughtWorks.QRCode.Codec.QRCodeDecoder;
- using InvalidDataBlockException = ThoughtWorks.QRCode.ExceptionHandler.InvalidDataBlockException;
- using DebugCanvas = ThoughtWorks.QRCode.Codec.Util.DebugCanvas;
- using SystemUtils = ThoughtWorks.QRCode.Codec.Util.SystemUtils;
- namespace ThoughtWorks.QRCode.Codec.Reader
- {
- public class QRCodeDataBlockReader
- {
- virtual internal int NextMode
- {
- get
- {
- //canvas.println("data blocks:"+ (blocks.length - numErrorCorrectionCode));
- if ((blockPointer > blocks.Length - numErrorCorrectionCode - 2))
- return 0;
- else
- return getNextBits(4);
- }
- }
- virtual public sbyte[] DataByte
- {
- get
- {
- canvas.println("Reading data blocks.");
- System.IO.MemoryStream output = new System.IO.MemoryStream();
- try
- {
- do
- {
- int mode = NextMode;
- //canvas.println("mode: " + mode);
- if (mode == 0)
- {
- if (output.Length > 0)
- break;
- else
- throw new InvalidDataBlockException("Empty data block");
- }
- //if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
- // break;
- //}
- if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI)
- {
- /* canvas.println("Invalid mode: " + mode);
- mode = guessMode(mode);
- canvas.println("Guessed mode: " + mode); */
- throw new InvalidDataBlockException("Invalid mode: " + mode + " in (block:" + blockPointer + " bit:" + bitPointer + ")");
- }
- dataLength = getDataLength(mode);
- if (dataLength < 1)
- throw new InvalidDataBlockException("Invalid data length: " + dataLength);
- //canvas.println("length: " + dataLength);
- switch (mode)
- {
- case MODE_NUMBER:
- //canvas.println("Mode: Figure");
- sbyte[] temp_sbyteArray;
- temp_sbyteArray = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getFigureString(dataLength)));
- output.Write(SystemUtils.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);
- break;
- case MODE_ROMAN_AND_NUMBER:
- //canvas.println("Mode: Roman&Figure");
- sbyte[] temp_sbyteArray2;
- temp_sbyteArray2 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getRomanAndFigureString(dataLength)));
- output.Write(SystemUtils.ToByteArray(temp_sbyteArray2), 0, temp_sbyteArray2.Length);
- break;
- case MODE_8BIT_BYTE:
- //canvas.println("Mode: 8bit Byte");
- sbyte[] temp_sbyteArray3;
- temp_sbyteArray3 = get8bitByteArray(dataLength);
- output.Write(SystemUtils.ToByteArray(temp_sbyteArray3), 0, temp_sbyteArray3.Length);
- break;
- case MODE_KANJI:
- //canvas.println("Mode: Kanji");
- sbyte[] temp_sbyteArray4;
- temp_sbyteArray4 = SystemUtils.ToSByteArray(SystemUtils.ToByteArray(getKanjiString(dataLength)));
- output.Write(SystemUtils.ToByteArray(temp_sbyteArray4), 0, temp_sbyteArray4.Length);
- break;
- }
- //
- //canvas.println("DataLength: " + dataLength);
- //Console.out.println(dataString);
- }
- while (true);
- }
- catch (System.IndexOutOfRangeException e)
- {
- SystemUtils.WriteStackTrace(e, Console.Error);
- throw new InvalidDataBlockException("Data Block Error in (block:" + blockPointer + " bit:" + bitPointer + ")");
- }
- catch (System.IO.IOException e)
- {
- throw new InvalidDataBlockException(e.Message);
- }
- return SystemUtils.ToSByteArray(output.ToArray());
- }
- }
- virtual public String DataString
- {
- get
- {
- canvas.println("Reading data blocks...");
- String dataString = "";
- do
- {
- int mode = NextMode;
- canvas.println("mode: " + mode);
- if (mode == 0)
- break;
- //if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
- // break;
- //}
- if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI)
- {
- // mode = guessMode(mode);
- // do not guesswork
- //Console.out.println("guessed mode: " + mode);
- }
- dataLength = getDataLength(mode);
- canvas.println(System.Convert.ToString(blocks[blockPointer]));
- System.Console.Out.WriteLine("length: " + dataLength);
- switch (mode)
- {
- case MODE_NUMBER:
- //canvas.println("Mode: Figure");
- dataString += getFigureString(dataLength);
- break;
- case MODE_ROMAN_AND_NUMBER:
- //canvas.println("Mode: Roman&Figure");
- dataString += getRomanAndFigureString(dataLength);
- break;
- case MODE_8BIT_BYTE:
- //canvas.println("Mode: 8bit Byte");
- dataString += get8bitByteString(dataLength);
- break;
- case MODE_KANJI:
- //canvas.println("Mode: Kanji");
- dataString += getKanjiString(dataLength);
- break;
- }
- //canvas.println("DataLength: " + dataLength);
- //Console.out.println(dataString);
- }
- while (true);
- System.Console.Out.WriteLine("");
- return dataString;
- }
- }
- internal int[] blocks;
- internal int dataLengthMode;
- internal int blockPointer;
- internal int bitPointer;
- internal int dataLength;
- internal int numErrorCorrectionCode;
- internal DebugCanvas canvas;
- const int MODE_NUMBER = 1;
- const int MODE_ROMAN_AND_NUMBER = 2;
- const int MODE_8BIT_BYTE = 4;
- const int MODE_KANJI = 8;
- int[][] sizeOfDataLengthInfo = new int[][] { new int[] { 10, 9, 8, 8 }, new int[] { 12, 11, 16, 10 }, new int[] { 14, 13, 16, 12 } };
- public QRCodeDataBlockReader(int[] blocks, int version, int numErrorCorrectionCode)
- {
- blockPointer = 0;
- bitPointer = 7;
- dataLength = 0;
- this.blocks = blocks;
- this.numErrorCorrectionCode = numErrorCorrectionCode;
- if (version <= 9)
- dataLengthMode = 0;
- else if (version >= 10 && version <= 26)
- dataLengthMode = 1;
- else if (version >= 27 && version <= 40)
- dataLengthMode = 2;
- canvas = QRCodeDecoder.Canvas;
- }
- internal virtual int getNextBits(int numBits)
- {
- int bits = 0;
- if (numBits < bitPointer + 1)
- {
- // next word fits into current data block
- int mask = 0;
- for (int i = 0; i < numBits; i++)
- {
- mask += (1 << i);
- }
- mask <<= (bitPointer - numBits + 1);
- bits = (blocks[blockPointer] & mask) >> (bitPointer - numBits + 1);
- bitPointer -= numBits;
- return bits;
- }
- else if (numBits < bitPointer + 1 + 8)
- {
- // next word crosses 2 data blocks
- int mask1 = 0;
- for (int i = 0; i < bitPointer + 1; i++)
- {
- mask1 += (1 << i);
- }
- bits = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1));
- blockPointer++;
- bits += ((blocks[blockPointer]) >> (8 - (numBits - (bitPointer + 1))));
- bitPointer = bitPointer - numBits % 8;
- if (bitPointer < 0)
- {
- bitPointer = 8 + bitPointer;
- }
- return bits;
- }
- else if (numBits < bitPointer + 1 + 16)
- {
- // next word crosses 3 data blocks
- int mask1 = 0; // mask of first block
- int mask3 = 0; // mask of 3rd block
- //bitPointer + 1 : number of bits of the 1st block
- //8 : number of the 2nd block (note that use already 8bits because next word uses 3 data blocks)
- //numBits - (bitPointer + 1 + 8) : number of bits of the 3rd block
- for (int i = 0; i < bitPointer + 1; i++)
- {
- mask1 += (1 << i);
- }
- int bitsFirstBlock = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1));
- blockPointer++;
- int bitsSecondBlock = blocks[blockPointer] << (numBits - (bitPointer + 1 + 8));
- blockPointer++;
- for (int i = 0; i < numBits - (bitPointer + 1 + 8); i++)
- {
- mask3 += (1 << i);
- }
- mask3 <<= 8 - (numBits - (bitPointer + 1 + 8));
- int bitsThirdBlock = (blocks[blockPointer] & mask3) >> (8 - (numBits - (bitPointer + 1 + 8)));
- bits = bitsFirstBlock + bitsSecondBlock + bitsThirdBlock;
- bitPointer = bitPointer - (numBits - 8) % 8;
- if (bitPointer < 0)
- {
- bitPointer = 8 + bitPointer;
- }
- return bits;
- }
- else
- {
- System.Console.Out.WriteLine("ERROR!");
- return 0;
- }
- }
- internal virtual int guessMode(int mode)
- {
- //correct modes: 0001 0010 0100 1000
- //possible data: 0000 0011 0101 1001 0110 1010 1100
- // 0111 1101 1011 1110 1111
- // MODE_NUMBER = 1;
- // MODE_ROMAN_AND_NUMBER = 2;
- // MODE_8BIT_BYTE = 4;
- // MODE_KANJI = 8;
- switch (mode)
- {
- case 3:
- return MODE_NUMBER;
- case 5:
- return MODE_8BIT_BYTE;
- case 6:
- return MODE_8BIT_BYTE;
- case 7:
- return MODE_8BIT_BYTE;
- case 9:
- return MODE_KANJI;
- case 10:
- return MODE_KANJI;
- case 11:
- return MODE_KANJI;
- case 12:
- return MODE_8BIT_BYTE;
- case 13:
- return MODE_8BIT_BYTE;
- case 14:
- return MODE_8BIT_BYTE;
- case 15:
- return MODE_8BIT_BYTE;
- default:
- return MODE_KANJI;
- }
- }
- internal virtual int getDataLength(int modeIndicator)
- {
- int index = 0;
- while (true)
- {
- if ((modeIndicator >> index) == 1)
- break;
- index++;
- }
- return getNextBits(sizeOfDataLengthInfo[dataLengthMode][index]);
- }
- internal virtual String getFigureString(int dataLength)
- {
- int length = dataLength;
- int intData = 0;
- String strData = "";
- do
- {
- if (length >= 3)
- {
- intData = getNextBits(10);
- if (intData < 100)
- strData += "0";
- if (intData < 10)
- strData += "0";
- length -= 3;
- }
- else if (length == 2)
- {
- intData = getNextBits(7);
- if (intData < 10)
- strData += "0";
- length -= 2;
- }
- else if (length == 1)
- {
- intData = getNextBits(4);
- length -= 1;
- }
- strData += System.Convert.ToString(intData);
- }
- while (length > 0);
- return strData;
- }
- internal virtual String getRomanAndFigureString(int dataLength)
- {
- int length = dataLength;
- int intData = 0;
- String strData = "";
- 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', ' ', '$', '%', '*', '+', '-', '.', '/', ':'};
- do
- {
- if (length > 1)
- {
- intData = getNextBits(11);
- int firstLetter = intData / 45;
- int secondLetter = intData % 45;
- strData += System.Convert.ToString(tableRomanAndFigure[firstLetter]);
- strData += System.Convert.ToString(tableRomanAndFigure[secondLetter]);
- length -= 2;
- }
- else if (length == 1)
- {
- intData = getNextBits(6);
- strData += System.Convert.ToString(tableRomanAndFigure[intData]);
- length -= 1;
- }
- }
- while (length > 0);
- return strData;
- }
- public virtual sbyte[] get8bitByteArray(int dataLength)
- {
- int length = dataLength;
- int intData = 0;
- System.IO.MemoryStream output = new System.IO.MemoryStream();
- do
- {
- canvas.println("Length: " + length);
- intData = getNextBits(8);
- output.WriteByte((byte) intData);
- length--;
- }
- while (length > 0);
- return SystemUtils.ToSByteArray(output.ToArray());
- }
- internal virtual String get8bitByteString(int dataLength)
- {
- int length = dataLength;
- int intData = 0;
- String strData = "";
- do
- {
- intData = getNextBits(8);
- strData += (char) intData;
- length--;
- }
- while (length > 0);
- return strData;
- }
- internal virtual String getKanjiString(int dataLength)
- {
- int length = dataLength;
- int intData = 0;
- String unicodeString = "";
- do
- {
- intData = getNextBits(13);
- int lowerByte = intData % 0xC0;
- int higherByte = intData / 0xC0;
- int tempWord = (higherByte << 8) + lowerByte;
- int shiftjisWord = 0;
- if (tempWord + 0x8140 <= 0x9FFC)
- {
- // between 8140 - 9FFC on Shift_JIS character set
- shiftjisWord = tempWord + 0x8140;
- }
- else
- {
- // between E040 - EBBF on Shift_JIS character set
- shiftjisWord = tempWord + 0xC140;
- }
- sbyte[] tempByte = new sbyte[2];
- tempByte[0] = (sbyte) (shiftjisWord >> 8);
- tempByte[1] = (sbyte) (shiftjisWord & 0xFF);
- unicodeString += new String(SystemUtils.ToCharArray(SystemUtils.ToByteArray(tempByte)));
- length--;
- }
- while (length > 0);
- return unicodeString;
- }
- }
- }