Skip to content

Commit

Permalink
move source files around to more clearly seperate pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
cozmo committed Dec 13, 2017
1 parent ba5ad66 commit 76f8157
Show file tree
Hide file tree
Showing 15 changed files with 130 additions and 161 deletions.
3 changes: 2 additions & 1 deletion src/detector/binarizer.ts → src/binarizer/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {BitMatrix} from "../common/bitmatrix";
import {BitMatrix} from "../bitmatrix";

const REGION_SIZE = 8;
const MIN_DYNAMIC_RANGE = 24;
Expand All @@ -7,6 +7,7 @@ function numBetween(value: number, min: number, max: number): number {
return value < min ? min : value > max ? max : value;
}

// Like BitMatrix but accepts arbitry Uint8 values
class Matrix {
private data: Uint8ClampedArray;
private width: number;
Expand Down
File renamed without changes.
34 changes: 34 additions & 0 deletions src/bitmatrix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export class BitMatrix {
public static createEmpty(width: number, height: number) {
return new BitMatrix(new Uint8ClampedArray(width * height), width);
}

public width: number;
public height: number;
private data: Uint8ClampedArray;

constructor(data: Uint8ClampedArray, width: number) {
this.width = width;
this.height = data.length / width;
this.data = data;
}

public get(x: number, y: number): boolean {
if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
return false;
}
return !!this.data[y * this.width + x];
}

public set(x: number, y: number, v: boolean) {
this.data[y * this.width + x] = v ? 1 : 0;
}

public setRegion(left: number, top: number, width: number, height: number, v: boolean) {
for (let y = top; y < top + height; y++) {
for (let x = left; x < left + width; x++) {
this.set(x, y, !!v);
}
}
}
}
52 changes: 0 additions & 52 deletions src/common/bitmatrix.ts

This file was deleted.

19 changes: 0 additions & 19 deletions src/common/helpers.ts

This file was deleted.

File renamed without changes.
2 changes: 1 addition & 1 deletion src/decoder/decodeqrdata.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {BitStream} from "../common/bitstream";
import {BitStream} from "./bitstream";

function toAlphaNumericByte(value: number): number {
var ALPHANUMERIC_CHARS: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
Expand Down
55 changes: 33 additions & 22 deletions src/decoder/decoder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {BitMatrix} from "../common/bitmatrix";
import {BitMatrix} from "../bitmatrix";
import {decodeQRdata} from "./decodeqrdata";
import {numBitsDiffering} from "../common/helpers";
import {ReedSolomonDecoder} from "./reedsolomon";
import {Version, ErrorCorrectionLevel, getVersionForNumber} from "../common/version";
import {ErrorCorrectionLevel, getVersionForNumber, numBitsDiffering, Version} from "./version";

const FORMAT_INFO_MASK_QR = 0x5412;

Expand Down Expand Up @@ -69,18 +68,22 @@ interface FormatInformation {
dataMask: number
}

function copyBit(matrix: BitMatrix, x: number, y: number, versionBits: number): number {
return matrix.get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1;
}

function buildFunctionPattern(version: Version): BitMatrix {
var dimension = version.getDimensionForVersion();
var emptyArray = new Uint8ClampedArray(dimension * dimension);
var bitMatrix = new BitMatrix(emptyArray, dimension);
///BitMatrix bitMatrix = new BitMatrix(dimension);

// Top left finder pattern + separator + format
bitMatrix.setRegion(0, 0, 9, 9);
bitMatrix.setRegion(0, 0, 9, 9, true);
// Top right finder pattern + separator + format
bitMatrix.setRegion(dimension - 8, 0, 8, 9);
bitMatrix.setRegion(dimension - 8, 0, 8, 9, true);
// Bottom left finder pattern + separator + format
bitMatrix.setRegion(0, dimension - 8, 9, 8);
bitMatrix.setRegion(0, dimension - 8, 9, 8, true);

// Alignment patterns
var max = version.alignmentPatternCenters.length;
Expand All @@ -91,20 +94,20 @@ function buildFunctionPattern(version: Version): BitMatrix {
// No alignment patterns near the three finder paterns
continue;
}
bitMatrix.setRegion(version.alignmentPatternCenters[y] - 2, i, 5, 5);
bitMatrix.setRegion(version.alignmentPatternCenters[y] - 2, i, 5, 5, true);
}
}

// Vertical timing pattern
bitMatrix.setRegion(6, 9, 1, dimension - 17);
bitMatrix.setRegion(6, 9, 1, dimension - 17, true);
// Horizontal timing pattern
bitMatrix.setRegion(9, 6, dimension - 17, 1);
bitMatrix.setRegion(9, 6, dimension - 17, 1, true);

if (version.versionNumber > 6) {
// Version info, top right
bitMatrix.setRegion(dimension - 11, 0, 3, 6);
bitMatrix.setRegion(dimension - 11, 0, 3, 6, true);
// Version info, bottom left
bitMatrix.setRegion(0, dimension - 11, 6, 3);
bitMatrix.setRegion(0, dimension - 11, 6, 3, true);
}

