Skip to content

Commit

Permalink
Switch to enum
Browse files Browse the repository at this point in the history
  • Loading branch information
cozmo committed Aug 15, 2018
1 parent 0be6075 commit 26e4ad2
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 61 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ This data is in the same form as the [`ImageData`](https://developer.mozilla.org
- `width` - The width of the image you wish to decode.
- `height` - The height of the image you wish to decode.
- `options` (optional) - Additional options.
- `attemptInverted` - (default: `true`) - Should jsQR attempt to invert the image to find QR codes with white modules on black backgrounds instead of the black modules on white background. This option defaults to true for backwards compatibility but causes a ~50% performance hit, and will probably be disabled in future versions.
- `inversionAttempts` - (`attemptBoth` (default), `dontInvert`, `onlyInvert`, or `invertFirst`) - Should jsQR attempt to invert the image to find QR codes with white modules on black backgrounds instead of the black modules on white background. This option defaults to `attemptBoth` for backwards compatibility but causes a ~50% performance hit, and will probably be default to `dontInvert` in future versions.
### Return value
If a QR is able to be decoded the library will return an object with the following keys.
Expand Down
1 change: 0 additions & 1 deletion dist/BitMatrix.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ export declare class BitMatrix {
get(x: number, y: number): boolean;
set(x: number, y: number, v: boolean): void;
setRegion(left: number, top: number, width: number, height: number, v: boolean): void;
getInverted(): BitMatrix;
}
8 changes: 7 additions & 1 deletion dist/binarizer/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
import { BitMatrix } from "../BitMatrix";
export declare function binarize(data: Uint8ClampedArray, width: number, height: number): BitMatrix;
export declare function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean): {
binarized: BitMatrix;
inverted: BitMatrix;
} | {
binarized: BitMatrix;
inverted?: undefined;
};
4 changes: 2 additions & 2 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface QRCode {
};
}
export interface Options {
attemptInverted?: boolean;
inversionAttempts?: "dontInvert" | "onlyInvert" | "attemptBoth" | "invertFirst";
}
declare function jsQR(data: Uint8ClampedArray, width: number, height: number, options?: Options): QRCode | null;
declare function jsQR(data: Uint8ClampedArray, width: number, height: number, providedOptions?: Options): QRCode | null;
export default jsQR;
46 changes: 29 additions & 17 deletions dist/jsQR.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ var BitMatrix = /** @class */ (function () {
}
}
};
BitMatrix.prototype.getInverted = function () {
return new BitMatrix(this.data.map(function (d) { return d === 0 ? 1 : 0; }), this.width);
};
return BitMatrix;
}());
exports.BitMatrix = BitMatrix;
Expand Down Expand Up @@ -358,17 +355,20 @@ function scan(matrix) {
};
}
var defaultOptions = {
attemptInverted: true,
inversionAttempts: "attemptBoth",
};
function jsQR(data, width, height, options) {
var actualOpts = defaultOptions;
function jsQR(data, width, height, providedOptions) {
if (providedOptions === void 0) { providedOptions = {}; }
var options = defaultOptions;
Object.keys(options || {}).forEach(function (opt) {
actualOpts[opt] = options[opt];
options[opt] = providedOptions[opt] || options[opt];
});
var binarized = binarizer_1.binarize(data, width, height);
var result = scan(binarized);
if (!result && actualOpts.attemptInverted) {
result = scan(binarized.getInverted());
var shouldInvert = options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst";
var tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst";
var _a = binarizer_1.binarize(data, width, height, shouldInvert), binarized = _a.binarized, inverted = _a.inverted;
var result = scan(tryInvertedFirst ? inverted : binarized);
if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) {
result = scan(tryInvertedFirst ? binarized : inverted);
}
return result;
}
Expand Down Expand Up @@ -403,7 +403,7 @@ var Matrix = /** @class */ (function () {
};
return Matrix;
}());
function binarize(data, width, height) {
function binarize(data, width, height, returnInverted) {
if (data.length !== width * height * 4) {
throw new Error("Malformed data passed to binarizer.");
}
Expand Down Expand Up @@ -460,6 +460,10 @@ function binarize(data, width, height) {
}
}
var binarized = BitMatrix_1.BitMatrix.createEmpty(width, height);
var inverted = null;
if (returnInverted) {
inverted = BitMatrix_1.BitMatrix.createEmpty(width, height);
}
for (var verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {
for (var hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {
var left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3);
Expand All @@ -471,15 +475,23 @@ function binarize(data, width, height) {
}
}
var threshold = sum / 25;
for (var x = 0; x < REGION_SIZE; x++) {
for (var y = 0; y < REGION_SIZE; y++) {
var lum = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y);
binarized.set(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y, lum <= threshold);
for (var xRegion = 0; xRegion < REGION_SIZE; xRegion++) {
for (var yRegion = 0; yRegion < REGION_SIZE; yRegion++) {
var x = hortizontalRegion * REGION_SIZE + xRegion;
var y = verticalRegion * REGION_SIZE + yRegion;
var lum = greyscalePixels.get(x, y);
binarized.set(x, y, lum <= threshold);
if (returnInverted) {
inverted.set(x, y, !(lum <= threshold));
}
}
}
}
}
return binarized;
if (returnInverted) {
return { binarized: binarized, inverted: inverted };
}
return { binarized: binarized };
}
exports.binarize = binarize;

Expand Down
2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ <h1>jsQR Demo</h1>
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
var code = jsQR(imageData.data, imageData.width, imageData.height, {
attemptInverted: false,
inversionAttempts: "dontInvert",
});
if (code) {
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
Expand Down
46 changes: 29 additions & 17 deletions docs/jsQR.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ var BitMatrix = /** @class */ (function () {
}
}
};
BitMatrix.prototype.getInverted = function () {
return new BitMatrix(this.data.map(function (d) { return d === 0 ? 1 : 0; }), this.width);
};
return BitMatrix;
}());
exports.BitMatrix = BitMatrix;
Expand Down Expand Up @@ -358,17 +355,20 @@ function scan(matrix) {
};
}
var defaultOptions = {
attemptInverted: true,
inversionAttempts: "attemptBoth",
};
function jsQR(data, width, height, options) {
var actualOpts = defaultOptions;
function jsQR(data, width, height, providedOptions) {
if (providedOptions === void 0) { providedOptions = {}; }
var options = defaultOptions;
Object.keys(options || {}).forEach(function (opt) {
actualOpts[opt] = options[opt];
options[opt] = providedOptions[opt] || options[opt];
});
var binarized = binarizer_1.binarize(data, width, height);
var result = scan(binarized);
if (!result && actualOpts.attemptInverted) {
result = scan(binarized.getInverted());
var shouldInvert = options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst";
var tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst";
var _a = binarizer_1.binarize(data, width, height, shouldInvert), binarized = _a.binarized, inverted = _a.inverted;
var result = scan(tryInvertedFirst ? inverted : binarized);
if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) {
result = scan(tryInvertedFirst ? binarized : inverted);
}
return result;
}
Expand Down Expand Up @@ -403,7 +403,7 @@ var Matrix = /** @class */ (function () {
};
return Matrix;
}());
function binarize(data, width, height) {
function binarize(data, width, height, returnInverted) {
if (data.length !== width * height * 4) {
throw new Error("Malformed data passed to binarizer.");
}
Expand Down Expand Up @@ -460,6 +460,10 @@ function binarize(data, width, height) {
}
}
var binarized = BitMatrix_1.BitMatrix.createEmpty(width, height);
var inverted = null;
if (returnInverted) {
inverted = BitMatrix_1.BitMatrix.createEmpty(width, height);
}
for (var verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {
for (var hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {
var left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3);
Expand All @@ -471,15 +475,23 @@ function binarize(data, width, height) {
}
}
var threshold = sum / 25;
for (var x = 0; x < REGION_SIZE; x++) {
for (var y = 0; y < REGION_SIZE; y++) {
var lum = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y);
binarized.set(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y, lum <= threshold);
for (var xRegion = 0; xRegion < REGION_SIZE; xRegion++) {
for (var yRegion = 0; yRegion < REGION_SIZE; yRegion++) {
var x = hortizontalRegion * REGION_SIZE + xRegion;
var y = verticalRegion * REGION_SIZE + yRegion;
var lum = greyscalePixels.get(x, y);
binarized.set(x, y, lum <= threshold);
if (returnInverted) {
inverted.set(x, y, !(lum <= threshold));
}
}
}
}
}
return binarized;
if (returnInverted) {
return { binarized: binarized, inverted: inverted };
}
return { binarized: binarized };
}
exports.binarize = binarize;

Expand Down
4 changes: 0 additions & 4 deletions src/BitMatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,4 @@ export class BitMatrix {
}
}
}

