QRCodeDecoder.cs
资源名称:QRCodeLib.rar [点击查看]
上传用户:tjjgrl
上传日期:2019-04-04
资源大小:1010k
文件大小:15k
源码类别:
电子政务应用
开发平台:
C#
- using System;
- using System.Text;
- using QRCodeImage = ThoughtWorks.QRCode.Codec.Data.QRCodeImage;
- using QRCodeSymbol = ThoughtWorks.QRCode.Codec.Data.QRCodeSymbol;
- using ReedSolomon = ThoughtWorks.QRCode.Codec.Ecc.ReedSolomon;
- using DecodingFailedException = ThoughtWorks.QRCode.ExceptionHandler.DecodingFailedException;
- using InvalidDataBlockException = ThoughtWorks.QRCode.ExceptionHandler.InvalidDataBlockException;
- using SymbolNotFoundException = ThoughtWorks.QRCode.ExceptionHandler.SymbolNotFoundException;
- using Point = ThoughtWorks.QRCode.Geom.Point;
- using QRCodeDataBlockReader = ThoughtWorks.QRCode.Codec.Reader.QRCodeDataBlockReader;
- using QRCodeImageReader = ThoughtWorks.QRCode.Codec.Reader.QRCodeImageReader;
- using DebugCanvas = ThoughtWorks.QRCode.Codec.Util.DebugCanvas;
- using DebugCanvasAdapter = ThoughtWorks.QRCode.Codec.Util.DebugCanvasAdapter;
- using QRCodeUtility = ThoughtWorks.QRCode.Codec.Util.QRCodeUtility;
- namespace ThoughtWorks.QRCode.Codec
- {
- public class QRCodeDecoder
- {
- internal QRCodeSymbol qrCodeSymbol;
- internal int numTryDecode;
- internal System.Collections.ArrayList results;
- internal System.Collections.ArrayList lastResults = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
- internal static DebugCanvas canvas;
- internal QRCodeImageReader imageReader;
- internal int numLastCorrections;
- internal bool correctionSucceeded;
- public static DebugCanvas Canvas
- {
- get
- {
- return QRCodeDecoder.canvas;
- }
- set
- {
- QRCodeDecoder.canvas = value;
- }
- }
- virtual internal Point[] AdjustPoints
- {
- get
- {
- // note that adjusts affect dependently
- // i.e. below means (0,0), (2,3), (3,4), (1,2), (2,1), (1,1), (-1,-1)
- // Point[] adjusts = {new Point(0,0), new Point(2,3), new Point(1,1),
- // new Point(-2,-2), new Point(1,-1), new Point(-1,0), new Point(-2,-2)};
- System.Collections.ArrayList adjustPoints = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
- for (int d = 0; d < 4; d++)
- adjustPoints.Add(new Point(1, 1));
- int lastX = 0, lastY = 0;
- for (int y = 0; y > - 4; y--)
- {
- for (int x = 0; x > - 4; x--)
- {
- if (x != y && ((x + y) % 2 == 0))
- {
- adjustPoints.Add(new Point(x - lastX, y - lastY));
- lastX = x;
- lastY = y;
- }
- }
- }
- Point[] adjusts = new Point[adjustPoints.Count];
- for (int i = 0; i < adjusts.Length; i++)
- adjusts[i] = (Point) adjustPoints[i];
- return adjusts;
- }
- }
- internal class DecodeResult
- {
- internal int numCorrections;
- internal bool correctionSucceeded;
- internal sbyte[] decodedBytes;
- private QRCodeDecoder enclosingInstance;
- public DecodeResult(QRCodeDecoder enclosingInstance, sbyte[] decodedBytes, int numErrors, bool correctionSucceeded)
- {
- InitBlock(enclosingInstance);
- this.decodedBytes = decodedBytes;
- this.numCorrections = numErrors;
- this.correctionSucceeded = correctionSucceeded;
- }
- private void InitBlock(QRCodeDecoder enclosingInstance)
- {
- this.enclosingInstance = enclosingInstance;
- }
- virtual public sbyte[] DecodedBytes
- {
- get
- {
- return decodedBytes;
- }
- }
- virtual public int NumErrors
- {
- get
- {
- return numCorrections;
- }
- }
- virtual public bool CorrectionSucceeded
- {
- get
- {
- return correctionSucceeded;
- }
- }
- public QRCodeDecoder Enclosing_Instance
- {
- get
- {
- return enclosingInstance;
- }
- }
- }
- public QRCodeDecoder()
- {
- numTryDecode = 0;
- results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
- QRCodeDecoder.canvas = new DebugCanvasAdapter();
- }
- /* public byte[] decode(QRCodeImage qrCodeImage) throws DecodingFailedException{
- canvas.println("Decoding started.");
- int[][] intImage = imageToIntArray(qrCodeImage);
- try {
- QRCodeImageReader reader = new QRCodeImageReader();
- qrCodeSymbol = reader.getQRCodeSymbol(intImage);
- } catch (SymbolNotFoundException e) {
- throw new DecodingFailedException(e.getMessage());
- }
- canvas.println("Created QRCode symbol.");
- canvas.println("Reading symbol.");
- canvas.println("Version: " + qrCodeSymbol.getVersionReference());
- canvas.println("Mask pattern: " + qrCodeSymbol.getMaskPatternRefererAsString());
- int[] blocks = qrCodeSymbol.getBlocks();
- canvas.println("Correcting data errors.");
- int[] dataBlocks = correctDataBlocks(blocks);
- try {
- byte[] decodedByteArray =
- getDecodedByteArray(dataBlocks, qrCodeSymbol.getVersion());
- canvas.println("Decoding finished.");
- return decodedByteArray;
- } catch (InvalidDataBlockException e) {
- throw new DecodingFailedException(e.getMessage());
- }
- }*/
- public virtual sbyte[] decodeBytes(QRCodeImage qrCodeImage)
- {
- Point[] adjusts = AdjustPoints;
- System.Collections.ArrayList results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
- while (numTryDecode < adjusts.Length)
- {
- try
- {
- DecodeResult result = decode(qrCodeImage, adjusts[numTryDecode]);
- if (result.CorrectionSucceeded)
- {
- return result.DecodedBytes;
- }
- else
- {
- results.Add(result);
- canvas.println("Decoding succeeded but could not correct");
- canvas.println("all errors. Retrying..");
- }
- }
- catch (DecodingFailedException dfe)
- {
- if (dfe.Message.IndexOf("Finder Pattern") >= 0)
- throw dfe;
- }
- finally
- {
- numTryDecode += 1;
- }
- }
- if (results.Count == 0)
- throw new DecodingFailedException("Give up decoding");
- int lowestErrorIndex = - 1;
- int lowestError = System.Int32.MaxValue;
- for (int i = 0; i < results.Count; i++)
- {
- DecodeResult result = (DecodeResult) results[i];
- if (result.NumErrors < lowestError)
- {
- lowestError = result.NumErrors;
- lowestErrorIndex = i;
- }
- }
- canvas.println("All trials need for correct error");
- canvas.println("Reporting #" + (lowestErrorIndex) + " that,");
- canvas.println("corrected minimum errors (" + lowestError + ")");
- canvas.println("Decoding finished.");
- return ((DecodeResult) results[lowestErrorIndex]).DecodedBytes;
- }
- public virtual String decode(QRCodeImage qrCodeImage, Encoding encoding)
- {
- sbyte[] data = decodeBytes(qrCodeImage);
- byte[] byteData = new byte[data.Length];
- Buffer.BlockCopy(data, 0, byteData, 0, byteData.Length);
- /*
- char[] decodedData = new char[data.Length];
- for (int i = 0; i < data.Length; i++)
- {
- decodedData[i] = Convert.to(data[i]);
- }
- return new String(decodedData);
- */
- String decodedData;
- decodedData = encoding.GetString(byteData);
- return decodedData;
- }
- public virtual String decode(QRCodeImage qrCodeImage)
- {
- sbyte[] data = decodeBytes(qrCodeImage);
- byte[] byteData = new byte[data.Length];
- Buffer.BlockCopy(data, 0, byteData, 0, byteData.Length);
- Encoding encoding;
- if (QRCodeUtility.IsUnicode(byteData))
- {
- encoding = Encoding.Unicode;
- }
- else
- {
- encoding = Encoding.ASCII;
- }
- String decodedData;
- decodedData = encoding.GetString(byteData);
- return decodedData;
- }
- internal virtual DecodeResult decode(QRCodeImage qrCodeImage, Point adjust)
- {
- try
- {
- if (numTryDecode == 0)
- {
- canvas.println("Decoding started");
- int[][] intImage = imageToIntArray(qrCodeImage);
- imageReader = new QRCodeImageReader();
- qrCodeSymbol = imageReader.getQRCodeSymbol(intImage);
- }
- else
- {
- canvas.println("--");
- canvas.println("Decoding restarted #" + (numTryDecode));
- qrCodeSymbol = imageReader.getQRCodeSymbolWithAdjustedGrid(adjust);
- }
- }
- catch (SymbolNotFoundException e)
- {
- throw new DecodingFailedException(e.Message);
- }
- canvas.println("Created QRCode symbol.");
- canvas.println("Reading symbol.");
- canvas.println("Version: " + qrCodeSymbol.VersionReference);
- canvas.println("Mask pattern: " + qrCodeSymbol.MaskPatternRefererAsString);
- // blocks contains all (data and RS) blocks in QR Code symbol
- int[] blocks = qrCodeSymbol.Blocks;
- canvas.println("Correcting data errors.");
- // now blocks turn to data blocks (corrected and extracted from original blocks)
- blocks = correctDataBlocks(blocks);
- try
- {
- sbyte[] decodedByteArray = getDecodedByteArray(blocks, qrCodeSymbol.Version, qrCodeSymbol.NumErrorCollectionCode);
- return new DecodeResult(this, decodedByteArray, numLastCorrections, correctionSucceeded);
- }
- catch (InvalidDataBlockException e)
- {
- canvas.println(e.Message);
- throw new DecodingFailedException(e.Message);
- }
- }
- internal virtual int[][] imageToIntArray(QRCodeImage image)
- {
- int width = image.Width;
- int height = image.Height;
- int[][] intImage = new int[width][];
- for (int i = 0; i < width; i++)
- {
- intImage[i] = new int[height];
- }
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- intImage[x][y] = image.getPixel(x, y);
- }
- }
- return intImage;
- }
- internal virtual int[] correctDataBlocks(int[] blocks)
- {
- int numCorrections = 0;
- int dataCapacity = qrCodeSymbol.DataCapacity;
- int[] dataBlocks = new int[dataCapacity];
- int numErrorCollectionCode = qrCodeSymbol.NumErrorCollectionCode;
- int numRSBlocks = qrCodeSymbol.NumRSBlocks;
- int eccPerRSBlock = numErrorCollectionCode / numRSBlocks;
- if (numRSBlocks == 1)
- {
- ReedSolomon corrector = new ReedSolomon(blocks, eccPerRSBlock);
- corrector.correct();
- numCorrections += corrector.NumCorrectedErrors;
- if (numCorrections > 0)
- canvas.println(System.Convert.ToString(numCorrections) + " data errors corrected.");
- else
- canvas.println("No errors found.");
- numLastCorrections = numCorrections;
- correctionSucceeded = corrector.CorrectionSucceeded;
- return blocks;
- }
- else
- {
- //we have to interleave data blocks because symbol has 2 or more RS blocks
- int numLongerRSBlocks = dataCapacity % numRSBlocks;
- if (numLongerRSBlocks == 0)
- {
- //symbol has only 1 type of RS block
- int lengthRSBlock = dataCapacity / numRSBlocks;
- int[][] tmpArray = new int[numRSBlocks][];
- for (int i = 0; i < numRSBlocks; i++)
- {
- tmpArray[i] = new int[lengthRSBlock];
- }
- int[][] RSBlocks = tmpArray;
- //obtain RS blocks
- for (int i = 0; i < numRSBlocks; i++)
- {
- for (int j = 0; j < lengthRSBlock; j++)
- {
- RSBlocks[i][j] = blocks[j * numRSBlocks + i];
- }
- ReedSolomon corrector = new ReedSolomon(RSBlocks[i], eccPerRSBlock);
- corrector.correct();
- numCorrections += corrector.NumCorrectedErrors;
- correctionSucceeded = corrector.CorrectionSucceeded;
- }
- //obtain only data part
- int p = 0;
- for (int i = 0; i < numRSBlocks; i++)
- {
- for (int j = 0; j < lengthRSBlock - eccPerRSBlock; j++)
- {
- dataBlocks[p++] = RSBlocks[i][j];
- }
- }
- }
- else
- {
- //symbol has 2 types of RS blocks
- int lengthShorterRSBlock = dataCapacity / numRSBlocks;
- int lengthLongerRSBlock = dataCapacity / numRSBlocks + 1;
- int numShorterRSBlocks = numRSBlocks - numLongerRSBlocks;
- int[][] tmpArray2 = new int[numShorterRSBlocks][];
- for (int i2 = 0; i2 < numShorterRSBlocks; i2++)
- {
- tmpArray2[i2] = new int[lengthShorterRSBlock];
- }
- int[][] shorterRSBlocks = tmpArray2;
- int[][] tmpArray3 = new int[numLongerRSBlocks][];
- for (int i3 = 0; i3 < numLongerRSBlocks; i3++)
- {
- tmpArray3[i3] = new int[lengthLongerRSBlock];
- }
- int[][] longerRSBlocks = tmpArray3;
- for (int i = 0; i < numRSBlocks; i++)
- {
- if (i < numShorterRSBlocks)
- {
- //get shorter RS Block(s)
- int mod = 0;
- for (int j = 0; j < lengthShorterRSBlock; j++)
- {
- if (j == lengthShorterRSBlock - eccPerRSBlock)
- mod = numLongerRSBlocks;
- shorterRSBlocks[i][j] = blocks[j * numRSBlocks + i + mod];
- }
- ReedSolomon corrector = new ReedSolomon(shorterRSBlocks[i], eccPerRSBlock);
- corrector.correct();
- numCorrections += corrector.NumCorrectedErrors;
- correctionSucceeded = corrector.CorrectionSucceeded;
- }
- else
- {
- //get longer RS Blocks
- int mod = 0;
- for (int j = 0; j < lengthLongerRSBlock; j++)
- {
- if (j == lengthShorterRSBlock - eccPerRSBlock)
- mod = numShorterRSBlocks;
- longerRSBlocks[i - numShorterRSBlocks][j] = blocks[j * numRSBlocks + i - mod];
- }
- ReedSolomon corrector = new ReedSolomon(longerRSBlocks[i - numShorterRSBlocks], eccPerRSBlock);
- corrector.correct();
- numCorrections += corrector.NumCorrectedErrors;
- correctionSucceeded = corrector.CorrectionSucceeded;
- }
- }
- int p = 0;
- for (int i = 0; i < numRSBlocks; i++)
- {
- if (i < numShorterRSBlocks)
- {
- for (int j = 0; j < lengthShorterRSBlock - eccPerRSBlock; j++)
- {
- dataBlocks[p++] = shorterRSBlocks[i][j];
- }
- }
- else
- {
- for (int j = 0; j < lengthLongerRSBlock - eccPerRSBlock; j++)
- {
- dataBlocks[p++] = longerRSBlocks[i - numShorterRSBlocks][j];
- }
- }
- }
- }
- if (numCorrections > 0)
- canvas.println(System.Convert.ToString(numCorrections) + " data errors corrected.");
- else
- canvas.println("No errors found.");
- numLastCorrections = numCorrections;
- return dataBlocks;
- }
- }
- internal virtual sbyte[] getDecodedByteArray(int[] blocks, int version, int numErrorCorrectionCode)
- {
- sbyte[] byteArray;
- QRCodeDataBlockReader reader = new QRCodeDataBlockReader(blocks, version, numErrorCorrectionCode);
- try
- {
- byteArray = reader.DataByte;
- }
- catch (InvalidDataBlockException e)
- {
- throw e;
- }
- return byteArray;
- }
- internal virtual String getDecodedString(int[] blocks, int version, int numErrorCorrectionCode)
- {
- String dataString = null;
- QRCodeDataBlockReader reader = new QRCodeDataBlockReader(blocks, version, numErrorCorrectionCode);
- try
- {
- dataString = reader.DataString;
- }
- catch (System.IndexOutOfRangeException e)
- {
- throw new InvalidDataBlockException(e.Message);
- }
- return dataString;
- }
- }
- }