return bitMatrix;
Expand Down Expand Up @@ -172,7 +175,7 @@ function readVersion(matrix: BitMatrix): Version {
var ijMin = dimension - 11;
for (var j = 5; j >= 0; j--) {
for (var i = dimension - 9; i >= ijMin; i--) {
versionBits = matrix.copyBit(i, j, versionBits);
versionBits = copyBit(matrix, i, j, versionBits);
}
}

Expand All @@ -185,7 +188,7 @@ function readVersion(matrix: BitMatrix): Version {
versionBits = 0;
for (var i = 5; i >= 0; i--) {
for (var j = dimension - 9; j >= ijMin; j--) {
versionBits = matrix.copyBit(i, j, versionBits);
versionBits = copyBit(matrix, i, j, versionBits);
}
}

Expand Down Expand Up @@ -252,25 +255,25 @@ function readFormatInformation(matrix: BitMatrix): FormatInformation {
// Read top-left format info bits
var formatInfoBits1 = 0;
for (var i = 0; i < 6; i++) {
formatInfoBits1 = matrix.copyBit(i, 8, formatInfoBits1);
formatInfoBits1 = copyBit(matrix, i, 8, formatInfoBits1);
}
// .. and skip a bit in the timing pattern ...
formatInfoBits1 = matrix.copyBit(7, 8, formatInfoBits1);
formatInfoBits1 = matrix.copyBit(8, 8, formatInfoBits1);
formatInfoBits1 = matrix.copyBit(8, 7, formatInfoBits1);
formatInfoBits1 = copyBit(matrix, 7, 8, formatInfoBits1);
formatInfoBits1 = copyBit(matrix, 8, 8, formatInfoBits1);
formatInfoBits1 = copyBit(matrix, 8, 7, formatInfoBits1);
// .. and skip a bit in the timing pattern ...
for (var j = 5; j >= 0; j--) {
formatInfoBits1 = matrix.copyBit(8, j, formatInfoBits1);
formatInfoBits1 = copyBit(matrix, 8, j, formatInfoBits1);
}
// Read the top-right/bottom-left pattern too
var dimension = matrix.height;
var formatInfoBits2 = 0;
var jMin = dimension - 7;
for (var j = dimension - 1; j >= jMin; j--) {
formatInfoBits2 = matrix.copyBit(8, j, formatInfoBits2);
formatInfoBits2 = copyBit(matrix, 8, j, formatInfoBits2);
}
for (var i = dimension - 8; i < dimension; i++) {
formatInfoBits2 = matrix.copyBit(i, 8, formatInfoBits2);
formatInfoBits2 = copyBit(matrix, i, 8, formatInfoBits2);
}

// parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);
Expand Down Expand Up @@ -419,7 +422,15 @@ export function decode(matrix: BitMatrix): number[] {
if (result) {
return result;
}
// Decoding didn't work, try mirroring the QR
matrix.mirror();
// Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line.
// TODO - unclear if this is actually needed?
for (let x = 0; x < matrix.width; x++) {
for (let y = x + 1; y < matrix.height; y++) {
if (matrix.get(x, y) !== matrix.get(y, x)) {
matrix.set(x, y, !matrix.get(x, y));
matrix.set(y, x, !matrix.get(y, x));
}
}
}
return decodeMatrix(matrix);
}
15 changes: 14 additions & 1 deletion src/common/version.ts → src/decoder/version.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import {numBitsDiffering} from "./helpers";
export function numBitsDiffering(a: number, b: number): number {
const BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
a ^= b; // a now has a 1 bit exactly where its bit differs with b's
// Count bits set quickly with a series of lookups:
return BITS_SET_IN_HALF_BYTE[a & 0x0F] +
BITS_SET_IN_HALF_BYTE[((a >> 4) & 0x0F)] +
BITS_SET_IN_HALF_BYTE[((a >> 8) & 0x0F)] +
BITS_SET_IN_HALF_BYTE[((a >> 12) & 0x0F)] +
BITS_SET_IN_HALF_BYTE[((a >> 16) & 0x0F)] +
BITS_SET_IN_HALF_BYTE[((a >> 20) & 0x0F)] +
BITS_SET_IN_HALF_BYTE[((a >> 24) & 0x0F)] +
BITS_SET_IN_HALF_BYTE[((a >> 28) & 0x0F)];
}


const VERSION_DECODE_INFO = [
0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
Expand Down
4 changes: 2 additions & 2 deletions src/detector/extractor.ts → src/extractor/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {BitMatrix} from "../common/bitmatrix";
import { QRLocation } from "./locator";
import {BitMatrix} from "../bitmatrix";
import {QRLocation} from "../locator";

interface Point {
x: number;
Expand Down
File renamed without changes.
43 changes: 43 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {binarize} from "./binarizer";
import {BitMatrix} from "./bitmatrix";
import {decode} from "./decoder/decoder";
import {extract} from "./extractor";
import {locate} from "./locator";

export interface Point {
x: number;
y: number;
}

export interface QRCode {
binaryData: Uint8ClampedArray;
text: string;
encodingType: "numeric" | "alphanumeric" | "byte" | "structured_append" | "eci" | "kanji";
location: {
topRightCorner: Point;
topLeftCorner: Point;
bottomRightCorner: Point;
bottomLeftCorner: Point;

topRightFinderPattern: Point;
topLeftFinderPattern: Point;
bottomLeftFinderPattern: Point;

bottomRightAlignmentPattern?: Point;
};

errorRate: number; // TODO is this the right field name?
}

// TODO - is this the name we want?
export default function readQR(data: Uint8ClampedArray, width: number, height: number): QRCode | null {
const binarized = binarize(data, width, height);
const location = locate(binarized);
if (!location) {
return null;
}
const extracted = extract(binarized, location);
const decoded = decode(extracted);

return null;
}
2 changes: 1 addition & 1 deletion src/detector/locator.ts → src/locator/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BitMatrix } from "../common/bitmatrix";
import { BitMatrix } from "../bitmatrix";

const MAX_FINDERPATTERNS_TO_SEARCH = 4;
const MIN_QUAD_RATIO = 0.5;
Expand Down
File renamed without changes.
62 changes: 0 additions & 62 deletions src/main.ts

This file was deleted.

0 comments on commit 76f8157

Please sign in to comment.