public getInverted() {
return new BitMatrix(this.data.map(d => d === 0 ? 1 : 0), this.width);
}
}
25 changes: 18 additions & 7 deletions src/binarizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Matrix {
}
}

export function binarize(data: Uint8ClampedArray, width: number, height: number): BitMatrix {
export function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean) {
if (data.length !== width * height * 4) {
throw new Error("Malformed data passed to binarizer.");
}
Expand Down Expand Up @@ -88,6 +88,10 @@ export function binarize(data: Uint8ClampedArray, width: number, height: number)
}

const binarized = BitMatrix.createEmpty(width, height);
let inverted: BitMatrix = null;
if (returnInverted) {
inverted = BitMatrix.createEmpty(width, height);
}
for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {
for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {
const left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3);
Expand All @@ -99,14 +103,21 @@ export function binarize(data: Uint8ClampedArray, width: number, height: number)
}
}
const threshold = sum / 25;
for (let x = 0; x < REGION_SIZE; x++) {
for (let y = 0; y < REGION_SIZE; y++) {
const lum = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y);
binarized.set(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y, lum <= threshold);
for (let xRegion = 0; xRegion < REGION_SIZE; xRegion++) {
for (let yRegion = 0; yRegion < REGION_SIZE; yRegion++) {
const x = hortizontalRegion * REGION_SIZE + xRegion;
const y = verticalRegion * REGION_SIZE + yRegion;
const lum = greyscalePixels.get(x, y);
binarized.set(x, y, lum <= threshold);
if (returnInverted) {
inverted.set(x, y, !(lum <= threshold));
}
}
}
}
}

