Files
SuperVPN/output/Libraries/MessagingToolkit.QRCode/MessagingToolkit/QRCode/Codec/QRCodeDecoder.cs
2025-10-09 09:57:24 +09:00

407 lines
9.8 KiB
C#

using System;
using System.Collections;
using System.Text;
using MessagingToolkit.QRCode.Codec.Data;
using MessagingToolkit.QRCode.Codec.Ecc;
using MessagingToolkit.QRCode.Codec.Reader;
using MessagingToolkit.QRCode.Codec.Util;
using MessagingToolkit.QRCode.ExceptionHandler;
using MessagingToolkit.QRCode.Geom;
namespace MessagingToolkit.QRCode.Codec;
public class QRCodeDecoder
{
internal class DecodeResult
{
internal int numCorrections;
internal bool correctionSucceeded;
internal sbyte[] decodedBytes;
private QRCodeDecoder enclosingInstance;
public virtual sbyte[] DecodedBytes => decodedBytes;
public virtual int NumErrors => numCorrections;
public virtual bool CorrectionSucceeded => correctionSucceeded;
public QRCodeDecoder Enclosing_Instance => enclosingInstance;
public DecodeResult(QRCodeDecoder enclosingInstance, sbyte[] decodedBytes, int numErrors, bool correctionSucceeded)
{
InitBlock(enclosingInstance);
this.decodedBytes = decodedBytes;
numCorrections = numErrors;
this.correctionSucceeded = correctionSucceeded;
}
private void InitBlock(QRCodeDecoder enclosingInstance)
{
this.enclosingInstance = enclosingInstance;
}
}
internal QRCodeSymbol qrCodeSymbol;
internal int numTryDecode;
internal ArrayList results;
internal ArrayList lastResults = ArrayList.Synchronized(new ArrayList(10));
internal static DebugCanvas canvas;
internal QRCodeImageReader imageReader;
internal int numLastCorrections;
internal bool correctionSucceeded;
public static DebugCanvas Canvas
{
get
{
return canvas;
}
set
{
canvas = value;
}
}
internal virtual Point[] AdjustPoints
{
get
{
ArrayList arrayList = ArrayList.Synchronized(new ArrayList(10));
for (int i = 0; i < 4; i++)
{
arrayList.Add(new Point(1, 1));
}
int num = 0;
int num2 = 0;
for (int num3 = 0; num3 > -4; num3--)
{
for (int num4 = 0; num4 > -4; num4--)
{
if (num4 != num3 && (num4 + num3) % 2 == 0)
{
arrayList.Add(new Point(num4 - num, num3 - num2));
num = num4;
num2 = num3;
}
}
}
Point[] array = new Point[arrayList.Count];
for (int j = 0; j < array.Length; j++)
{
array[j] = (Point)arrayList[j];
}
return array;
}
}
public QRCodeDecoder()
{
numTryDecode = 0;
results = ArrayList.Synchronized(new ArrayList(10));
canvas = new DebugCanvasAdapter();
}
public virtual sbyte[] decodeBytes(QRCodeImage qrCodeImage)
{
Point[] adjustPoints = AdjustPoints;
ArrayList arrayList = ArrayList.Synchronized(new ArrayList(10));
while (numTryDecode < adjustPoints.Length)
{
try
{
DecodeResult decodeResult = decode(qrCodeImage, adjustPoints[numTryDecode]);
if (decodeResult.CorrectionSucceeded)
{
return decodeResult.DecodedBytes;
}
arrayList.Add(decodeResult);
canvas.println("Decoding succeeded but could not correct");
canvas.println("all errors. Retrying..");
}
catch (DecodingFailedException ex)
{
if (ex.Message.IndexOf("Finder Pattern") >= 0)
{
throw ex;
}
}
finally
{
numTryDecode++;
}
}
if (arrayList.Count == 0)
{
throw new DecodingFailedException("Give up decoding");
}
int num = -1;
int num2 = int.MaxValue;
for (int i = 0; i < arrayList.Count; i++)
{
DecodeResult decodeResult = (DecodeResult)arrayList[i];
if (decodeResult.NumErrors < num2)
{
num2 = decodeResult.NumErrors;
num = i;
}
}
canvas.println("All trials need for correct error");
canvas.println("Reporting #" + num + " that,");
canvas.println("corrected minimum errors (" + num2 + ")");
canvas.println("Decoding finished.");
return ((DecodeResult)arrayList[num]).DecodedBytes;
}
public virtual string decode(QRCodeImage qrCodeImage, Encoding encoding)
{
sbyte[] array = decodeBytes(qrCodeImage);
byte[] array2 = new byte[array.Length];
Buffer.BlockCopy(array, 0, array2, 0, array2.Length);
return encoding.GetString(array2);
}
public virtual string decode(QRCodeImage qrCodeImage)
{
sbyte[] array = decodeBytes(qrCodeImage);
byte[] array2 = new byte[array.Length];
Buffer.BlockCopy(array, 0, array2, 0, array2.Length);
Encoding encoding = ((!QRCodeUtility.IsUnicode(array2)) ? Encoding.ASCII : Encoding.Unicode);
return encoding.GetString(array2);
}
internal virtual DecodeResult decode(QRCodeImage qrCodeImage, Point adjust)
{
try
{
if (numTryDecode == 0)
{
canvas.println("Decoding started");
int[][] image = imageToIntArray(qrCodeImage);
imageReader = new QRCodeImageReader();
qrCodeSymbol = imageReader.getQRCodeSymbol(image);
}
else
{
canvas.println("--");
canvas.println("Decoding restarted #" + numTryDecode);
qrCodeSymbol = imageReader.getQRCodeSymbolWithAdjustedGrid(adjust);
}
}
catch (SymbolNotFoundException ex)
{
throw new DecodingFailedException(ex.Message);
}
canvas.println("Created QRCode symbol.");
canvas.println("Reading symbol.");
canvas.println("Version: " + qrCodeSymbol.VersionReference);
canvas.println("Mask pattern: " + qrCodeSymbol.MaskPatternRefererAsString);
int[] blocks = qrCodeSymbol.Blocks;
canvas.println("Correcting data errors.");
blocks = correctDataBlocks(blocks);
try
{
sbyte[] decodedByteArray = getDecodedByteArray(blocks, qrCodeSymbol.Version, qrCodeSymbol.NumErrorCollectionCode);
return new DecodeResult(this, decodedByteArray, numLastCorrections, correctionSucceeded);
}
catch (InvalidDataBlockException ex2)
{
canvas.println(ex2.Message);
throw new DecodingFailedException(ex2.Message);
}
}
internal virtual int[][] imageToIntArray(QRCodeImage image)
{
int width = image.Width;
int height = image.Height;
int[][] array = new int[width][];
for (int i = 0; i < width; i++)
{
array[i] = new int[height];
}
for (int j = 0; j < height; j++)
{
for (int k = 0; k < width; k++)
{
array[k][j] = image.getPixel(k, j);
}
}
return array;
}
internal virtual int[] correctDataBlocks(int[] blocks)
{
int num = 0;
int dataCapacity = qrCodeSymbol.DataCapacity;
int[] array = new int[dataCapacity];
int numErrorCollectionCode = qrCodeSymbol.NumErrorCollectionCode;
int numRSBlocks = qrCodeSymbol.NumRSBlocks;
int num2 = numErrorCollectionCode / numRSBlocks;
if (numRSBlocks == 1)
{
ReedSolomon reedSolomon = new ReedSolomon(blocks, num2);
reedSolomon.correct();
num += reedSolomon.NumCorrectedErrors;
if (num > 0)
{
canvas.println(Convert.ToString(num) + " data errors corrected.");
}
else
{
canvas.println("No errors found.");
}
numLastCorrections = num;
correctionSucceeded = reedSolomon.CorrectionSucceeded;
return blocks;
}
int num3 = dataCapacity % numRSBlocks;
if (num3 == 0)
{
int num4 = dataCapacity / numRSBlocks;
int[][] array2 = new int[numRSBlocks][];
for (int i = 0; i < numRSBlocks; i++)
{
array2[i] = new int[num4];
}
int[][] array3 = array2;
for (int i = 0; i < numRSBlocks; i++)
{
for (int j = 0; j < num4; j++)
{
array3[i][j] = blocks[j * numRSBlocks + i];
}
ReedSolomon reedSolomon = new ReedSolomon(array3[i], num2);
reedSolomon.correct();
num += reedSolomon.NumCorrectedErrors;
correctionSucceeded = reedSolomon.CorrectionSucceeded;
}
int num5 = 0;
for (int i = 0; i < numRSBlocks; i++)
{
for (int j = 0; j < num4 - num2; j++)
{
array[num5++] = array3[i][j];
}
}
}
else
{
int num6 = dataCapacity / numRSBlocks;
int num7 = dataCapacity / numRSBlocks + 1;
int num8 = numRSBlocks - num3;
int[][] array4 = new int[num8][];
for (int k = 0; k < num8; k++)
{
array4[k] = new int[num6];
}
int[][] array5 = array4;
int[][] array6 = new int[num3][];
for (int l = 0; l < num3; l++)
{
array6[l] = new int[num7];
}
int[][] array7 = array6;
for (int i = 0; i < numRSBlocks; i++)
{
int num9;
ReedSolomon reedSolomon;
if (i < num8)
{
num9 = 0;
for (int j = 0; j < num6; j++)
{
if (j == num6 - num2)
{
num9 = num3;
}
array5[i][j] = blocks[j * numRSBlocks + i + num9];
}
reedSolomon = new ReedSolomon(array5[i], num2);
reedSolomon.correct();
num += reedSolomon.NumCorrectedErrors;
correctionSucceeded = reedSolomon.CorrectionSucceeded;
continue;
}
num9 = 0;
for (int j = 0; j < num7; j++)
{
if (j == num6 - num2)
{
num9 = num8;
}
array7[i - num8][j] = blocks[j * numRSBlocks + i - num9];
}
reedSolomon = new ReedSolomon(array7[i - num8], num2);
reedSolomon.correct();
num += reedSolomon.NumCorrectedErrors;
correctionSucceeded = reedSolomon.CorrectionSucceeded;
}
int num5 = 0;
for (int i = 0; i < numRSBlocks; i++)
{
if (i < num8)
{
for (int j = 0; j < num6 - num2; j++)
{
array[num5++] = array5[i][j];
}
}
else
{
for (int j = 0; j < num7 - num2; j++)
{
array[num5++] = array7[i - num8][j];
}
}
}
}
if (num > 0)
{
canvas.println(Convert.ToString(num) + " data errors corrected.");
}
else
{
canvas.println("No errors found.");
}
numLastCorrections = num;
return array;
}
internal virtual sbyte[] getDecodedByteArray(int[] blocks, int version, int numErrorCorrectionCode)
{
QRCodeDataBlockReader qRCodeDataBlockReader = new QRCodeDataBlockReader(blocks, version, numErrorCorrectionCode);
try
{
return qRCodeDataBlockReader.DataByte;
}
catch (InvalidDataBlockException ex)
{
throw ex;
}
}
internal virtual string getDecodedString(int[] blocks, int version, int numErrorCorrectionCode)
{
string text = null;
QRCodeDataBlockReader qRCodeDataBlockReader = new QRCodeDataBlockReader(blocks, version, numErrorCorrectionCode);
try
{
return qRCodeDataBlockReader.DataString;
}
catch (IndexOutOfRangeException ex)
{
throw new InvalidDataBlockException(ex.Message);
}
}
}