-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Split alphanumeric encoding from QRCodeGenerator, split encoding tables #590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
1c87314
Split QRCodeGenerator further
Shane32 e10801d
update
Shane32 5d16dca
update
Shane32 f3d17c7
update
Shane32 5941456
update
Shane32 6b57a3f
update test
Shane32 7546d16
update
Shane32 5a97eb2
update
Shane32 ae3d1c2
update
Shane32 ddb443c
Separate GaloisField from CapacityTables
Shane32 e6fc48f
update
Shane32 4bd7227
remove using
Shane32 faac596
Update QRCoder/QRCodeGenerator/GaloisField.cs
Shane32 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace QRCoder; | ||
|
||
public partial class QRCodeGenerator | ||
{ | ||
/// <summary> | ||
/// This class contains the alignment patterns used in QR codes. | ||
/// </summary> | ||
private static class AlignmentPatterns | ||
{ | ||
/// <summary> | ||
/// A lookup table mapping QR code versions to their corresponding alignment patterns. | ||
/// </summary> | ||
private static readonly Dictionary<int, AlignmentPattern> _alignmentPatternTable = CreateAlignmentPatternTable(); | ||
|
||
/// <summary> | ||
/// Retrieves the alignment pattern for a specific QR code version. | ||
/// </summary> | ||
public static AlignmentPattern FromVersion(int version) => _alignmentPatternTable[version]; | ||
|
||
/// <summary> | ||
/// Creates a lookup table mapping QR code versions to their corresponding alignment patterns. | ||
/// Alignment patterns are used in QR codes to help scanners accurately read the code at high speeds and when partially obscured. | ||
/// This table provides the necessary patterns based on the QR code version which dictates the size and complexity of the QR code. | ||
/// </summary> | ||
/// <returns>A dictionary where keys are QR code version numbers and values are AlignmentPattern structures detailing the positions of alignment patterns for each version.</returns> | ||
private static Dictionary<int, AlignmentPattern> CreateAlignmentPatternTable() | ||
{ | ||
var alignmentPatternBaseValues = new int[] { 0, 0, 0, 0, 0, 0, 0, 6, 18, 0, 0, 0, 0, 0, 6, 22, 0, 0, 0, 0, 0, 6, 26, 0, 0, 0, 0, 0, 6, 30, 0, 0, 0, 0, 0, 6, 34, 0, 0, 0, 0, 0, 6, 22, 38, 0, 0, 0, 0, 6, 24, 42, 0, 0, 0, 0, 6, 26, 46, 0, 0, 0, 0, 6, 28, 50, 0, 0, 0, 0, 6, 30, 54, 0, 0, 0, 0, 6, 32, 58, 0, 0, 0, 0, 6, 34, 62, 0, 0, 0, 0, 6, 26, 46, 66, 0, 0, 0, 6, 26, 48, 70, 0, 0, 0, 6, 26, 50, 74, 0, 0, 0, 6, 30, 54, 78, 0, 0, 0, 6, 30, 56, 82, 0, 0, 0, 6, 30, 58, 86, 0, 0, 0, 6, 34, 62, 90, 0, 0, 0, 6, 28, 50, 72, 94, 0, 0, 6, 26, 50, 74, 98, 0, 0, 6, 30, 54, 78, 102, 0, 0, 6, 28, 54, 80, 106, 0, 0, 6, 32, 58, 84, 110, 0, 0, 6, 30, 58, 86, 114, 0, 0, 6, 34, 62, 90, 118, 0, 0, 6, 26, 50, 74, 98, 122, 0, 6, 30, 54, 78, 102, 126, 0, 6, 26, 52, 78, 104, 130, 0, 6, 30, 56, 82, 108, 134, 0, 6, 34, 60, 86, 112, 138, 0, 6, 30, 58, 86, 114, 142, 0, 6, 34, 62, 90, 118, 146, 0, 6, 30, 54, 78, 102, 126, 150, 6, 24, 50, 76, 102, 128, 154, 6, 28, 54, 80, 106, 132, 158, 6, 32, 58, 84, 110, 136, 162, 6, 26, 54, 82, 110, 138, 166, 6, 30, 58, 86, 114, 142, 170 }; | ||
var localAlignmentPatternTable = new Dictionary<int, AlignmentPattern>(40); | ||
|
||
for (var i = 0; i < (7 * 40); i += 7) | ||
{ | ||
var points = new List<Point>(50); | ||
for (var x = 0; x < 7; x++) | ||
{ | ||
if (alignmentPatternBaseValues[i + x] != 0) | ||
{ | ||
for (var y = 0; y < 7; y++) | ||
{ | ||
if (alignmentPatternBaseValues[i + y] != 0) | ||
{ | ||
var p = new Point(alignmentPatternBaseValues[i + x] - 2, alignmentPatternBaseValues[i + y] - 2); | ||
if (!points.Contains(p)) | ||
points.Add(p); | ||
} | ||
} | ||
} | ||
} | ||
|
||
var version = (i + 7) / 7; | ||
localAlignmentPatternTable.Add(version, new AlignmentPattern() | ||
{ | ||
Version = version, | ||
PatternPositions = points | ||
}); | ||
} | ||
return localAlignmentPatternTable; | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
|
||
namespace QRCoder; | ||
|
||
public partial class QRCodeGenerator | ||
{ | ||
/// <summary> | ||
/// Encodes alphanumeric characters (<c>0–9</c>, <c>A–Z</c> (uppercase), space, <c>$</c>, <c>%</c>, <c>*</c>, <c>+</c>, <c>-</c>, period, <c>/</c>, colon) into a binary format suitable for QR codes. | ||
/// </summary> | ||
private static class AlphanumericEncoder | ||
{ | ||
private static readonly char[] _alphanumEncTable = { ' ', '$', '%', '*', '+', '-', '.', '/', ':' }; | ||
|
||
/// <summary> | ||
/// A dictionary mapping alphanumeric characters to their respective positions used in QR code encoding. | ||
/// This includes digits 0-9, uppercase letters A-Z, and some special characters. | ||
/// </summary> | ||
private static readonly Dictionary<char, int> _alphanumEncDict = CreateAlphanumEncDict(_alphanumEncTable); | ||
|
||
/// <summary> | ||
/// Creates a dictionary mapping alphanumeric characters to their respective positions used in QR code encoding. | ||
/// This includes digits 0-9, uppercase letters A-Z, and some special characters. | ||
/// </summary> | ||
/// <returns>A dictionary mapping each supported alphanumeric character to its corresponding value.</returns> | ||
private static Dictionary<char, int> CreateAlphanumEncDict(char[] alphanumEncTable) | ||
{ | ||
var localAlphanumEncDict = new Dictionary<char, int>(45); | ||
// Add 0-9 | ||
for (char c = '0'; c <= '9'; c++) | ||
localAlphanumEncDict.Add(c, c - '0'); | ||
codebude marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Add uppercase alphabetic characters. | ||
for (char c = 'A'; c <= 'Z'; c++) | ||
localAlphanumEncDict.Add(c, localAlphanumEncDict.Count); | ||
// Add special characters from a predefined table. | ||
for (int i = 0; i < _alphanumEncTable.Length; i++) | ||
localAlphanumEncDict.Add(alphanumEncTable[i], localAlphanumEncDict.Count); | ||
return localAlphanumEncDict; | ||
} | ||
|
||
/// <summary> | ||
/// Checks if a character is present in the alphanumeric encoding table. | ||
/// </summary> | ||
public static bool CanEncode(char c) => IsInRange(c, 'A', 'Z') || Array.IndexOf(_alphanumEncTable, c) >= 0; | ||
codebude marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// <summary> | ||
/// Converts alphanumeric plain text into a binary format optimized for QR codes. | ||
/// Alphanumeric encoding packs characters into 11-bit groups for each pair of characters, | ||
/// and 6 bits for a single remaining character if the total count is odd. | ||
/// </summary> | ||
/// <param name="plainText">The alphanumeric text to be encoded, which should only contain characters valid in QR alphanumeric mode.</param> | ||
/// <returns>A BitArray representing the binary data of the encoded alphanumeric text.</returns> | ||
public static BitArray GetBitArray(string plainText) | ||
{ | ||
// Calculate the length of the BitArray needed based on the number of character pairs. | ||
var codeText = new BitArray((plainText.Length / 2) * 11 + (plainText.Length & 1) * 6); | ||
var codeIndex = 0; | ||
var index = 0; | ||
var count = plainText.Length; | ||
|
||
// Process each pair of characters. | ||
while (count >= 2) | ||
{ | ||
// Convert each pair of characters to a number by looking them up in the alphanumeric dictionary and calculating. | ||
var dec = _alphanumEncDict[plainText[index++]] * 45 + _alphanumEncDict[plainText[index++]]; | ||
// Convert the number to binary and store it in the BitArray. | ||
codeIndex = DecToBin(dec, 11, codeText, codeIndex); | ||
count -= 2; | ||
} | ||
|
||
// Handle the last character if the length is odd. | ||
if (count > 0) | ||
{ | ||
DecToBin(_alphanumEncDict[plainText[index]], 6, codeText, codeIndex); | ||
} | ||
|
||
return codeText; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.