Skip to content

Commit f99e01d

Browse files
committed
support specifying greyscale weights and use integer approximation if desired
1 parent 01d3b0a commit f99e01d

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

src/binarizer/index.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {BitMatrix} from "../BitMatrix";
2+
import {GreyscaleWeigths} from "../index";
23

34
const REGION_SIZE = 8;
45
const MIN_DYNAMIC_RANGE = 24;
@@ -23,18 +24,35 @@ class Matrix {
2324
}
2425
}
2526

26-
export function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean) {
27+
export function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean,
28+
greyscaleWeigths: GreyscaleWeigths) {
2729
if (data.length !== width * height * 4) {
2830
throw new Error("Malformed data passed to binarizer.");
2931
}
3032
// Convert image to greyscale
3133
const greyscalePixels = new Matrix(width, height);
32-
for (let x = 0; x < width; x++) {
33-
for (let y = 0; y < height; y++) {
34-
const r = data[((y * width + x) * 4) + 0];
35-
const g = data[((y * width + x) * 4) + 1];
36-
const b = data[((y * width + x) * 4) + 2];
37-
greyscalePixels.set(x, y, 0.2126 * r + 0.7152 * g + 0.0722 * b);
34+
if (greyscaleWeigths.useIntegerApproximation) {
35+
for (let x = 0; x < width; x++) {
36+
for (let y = 0; y < height; y++) {
37+
const pixelPosition = (y * width + x) * 4;
38+
const r = data[pixelPosition];
39+
const g = data[pixelPosition + 1];
40+
const b = data[pixelPosition + 2];
41+
greyscalePixels.set(x, y,
42+
// tslint:disable-next-line no-bitwise
43+
(greyscaleWeigths.red * r + greyscaleWeigths.green * g + greyscaleWeigths.blue * b + 128) >> 8);
44+
}
45+
}
46+
} else {
47+
for (let x = 0; x < width; x++) {
48+
for (let y = 0; y < height; y++) {
49+
const pixelPosition = (y * width + x) * 4;
50+
const r = data[pixelPosition];
51+
const g = data[pixelPosition + 1];
52+
const b = data[pixelPosition + 2];
53+
greyscalePixels.set(x, y,
54+
greyscaleWeigths.red * r + greyscaleWeigths.green * g + greyscaleWeigths.blue * b);
55+
}
3856
}
3957
}
4058
const horizontalRegionCount = Math.ceil(width / REGION_SIZE);

src/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,24 @@ function scan(matrix: BitMatrix): QRCode | null {
5656

5757
export interface Options {
5858
inversionAttempts?: "dontInvert" | "onlyInvert" | "attemptBoth" | "invertFirst";
59+
greyScaleWeights?: GreyscaleWeigths;
60+
}
61+
62+
export interface GreyscaleWeigths {
63+
red: number;
64+
green: number;
65+
blue: number;
66+
useIntegerApproximation?: boolean;
5967
}
6068

6169
const defaultOptions: Options = {
6270
inversionAttempts: "attemptBoth",
71+
greyScaleWeights: {
72+
red: 0.2126,
73+
green: 0.7152,
74+
blue: 0.0722,
75+
useIntegerApproximation: false,
76+
},
6377
};
6478

6579
function jsQR(data: Uint8ClampedArray, width: number, height: number, providedOptions: Options = {}): QRCode | null {
@@ -71,7 +85,7 @@ function jsQR(data: Uint8ClampedArray, width: number, height: number, providedOp
7185

7286
const shouldInvert = options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst";
7387
const tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst";
74-
const {binarized, inverted} = binarize(data, width, height, shouldInvert);
88+
const {binarized, inverted} = binarize(data, width, height, shouldInvert, options.greyScaleWeights);
7589
let result = scan(tryInvertedFirst ? inverted : binarized);
7690
if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) {
7791
result = scan(tryInvertedFirst ? binarized : inverted);

0 commit comments

Comments
 (0)