Skip to content
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

Features/support structured append #98

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion dist/decoder/decodeData/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ export interface ECIChunk {
type: Mode.ECI;
assignmentNumber: number;
}
export declare type Chunks = Array<Chunk | ByteChunk | ECIChunk>;
export interface StructuredAppend {
type: Mode.StructuredAppend;
currentSequence: number;
totalSequence: number;
parity: number;
}
export declare type Chunks = Array<Chunk | ByteChunk | ECIChunk | StructuredAppend>;
export interface DecodedQR {
text: string;
bytes: number[];
Expand All @@ -22,5 +28,6 @@ export declare enum Mode {
Byte = "byte",
Kanji = "kanji",
ECI = "eci",
StructuredAppend = "structuredappend"
}
export declare function decode(data: Uint8ClampedArray, version: number): DecodedQR;
46 changes: 28 additions & 18 deletions dist/jsQR.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ var GenericGFPoly = /** @class */ (function () {
return this.coefficients[this.coefficients.length - 1 - degree];
};
GenericGFPoly.prototype.addOrSubtract = function (other) {
var _a;
if (this.isZero()) {
return other;
}
Expand All @@ -248,7 +249,6 @@ var GenericGFPoly = /** @class */ (function () {
sumDiff[i] = GenericGF_1.addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
}
return new GenericGFPoly(this.field, sumDiff);
var _a;
};
GenericGFPoly.prototype.multiply = function (scalar) {
if (scalar === 0) {
Expand Down Expand Up @@ -580,7 +580,7 @@ function readCodewords(matrix, version, formatInfo) {
// Read columns in pairs, from right to left
var readingUp = true;
for (var columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) {
if (columnIndex === 6) {
if (columnIndex === 6) { // Skip whole column with vertical alignment pattern;
columnIndex--;
}
for (var i = 0; i < dimension; i++) {
Expand All @@ -594,7 +594,7 @@ function readCodewords(matrix, version, formatInfo) {
bit = !bit;
}
currentByte = pushBit(bit, currentByte);
if (bitsRead === 8) {
if (bitsRead === 8) { // Whole bytes
codewords.push(currentByte);
bitsRead = 0;
currentByte = 0;
Expand All @@ -609,7 +609,7 @@ function readCodewords(matrix, version, formatInfo) {
function readVersion(matrix) {
var dimension = matrix.height;
var provisionalVersion = Math.floor((dimension - 17) / 4);
if (provisionalVersion <= 6) {
if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code
return version_1.VERSIONS[provisionalVersion - 1];
}
var topRightVersionBits = 0;
Expand Down Expand Up @@ -651,21 +651,21 @@ function readVersion(matrix) {
function readFormatInformation(matrix) {
var topLeftFormatInfoBits = 0;
for (var x = 0; x <= 8; x++) {
if (x !== 6) {
if (x !== 6) { // Skip timing pattern bit
topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits);
}
}
for (var y = 7; y >= 0; y--) {
if (y !== 6) {
if (y !== 6) { // Skip timing pattern bit
topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits);
}
}
var dimension = matrix.height;
var topRightBottomRightFormatInfoBits = 0;
for (var y = dimension - 1; y >= dimension - 7; y--) {
for (var y = dimension - 1; y >= dimension - 7; y--) { // bottom left
topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits);
}
for (var x = dimension - 8; x < dimension; x++) {
for (var x = dimension - 8; x < dimension; x++) { // top right
topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits);
}
var bestDifference = Infinity;
Expand All @@ -680,7 +680,7 @@ function readFormatInformation(matrix) {
bestFormatInfo = formatInfo;
bestDifference = difference;
}
if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) {
if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option
difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits);
if (difference < bestDifference) {
bestFormatInfo = formatInfo;
Expand Down Expand Up @@ -810,6 +810,7 @@ var Mode;
Mode["Byte"] = "byte";
Mode["Kanji"] = "kanji";
Mode["ECI"] = "eci";
Mode["StructuredAppend"] = "structuredappend";
})(Mode = exports.Mode || (exports.Mode = {}));
var ModeByte;
(function (ModeByte) {
Expand All @@ -819,7 +820,7 @@ var ModeByte;
ModeByte[ModeByte["Byte"] = 4] = "Byte";
ModeByte[ModeByte["Kanji"] = 8] = "Kanji";
ModeByte[ModeByte["ECI"] = 7] = "ECI";
// StructuredAppend = 0x3,
ModeByte[ModeByte["StructuredAppend"] = 3] = "StructuredAppend";
// FNC1FirstPosition = 0x5,
// FNC1SecondPosition = 0x9,
})(ModeByte || (ModeByte = {}));
Expand Down Expand Up @@ -926,6 +927,7 @@ function decodeKanji(stream, size) {
return { bytes: bytes, text: text };
}
function decode(data, version) {
var _a, _b, _c, _d;
var stream = new BitStream_1.BitStream(data);
// There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2).
var size = version <= 9 ? 0 : version <= 26 ? 1 : 2;
Expand Down Expand Up @@ -1004,8 +1006,15 @@ function decode(data, version) {
text: kanjiResult.text,
});
}
else if (mode === ModeByte.StructuredAppend) {
result.chunks.push({
type: Mode.StructuredAppend,
currentSequence: stream.readBits(4),
totalSequence: stream.readBits(4),
parity: stream.readBits(8),
});
}
}
var _a, _b, _c, _d;
}
exports.decode = decode;

Expand Down Expand Up @@ -8126,6 +8135,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
var GenericGF_1 = __webpack_require__(1);
var GenericGFPoly_1 = __webpack_require__(2);
function runEuclideanAlgorithm(field, a, b, R) {
var _a;
// Assume a's degree is >= b's
if (a.degree() < b.degree()) {
_a = [b, a], a = _a[0], b = _a[1];
Expand Down Expand Up @@ -8166,7 +8176,6 @@ function runEuclideanAlgorithm(field, a, b, R) {
}
var inverse = field.inverse(sigmaTildeAtZero);
return [t.multiply(inverse), r.multiply(inverse)];
var _a;
}
function findErrorLocations(field, errorLocator) {
// This is a direct application of Chien's search
Expand Down Expand Up @@ -9571,7 +9580,7 @@ var BitMatrix_1 = __webpack_require__(0);
function squareToQuadrilateral(p1, p2, p3, p4) {
var dx3 = p1.x - p2.x + p3.x - p4.x;
var dy3 = p1.y - p2.y + p3.y - p4.y;
if (dx3 === 0 && dy3 === 0) {
if (dx3 === 0 && dy3 === 0) { // Affine
return {
a11: p2.x - p1.x,
a12: p2.y - p1.y,
Expand Down Expand Up @@ -9677,6 +9686,7 @@ function sum(values) {
}
// Takes three finder patterns and organizes them into topLeft, topRight, etc
function reorderFinderPatterns(pattern1, pattern2, pattern3) {
var _a, _b, _c, _d;
// Find distances between pattern centers
var oneTwoDistance = distance(pattern1, pattern2);
var twoThreeDistance = distance(pattern2, pattern3);
Expand All @@ -9701,7 +9711,6 @@ function reorderFinderPatterns(pattern1, pattern2, pattern3) {
_d = [topRight, bottomLeft], bottomLeft = _d[0], topRight = _d[1];
}
return { bottomLeft: bottomLeft, topLeft: topLeft, topRight: topRight };
var _a, _b, _c, _d;
}
// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns
function computeDimension(topLeft, topRight, bottomLeft, matrix) {
Expand Down Expand Up @@ -9791,13 +9800,13 @@ function countBlackWhiteRunTowardsPoint(origin, end, matrix, length) {
// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes
// of the black white run. Takes a length which represents the number of switches from black to white to look for.
function countBlackWhiteRun(origin, end, matrix, length) {
var _a;
var rise = end.y - origin.y;
var run = end.x - origin.x;
var towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2));
var awayFromEnd = countBlackWhiteRunTowardsPoint(origin, { x: origin.x - run, y: origin.y - rise }, matrix, Math.ceil(length / 2));
var middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel
return (_a = awayFromEnd.concat(middleValue)).concat.apply(_a, towardsEnd);
var _a;
}
// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the "error" -
// that is the amount the run diverges from the expected ratio
Expand Down Expand Up @@ -9846,6 +9855,7 @@ function scorePattern(point, ratios, matrix) {
}
}
function locate(matrix) {
var _a;
var finderPatternQuads = [];
var activeFinderPatternQuads = [];
var alignmentPatternQuads = [];
Expand Down Expand Up @@ -9947,6 +9957,7 @@ function locate(matrix) {
})
.filter(function (q) { return !!q; }) // Filter out any rejected quads from above
.sort(function (a, b) { return a.score - b.score; })
// Now take the top finder pattern options and try to find 2 other options with a similar size.
.map(function (point, i, finderPatterns) {
if (i > MAX_FINDERPATTERNS_TO_SEARCH) {
return null;
Expand All @@ -9966,13 +9977,13 @@ function locate(matrix) {
if (finderPatternGroups.length === 0) {
return null;
}
var _a = reorderFinderPatterns(finderPatternGroups[0].points[0], finderPatternGroups[0].points[1], finderPatternGroups[0].points[2]), topRight = _a.topRight, topLeft = _a.topLeft, bottomLeft = _a.bottomLeft;
var _b = reorderFinderPatterns(finderPatternGroups[0].points[0], finderPatternGroups[0].points[1], finderPatternGroups[0].points[2]), topRight = _b.topRight, topLeft = _b.topLeft, bottomLeft = _b.bottomLeft;
// Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code.
// We'll use these to help find the alignment pattern but also later when we do the extraction.
var dimension;
var moduleSize;
try {
(_b = computeDimension(topLeft, topRight, bottomLeft, matrix), dimension = _b.dimension, moduleSize = _b.moduleSize);
(_a = computeDimension(topLeft, topRight, bottomLeft, matrix), dimension = _a.dimension, moduleSize = _a.moduleSize);
}
catch (e) {
return null;
Expand Down Expand Up @@ -10013,7 +10024,6 @@ function locate(matrix) {
topLeft: { x: topLeft.x, y: topLeft.y },
topRight: { x: topRight.x, y: topRight.y },
};
var _b;
}
exports.locate = locate;

Expand Down
Loading