This commit is contained in:
TheXamlGuy
2024-04-26 23:05:36 +01:00
parent 9f90ef693d
commit bc55c4649b
206 changed files with 3106 additions and 3204 deletions
@@ -1,4 +1,3 @@
using System;
using Gma.QrCodeNet.Encoding.Masking;
namespace Gma.QrCodeNet.Encoding.EncodingRegion;
@@ -10,105 +9,105 @@ namespace Gma.QrCodeNet.Encoding.EncodingRegion;
/// <remarks>ISO/IEC 18004:2000 Chapter 8.9 Page 53</remarks>
internal static class FormatInformation
{
/// <summary>
/// From Appendix C in JISX0510:2004 (p.65).
/// </summary>
private const int FormatInfoPoly = 0x537;
/// <summary>
/// From Appendix C in JISX0510:2004 (p.65).
/// </summary>
private const int FormatInfoPoly = 0x537;
/// <summary>
/// From Appendix C in JISX0510:2004 (p.65).
/// </summary>
private const int FormatInfoMaskPattern = 0x5412;
/// <summary>
/// From Appendix C in JISX0510:2004 (p.65).
/// </summary>
private const int FormatInfoMaskPattern = 0x5412;
/// <summary>
/// Embed format information to tristatematrix.
/// Process combination of create info bits, BCH error correction bits calculation, embed towards matrix.
/// </summary>
/// <remarks>ISO/IEC 18004:2000 Chapter 8.9 Page 53</remarks>
internal static void EmbedFormatInformation(this TriStateMatrix triMatrix, ErrorCorrectionLevel errorLevel, Pattern pattern)
{
BitList formatInfo = GetFormatInfoBits(errorLevel, pattern);
int width = triMatrix.Width;
for (int index = 0; index < 15; index++)
{
MatrixPoint point = PointForInfo1(index);
bool bit = formatInfo[index];
triMatrix[point.X, point.Y, MatrixStatus.NoMask] = bit;
/// <summary>
/// Embed format information to tristatematrix.
/// Process combination of create info bits, BCH error correction bits calculation, embed towards matrix.
/// </summary>
/// <remarks>ISO/IEC 18004:2000 Chapter 8.9 Page 53</remarks>
internal static void EmbedFormatInformation(this TriStateMatrix triMatrix, ErrorCorrectionLevel errorLevel, Pattern pattern)
{
BitList formatInfo = GetFormatInfoBits(errorLevel, pattern);
int width = triMatrix.Width;
for (int index = 0; index < 15; index++)
{
MatrixPoint point = PointForInfo1(index);
bool bit = formatInfo[index];
triMatrix[point.X, point.Y, MatrixStatus.NoMask] = bit;
if (index < 7)
{
triMatrix[8, width - 1 - index, MatrixStatus.NoMask] = bit;
}
else
{
triMatrix[width - 8 + (index - 7), 8, MatrixStatus.NoMask] = bit;
}
}
}
if (index < 7)
{
triMatrix[8, width - 1 - index, MatrixStatus.NoMask] = bit;
}
else
{
triMatrix[width - 8 + (index - 7), 8, MatrixStatus.NoMask] = bit;
}
}
}
private static MatrixPoint PointForInfo1(int bitsIndex)
{
if (bitsIndex <= 7)
{
return bitsIndex >= 6
? new MatrixPoint(bitsIndex + 1, 8)
: new MatrixPoint(bitsIndex, 8);
}
else
{
return bitsIndex == 8
? new MatrixPoint(8, 8 - (bitsIndex - 7))
: new MatrixPoint(8, 8 - (bitsIndex - 7) - 1);
}
}
private static MatrixPoint PointForInfo1(int bitsIndex)
{
if (bitsIndex <= 7)
{
return bitsIndex >= 6
? new MatrixPoint(bitsIndex + 1, 8)
: new MatrixPoint(bitsIndex, 8);
}
else
{
return bitsIndex == 8
? new MatrixPoint(8, 8 - (bitsIndex - 7))
: new MatrixPoint(8, 8 - (bitsIndex - 7) - 1);
}
}
private static BitList GetFormatInfoBits(ErrorCorrectionLevel errorLevel, Pattern pattern)
{
int formatInfo = (int)pattern.MaskPatternType;
private static BitList GetFormatInfoBits(ErrorCorrectionLevel errorLevel, Pattern pattern)
{
int formatInfo = (int)pattern.MaskPatternType;
// Pattern bits length = 3
formatInfo |= GetErrorCorrectionIndicatorBits(errorLevel) << 3;
// Pattern bits length = 3
formatInfo |= GetErrorCorrectionIndicatorBits(errorLevel) << 3;
int bchCode = BCHCalculator.CalculateBCH(formatInfo, FormatInfoPoly);
int bchCode = BCHCalculator.CalculateBCH(formatInfo, FormatInfoPoly);
// bchCode length = 10
formatInfo = (formatInfo << 10) | bchCode;
// bchCode length = 10
formatInfo = (formatInfo << 10) | bchCode;
// xor maskPattern
formatInfo ^= FormatInfoMaskPattern;
// xor maskPattern
formatInfo ^= FormatInfoMaskPattern;
BitList resultBits = new()
{
{ formatInfo, 15 }
};
BitList resultBits = new()
{
{ formatInfo, 15 }
};
if (resultBits.Count != 15)
{
throw new Exception("FormatInfoBits length is not 15");
}
else
{
return resultBits;
}
}
if (resultBits.Count != 15)
{
throw new Exception("FormatInfoBits length is not 15");
}
else
{
return resultBits;
}
}
/// <summary>
/// According Table 25 — Error correction level indicators
/// Using these bits as enum values would destroy their order which currently corresponds to error correction strength.
/// </summary>
internal static int GetErrorCorrectionIndicatorBits(ErrorCorrectionLevel errorLevel)
{
// L 01
// M 00
// Q 11
// H 10
return errorLevel switch
{
ErrorCorrectionLevel.H => 0x02,
ErrorCorrectionLevel.L => 0x01,
ErrorCorrectionLevel.M => 0x00,
ErrorCorrectionLevel.Q => 0x03,
_ => throw new ArgumentException($"Unsupported error correction level [{errorLevel}]", nameof(errorLevel))
};
}
}
/// <summary>
/// According Table 25 — Error correction level indicators
/// Using these bits as enum values would destroy their order which currently corresponds to error correction strength.
/// </summary>
internal static int GetErrorCorrectionIndicatorBits(ErrorCorrectionLevel errorLevel)
{
// L 01
// M 00
// Q 11
// H 10
return errorLevel switch
{
ErrorCorrectionLevel.H => 0x02,
ErrorCorrectionLevel.L => 0x01,
ErrorCorrectionLevel.M => 0x00,
ErrorCorrectionLevel.Q => 0x03,
_ => throw new ArgumentException($"Unsupported error correction level [{errorLevel}]", nameof(errorLevel))
};
}
}