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,36 +1,34 @@
using System.Linq;
namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
internal static class MatrixScoreCalculator
{
internal static BitMatrix GetLowestPenaltyMatrix(this TriStateMatrix matrix, ErrorCorrectionLevel errorLevel)
{
PatternFactory patternFactory = new();
int score = int.MaxValue;
int tempScore;
TriStateMatrix result = new(matrix.Width);
TriStateMatrix triMatrix;
foreach (Pattern pattern in patternFactory.AllPatterns())
{
triMatrix = matrix.Apply(pattern, errorLevel);
tempScore = triMatrix.PenaltyScore();
if (tempScore < score)
{
score = tempScore;
result = triMatrix;
}
}
internal static BitMatrix GetLowestPenaltyMatrix(this TriStateMatrix matrix, ErrorCorrectionLevel errorLevel)
{
PatternFactory patternFactory = new();
int score = int.MaxValue;
int tempScore;
TriStateMatrix result = new(matrix.Width);
TriStateMatrix triMatrix;
foreach (Pattern pattern in patternFactory.AllPatterns())
{
triMatrix = matrix.Apply(pattern, errorLevel);
tempScore = triMatrix.PenaltyScore();
if (tempScore < score)
{
score = tempScore;
result = triMatrix;
}
}
return result;
}
return result;
}
internal static int PenaltyScore(this BitMatrix matrix)
{
PenaltyFactory penaltyFactory = new();
return
penaltyFactory
.AllRules()
.Sum(penalty => penalty.PenaltyCalculate(matrix));
}
}
internal static int PenaltyScore(this BitMatrix matrix)
{
PenaltyFactory penaltyFactory = new();
return
penaltyFactory
.AllRules()
.Sum(penalty => penalty.PenaltyCalculate(matrix));
}
}
@@ -2,5 +2,5 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
public abstract class Penalty
{
internal abstract int PenaltyCalculate(BitMatrix matrix);
}
internal abstract int PenaltyCalculate(BitMatrix matrix);
}
@@ -5,81 +5,81 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// </summary>
internal class Penalty1 : Penalty
{
/// <summary>
/// Calculate penalty value for first rule.
/// </summary>
internal override int PenaltyCalculate(BitMatrix matrix)
{
int penaltyValue = PenaltyCalculation(matrix, true) + PenaltyCalculation(matrix, false);
return penaltyValue;
}
/// <summary>
/// Calculate penalty value for first rule.
/// </summary>
internal override int PenaltyCalculate(BitMatrix matrix)
{
int penaltyValue = PenaltyCalculation(matrix, true) + PenaltyCalculation(matrix, false);
return penaltyValue;
}
private int PenaltyCalculation(BitMatrix matrix, bool isHorizontal)
{
int penalty = 0;
int width = matrix.Width;
private int PenaltyCalculation(BitMatrix matrix, bool isHorizontal)
{
int penalty = 0;
int width = matrix.Width;
int i = 0;
int j = 0;
int i = 0;
int j = 0;
while (i < width)
{
while (j < width - 4)
{
bool preBit = isHorizontal
? matrix[j + 4, i]
: matrix[i, j + 4];
int numSameBitCell = 1;
while (i < width)
{
while (j < width - 4)
{
bool preBit = isHorizontal
? matrix[j + 4, i]
: matrix[i, j + 4];
int numSameBitCell = 1;
for (int x = 1; x <= 4; x++)
{
bool bit = isHorizontal
? matrix[j + 4 - x, i]
: matrix[i, j + 4 - x];
if (bit == preBit)
{
numSameBitCell++;
}
else
{
break;
}
}
for (int x = 1; x <= 4; x++)
{
bool bit = isHorizontal
? matrix[j + 4 - x, i]
: matrix[i, j + 4 - x];
if (bit == preBit)
{
numSameBitCell++;
}
else
{
break;
}
}
if (numSameBitCell == 1)
{
j += 4;
}
else
{
int x = 5;
while ((j + x) < width)
{
bool bit = isHorizontal
? matrix[j + x, i]
: matrix[i, j + x];
if (bit == preBit)
{
numSameBitCell++;
}
else
{
break;
}
x++;
}
if (numSameBitCell >= 5)
{
penalty += (3 + (numSameBitCell - 5));
}
if (numSameBitCell == 1)
{
j += 4;
}
else
{
int x = 5;
while ((j + x) < width)
{
bool bit = isHorizontal
? matrix[j + x, i]
: matrix[i, j + x];
if (bit == preBit)
{
numSameBitCell++;
}
else
{
break;
}
x++;
}
if (numSameBitCell >= 5)
{
penalty += (3 + (numSameBitCell - 5));
}
j += x;
}
}
j = 0;
i++;
}
j += x;
}
}
j = 0;
i++;
}
return penalty;
}
}
return penalty;
}
}
@@ -5,47 +5,47 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// </summary>
internal class Penalty2 : Penalty
{
internal override int PenaltyCalculate(BitMatrix matrix)
{
int width = matrix.Width;
int x = 0;
int y = 0;
int penalty = 0;
internal override int PenaltyCalculate(BitMatrix matrix)
{
int width = matrix.Width;
int x = 0;
int y = 0;
int penalty = 0;
while (y < (width - 1))
{
while (x < (width - 1))
{
bool topR = matrix[x + 1, y];
while (y < (width - 1))
{
while (x < (width - 1))
{
bool topR = matrix[x + 1, y];
if (topR == matrix[x + 1, y + 1]) // Bottom Right
{
if (topR == matrix[x, y + 1]) // Bottom Left
{
if (topR == matrix[x, y]) // Top Left
{
penalty += 3;
x += 1;
}
else
{
x += 1;
}
}
else
{
x += 1;
}
}
else
{
x += 2;
}
}
if (topR == matrix[x + 1, y + 1]) // Bottom Right
{
if (topR == matrix[x, y + 1]) // Bottom Left
{
if (topR == matrix[x, y]) // Top Left
{
penalty += 3;
x += 1;
}
else
{
x += 1;
}
}
else
{
x += 1;
}
}
else
{
x += 2;
}
}
x = 0;
y++;
}
return penalty;
}
}
x = 0;
y++;
}
return penalty;
}
}
@@ -5,137 +5,137 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// </summary>
internal class Penalty3 : Penalty
{
/// <summary>
/// Calculate penalty value for Third rule.
/// </summary>
internal override int PenaltyCalculate(BitMatrix matrix) => PenaltyCalculation(matrix, true) + PenaltyCalculation(matrix, false);
/// <summary>
/// Calculate penalty value for Third rule.
/// </summary>
internal override int PenaltyCalculate(BitMatrix matrix) => PenaltyCalculation(matrix, true) + PenaltyCalculation(matrix, false);
private int PenaltyCalculation(BitMatrix matrix, bool isHorizontal)
{
int i = 0;
int j = 1;
int penalty = 0;
int width = matrix.Width;
bool bit;
while (i < width)
{
while (j < width - 5)
{
bit = isHorizontal
? matrix[j + 4, i]
: matrix[i, j + 4];
if (!bit)
{
bit = isHorizontal
? matrix[j, i]
: matrix[i, j];
if (!bit)
{
penalty += PatternCheck(matrix, i, j, isHorizontal);
j += 4;
}
else
{
j += 4;
}
}
else
{
for (int num = 4; num > 0; num--)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (!bit)
{
j += num;
break;
}
if (num == 1)
{
j += 5;
}
}
}
}
j = 0;
i++;
}
return penalty;
}
private int PenaltyCalculation(BitMatrix matrix, bool isHorizontal)
{
int i = 0;
int j = 1;
int penalty = 0;
int width = matrix.Width;
bool bit;
while (i < width)
{
while (j < width - 5)
{
bit = isHorizontal
? matrix[j + 4, i]
: matrix[i, j + 4];
if (!bit)
{
bit = isHorizontal
? matrix[j, i]
: matrix[i, j];
if (!bit)
{
penalty += PatternCheck(matrix, i, j, isHorizontal);
j += 4;
}
else
{
j += 4;
}
}
else
{
for (int num = 4; num > 0; num--)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (!bit)
{
j += num;
break;
}
if (num == 1)
{
j += 5;
}
}
}
}
j = 0;
i++;
}
return penalty;
}
private int PatternCheck(BitMatrix matrix, int i, int j, bool isHorizontal)
{
bool bit;
for (int num = 3; num >= 1; num--)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (!bit)
{
return 0;
}
}
private int PatternCheck(BitMatrix matrix, int i, int j, bool isHorizontal)
{
bool bit;
for (int num = 3; num >= 1; num--)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (!bit)
{
return 0;
}
}
// Check for left side and right side x ( xoxxxox ).
if ((j - 1) < 0 || (j + 1) >= matrix.Width)
{
return 0;
}
// Check for left side and right side x ( xoxxxox ).
if ((j - 1) < 0 || (j + 1) >= matrix.Width)
{
return 0;
}
bit = isHorizontal
? matrix[j + 5, i]
: matrix[i, j + 5];
if (!bit)
{
return 0;
}
bit = isHorizontal
? matrix[j + 5, i]
: matrix[i, j + 5];
if (!bit)
{
return 0;
}
bit = isHorizontal
? matrix[j - 1, i]
: matrix[i, j - 1];
if (!bit)
{
return 0;
}
bit = isHorizontal
? matrix[j - 1, i]
: matrix[i, j - 1];
if (!bit)
{
return 0;
}
if ((j - 5) >= 0)
{
for (int num = -2; num >= -5; num--)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (bit)
{
break;
}
if ((j - 5) >= 0)
{
for (int num = -2; num >= -5; num--)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (bit)
{
break;
}
if (num == -5)
{
return 40;
}
}
}
if (num == -5)
{
return 40;
}
}
}
if ((j + 9) < matrix.Width)
{
for (int num = 6; num <= 9; num++)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (bit)
{
return 0;
}
}
return 40;
}
else
{
return 0;
}
}
}
if ((j + 9) < matrix.Width)
{
for (int num = 6; num <= 9; num++)
{
bit = isHorizontal
? matrix[j + num, i]
: matrix[i, j + num];
if (bit)
{
return 0;
}
}
return 40;
}
else
{
return 0;
}
}
}
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// <summary>
@@ -7,30 +5,30 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// </summary>
internal class Penalty4 : Penalty
{
/// <summary>
/// Calculate penalty value for Fourth rule.
/// Perform O(n) search for available x modules
/// </summary>
internal override int PenaltyCalculate(BitMatrix matrix)
{
int width = matrix.Width;
int darkBitCount = 0;
/// <summary>
/// Calculate penalty value for Fourth rule.
/// Perform O(n) search for available x modules
/// </summary>
internal override int PenaltyCalculate(BitMatrix matrix)
{
int width = matrix.Width;
int darkBitCount = 0;
for (int j = 0; j < width; j++)
{
for (int i = 0; i < width; i++)
{
if (matrix[i, j])
{
darkBitCount++;
}
}
}
for (int j = 0; j < width; j++)
{
for (int i = 0; i < width; i++)
{
if (matrix[i, j])
{
darkBitCount++;
}
}
}
int matrixCount = width * width;
int matrixCount = width * width;
double ratio = (double)darkBitCount / matrixCount;
double ratio = (double)darkBitCount / matrixCount;
return Math.Abs((int)((ratio * 100) - 50)) / 5 * 10;
}
}
return Math.Abs((int)((ratio * 100) - 50)) / 5 * 10;
}
}
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// <summary>
@@ -8,23 +5,23 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// </summary>
internal class PenaltyFactory
{
internal Penalty CreateByRule(PenaltyRules penaltyRule)
{
return penaltyRule switch
{
PenaltyRules.Rule01 => new Penalty1(),
PenaltyRules.Rule02 => new Penalty2(),
PenaltyRules.Rule03 => new Penalty3(),
PenaltyRules.Rule04 => new Penalty4(),
_ => throw new ArgumentException($"Unsupport penalty rule: {penaltyRule}", nameof(penaltyRule))
};
}
internal Penalty CreateByRule(PenaltyRules penaltyRule)
{
return penaltyRule switch
{
PenaltyRules.Rule01 => new Penalty1(),
PenaltyRules.Rule02 => new Penalty2(),
PenaltyRules.Rule03 => new Penalty3(),
PenaltyRules.Rule04 => new Penalty4(),
_ => throw new ArgumentException($"Unsupport penalty rule: {penaltyRule}", nameof(penaltyRule))
};
}
internal IEnumerable<Penalty> AllRules()
{
foreach (PenaltyRules penaltyRule in Enum.GetValues(typeof(PenaltyRules)))
{
yield return CreateByRule(penaltyRule);
}
}
}
internal IEnumerable<Penalty> AllRules()
{
foreach (PenaltyRules penaltyRule in Enum.GetValues(typeof(PenaltyRules)))
{
yield return CreateByRule(penaltyRule);
}
}
}
@@ -2,8 +2,8 @@ namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
public enum PenaltyRules
{
Rule01 = 1,
Rule02 = 2,
Rule03 = 3,
Rule04 = 4
}
Rule01 = 1,
Rule02 = 2,
Rule03 = 3,
Rule04 = 4
}