return binarized;
if (returnInverted) {
return { binarized, inverted };
}
return { binarized };
}
Binary file added src/decoder/test-data/zeros.bin
Binary file not shown.
22 changes: 12 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,26 @@ function scan(matrix: BitMatrix): QRCode | null {
}

export interface Options {
attemptInverted?: boolean;
inversionAttempts?: "dontInvert" | "onlyInvert" | "attemptBoth" | "invertFirst";
}

const defaultOptions: Options = {
attemptInverted: true,
inversionAttempts: "attemptBoth",
};

function jsQR(data: Uint8ClampedArray, width: number, height: number, options?: Options): QRCode | null {
function jsQR(data: Uint8ClampedArray, width: number, height: number, providedOptions: Options = {}): QRCode | null {

const actualOpts = defaultOptions;
Object.keys(options || {}).forEach(opt => {
(actualOpts as any)[opt] = (options as any)[opt];
const options = defaultOptions;
Object.keys(options || {}).forEach(opt => { // Sad implementation of Object.assign since we target es5 not es6
(options as any)[opt] = (providedOptions as any)[opt] || (options as any)[opt];
});

const binarized = binarize(data, width, height);
let result = scan(binarized);
if (!result && actualOpts.attemptInverted) {
result = scan(binarized.getInverted());
const shouldInvert = options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst";
const tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst";
const {binarized, inverted} = binarize(data, width, height, shouldInvert);
let result = scan(tryInvertedFirst ? inverted : binarized);
if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) {
result = scan(tryInvertedFirst ? binarized : inverted);
}
return result;
}
Expand Down

0 comments on commit 26e4ad2

Please sign in to comment.