Skip to content

Commit

Permalink
support specifying greyscale weights and use integer approximation if…
Browse files Browse the repository at this point in the history
… desired
  • Loading branch information
danimoh committed Feb 15, 2019
1 parent 01d3b0a commit f99e01d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
32 changes: 25 additions & 7 deletions src/binarizer/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {BitMatrix} from "../BitMatrix";
import {GreyscaleWeigths} from "../index";

const REGION_SIZE = 8;
const MIN_DYNAMIC_RANGE = 24;
Expand All @@ -23,18 +24,35 @@ class Matrix {
}
}

export function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean) {
export function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean,
greyscaleWeigths: GreyscaleWeigths) {
if (data.length !== width * height * 4) {
throw new Error("Malformed data passed to binarizer.");
}
// Convert image to greyscale
const greyscalePixels = new Matrix(width, height);
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const r = data[((y * width + x) * 4) + 0];
const g = data[((y * width + x) * 4) + 1];
const b = data[((y * width + x) * 4) + 2];
greyscalePixels.set(x, y, 0.2126 * r + 0.7152 * g + 0.0722 * b);
if (greyscaleWeigths.useIntegerApproximation) {
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const pixelPosition = (y * width + x) * 4;
const r = data[pixelPosition];
const g = data[pixelPosition + 1];
const b = data[pixelPosition + 2];
greyscalePixels.set(x, y,
// tslint:disable-next-line no-bitwise
(greyscaleWeigths.red * r + greyscaleWeigths.green * g + greyscaleWeigths.blue * b + 128) >> 8);
}
}
} else {
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const pixelPosition = (y * width + x) * 4;
const r = data[pixelPosition];
const g = data[pixelPosition + 1];
const b = data[pixelPosition + 2];
greyscalePixels.set(x, y,
greyscaleWeigths.red * r + greyscaleWeigths.green * g + greyscaleWeigths.blue * b);
}
}
}
const horizontalRegionCount = Math.ceil(width / REGION_SIZE);
Expand Down
16 changes: 15 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,24 @@ function scan(matrix: BitMatrix): QRCode | null {

export interface Options {
inversionAttempts?: "dontInvert" | "onlyInvert" | "attemptBoth" | "invertFirst";
greyScaleWeights?: GreyscaleWeigths;
}

export interface GreyscaleWeigths {
red: number;
green: number;
blue: number;
useIntegerApproximation?: boolean;
}

const defaultOptions: Options = {
inversionAttempts: "attemptBoth",
greyScaleWeights: {
red: 0.2126,
green: 0.7152,
blue: 0.0722,
useIntegerApproximation: false,
},
};

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

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

0 comments on commit f99e01d

Please sign in to comment.