"use strict";
|
/*
|
* Copyright 2007 ZXing authors
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
Object.defineProperty(exports, "__esModule", { value: true });
|
/*namespace com.google.zxing.common {*/
|
/*import java.util.Arrays;*/
|
var BitArray_1 = require("./BitArray");
|
var System_1 = require("../util/System");
|
var Arrays_1 = require("../util/Arrays");
|
var StringBuilder_1 = require("../util/StringBuilder");
|
var IllegalArgumentException_1 = require("../IllegalArgumentException");
|
/**
|
* <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common
|
* module, x is the column position, and y is the row position. The ordering is always x, y.
|
* The origin is at the top-left.</p>
|
*
|
* <p>Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins
|
* with a new int. This is done intentionally so that we can copy out a row into a BitArray very
|
* efficiently.</p>
|
*
|
* <p>The ordering of bits is row-major. Within each int, the least significant bits are used first,
|
* meaning they represent lower x values. This is compatible with BitArray's implementation.</p>
|
*
|
* @author Sean Owen
|
* @author dswitkin@google.com (Daniel Switkin)
|
*/
|
var BitMatrix /*implements Cloneable*/ = /** @class */ (function () {
|
/**
|
* Creates an empty square {@link BitMatrix}.
|
*
|
* @param dimension height and width
|
*/
|
// public constructor(dimension: number /*int*/) {
|
// this(dimension, dimension)
|
// }
|
/**
|
* Creates an empty {@link BitMatrix}.
|
*
|
* @param width bit matrix width
|
* @param height bit matrix height
|
*/
|
// public constructor(width: number /*int*/, height: number /*int*/) {
|
// if (width < 1 || height < 1) {
|
// throw new IllegalArgumentException("Both dimensions must be greater than 0")
|
// }
|
// this.width = width
|
// this.height = height
|
// this.rowSize = (width + 31) / 32
|
// bits = new int[rowSize * height];
|
// }
|
function BitMatrix(width /*int*/, height /*int*/, rowSize /*int*/, bits) {
|
this.width = width;
|
this.height = height;
|
this.rowSize = rowSize;
|
this.bits = bits;
|
if (undefined === height || null === height) {
|
height = width;
|
}
|
this.height = height;
|
if (width < 1 || height < 1) {
|
throw new IllegalArgumentException_1.default('Both dimensions must be greater than 0');
|
}
|
if (undefined === rowSize || null === rowSize) {
|
rowSize = Math.floor((width + 31) / 32);
|
}
|
this.rowSize = rowSize;
|
if (undefined === bits || null === bits) {
|
this.bits = new Int32Array(this.rowSize * this.height);
|
}
|
}
|
/**
|
* Interprets a 2D array of booleans as a {@link BitMatrix}, where "true" means an "on" bit.
|
*
|
* @function parse
|
* @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows
|
* @return {@link BitMatrix} representation of image
|
*/
|
BitMatrix.parseFromBooleanArray = function (image) {
|
var height = image.length;
|
var width = image[0].length;
|
var bits = new BitMatrix(width, height);
|
for (var i = 0; i < height; i++) {
|
var imageI = image[i];
|
for (var j = 0; j < width; j++) {
|
if (imageI[j]) {
|
bits.set(j, i);
|
}
|
}
|
}
|
return bits;
|
};
|
/**
|
*
|
* @function parse
|
* @param stringRepresentation
|
* @param setString
|
* @param unsetString
|
*/
|
BitMatrix.parseFromString = function (stringRepresentation, setString, unsetString) {
|
if (stringRepresentation === null) {
|
throw new IllegalArgumentException_1.default('stringRepresentation cannot be null');
|
}
|
var bits = new Array(stringRepresentation.length);
|
var bitsPos = 0;
|
var rowStartPos = 0;
|
var rowLength = -1;
|
var nRows = 0;
|
var pos = 0;
|
while (pos < stringRepresentation.length) {
|
if (stringRepresentation.charAt(pos) === '\n' ||
|
stringRepresentation.charAt(pos) === '\r') {
|
if (bitsPos > rowStartPos) {
|
if (rowLength === -1) {
|
rowLength = bitsPos - rowStartPos;
|
}
|
else if (bitsPos - rowStartPos !== rowLength) {
|
throw new IllegalArgumentException_1.default('row lengths do not match');
|
}
|
rowStartPos = bitsPos;
|
nRows++;
|
}
|
pos++;
|
}
|
else if (stringRepresentation.substring(pos, pos + setString.length) === setString) {
|
pos += setString.length;
|
bits[bitsPos] = true;
|
bitsPos++;
|
}
|
else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) {
|
pos += unsetString.length;
|
bits[bitsPos] = false;
|
bitsPos++;
|
}
|
else {
|
throw new IllegalArgumentException_1.default('illegal character encountered: ' + stringRepresentation.substring(pos));
|
}
|
}
|
// no EOL at end?
|
if (bitsPos > rowStartPos) {
|
if (rowLength === -1) {
|
rowLength = bitsPos - rowStartPos;
|
}
|
else if (bitsPos - rowStartPos !== rowLength) {
|
throw new IllegalArgumentException_1.default('row lengths do not match');
|
}
|
nRows++;
|
}
|
var matrix = new BitMatrix(rowLength, nRows);
|
for (var i = 0; i < bitsPos; i++) {
|
if (bits[i]) {
|
matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength));
|
}
|
}
|
return matrix;
|
};
|
/**
|
* <p>Gets the requested bit, where true means black.</p>
|
*
|
* @param x The horizontal component (i.e. which column)
|
* @param y The vertical component (i.e. which row)
|
* @return value of given bit in matrix
|
*/
|
BitMatrix.prototype.get = function (x /*int*/, y /*int*/) {
|
var offset = y * this.rowSize + Math.floor(x / 32);
|
return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0;
|
};
|
/**
|
* <p>Sets the given bit to true.</p>
|
*
|
* @param x The horizontal component (i.e. which column)
|
* @param y The vertical component (i.e. which row)
|
*/
|
BitMatrix.prototype.set = function (x /*int*/, y /*int*/) {
|
var offset = y * this.rowSize + Math.floor(x / 32);
|
this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF;
|
};
|
BitMatrix.prototype.unset = function (x /*int*/, y /*int*/) {
|
var offset = y * this.rowSize + Math.floor(x / 32);
|
this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF);
|
};
|
/**
|
* <p>Flips the given bit.</p>
|
*
|
* @param x The horizontal component (i.e. which column)
|
* @param y The vertical component (i.e. which row)
|
*/
|
BitMatrix.prototype.flip = function (x /*int*/, y /*int*/) {
|
var offset = y * this.rowSize + Math.floor(x / 32);
|
this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF);
|
};
|
/**
|
* Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding
|
* mask bit is set.
|
*
|
* @param mask XOR mask
|
*/
|
BitMatrix.prototype.xor = function (mask) {
|
if (this.width !== mask.getWidth() || this.height !== mask.getHeight()
|
|| this.rowSize !== mask.getRowSize()) {
|
throw new IllegalArgumentException_1.default('input matrix dimensions do not match');
|
}
|
var rowArray = new BitArray_1.default(Math.floor(this.width / 32) + 1);
|
var rowSize = this.rowSize;
|
var bits = this.bits;
|
for (var y = 0, height = this.height; y < height; y++) {
|
var offset = y * rowSize;
|
var row = mask.getRow(y, rowArray).getBitArray();
|
for (var x = 0; x < rowSize; x++) {
|
bits[offset + x] ^= row[x];
|
}
|
}
|
};
|
/**
|
* Clears all bits (sets to false).
|
*/
|
BitMatrix.prototype.clear = function () {
|
var bits = this.bits;
|
var max = bits.length;
|
for (var i = 0; i < max; i++) {
|
bits[i] = 0;
|
}
|
};
|
/**
|
* <p>Sets a square region of the bit matrix to true.</p>
|
*
|
* @param left The horizontal position to begin at (inclusive)
|
* @param top The vertical position to begin at (inclusive)
|
* @param width The width of the region
|
* @param height The height of the region
|
*/
|
BitMatrix.prototype.setRegion = function (left /*int*/, top /*int*/, width /*int*/, height /*int*/) {
|
if (top < 0 || left < 0) {
|
throw new IllegalArgumentException_1.default('Left and top must be nonnegative');
|
}
|
if (height < 1 || width < 1) {
|
throw new IllegalArgumentException_1.default('Height and width must be at least 1');
|
}
|
var right = left + width;
|
var bottom = top + height;
|
if (bottom > this.height || right > this.width) {
|
throw new IllegalArgumentException_1.default('The region must fit inside the matrix');
|
}
|
var rowSize = this.rowSize;
|
var bits = this.bits;
|
for (var y = top; y < bottom; y++) {
|
var offset = y * rowSize;
|
for (var x = left; x < right; x++) {
|
bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF);
|
}
|
}
|
};
|
/**
|
* A fast method to retrieve one row of data from the matrix as a BitArray.
|
*
|
* @param y The row to retrieve
|
* @param row An optional caller-allocated BitArray, will be allocated if null or too small
|
* @return The resulting BitArray - this reference should always be used even when passing
|
* your own row
|
*/
|
BitMatrix.prototype.getRow = function (y /*int*/, row) {
|
if (row === null || row === undefined || row.getSize() < this.width) {
|
row = new BitArray_1.default(this.width);
|
}
|
else {
|
row.clear();
|
}
|
var rowSize = this.rowSize;
|
var bits = this.bits;
|
var offset = y * rowSize;
|
for (var x = 0; x < rowSize; x++) {
|
row.setBulk(x * 32, bits[offset + x]);
|
}
|
return row;
|
};
|
/**
|
* @param y row to set
|
* @param row {@link BitArray} to copy from
|
*/
|
BitMatrix.prototype.setRow = function (y /*int*/, row) {
|
System_1.default.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize);
|
};
|
/**
|
* Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
|
*/
|
BitMatrix.prototype.rotate180 = function () {
|
var width = this.getWidth();
|
var height = this.getHeight();
|
var topRow = new BitArray_1.default(width);
|
var bottomRow = new BitArray_1.default(width);
|
for (var i = 0, length_1 = Math.floor((height + 1) / 2); i < length_1; i++) {
|
topRow = this.getRow(i, topRow);
|
bottomRow = this.getRow(height - 1 - i, bottomRow);
|
topRow.reverse();
|
bottomRow.reverse();
|
this.setRow(i, bottomRow);
|
this.setRow(height - 1 - i, topRow);
|
}
|
};
|
/**
|
* This is useful in detecting the enclosing rectangle of a 'pure' barcode.
|
*
|
* @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
|
*/
|
BitMatrix.prototype.getEnclosingRectangle = function () {
|
var width = this.width;
|
var height = this.height;
|
var rowSize = this.rowSize;
|
var bits = this.bits;
|
var left = width;
|
var top = height;
|
var right = -1;
|
var bottom = -1;
|
for (var y = 0; y < height; y++) {
|
for (var x32 = 0; x32 < rowSize; x32++) {
|
var theBits = bits[y * rowSize + x32];
|
if (theBits !== 0) {
|
if (y < top) {
|
top = y;
|
}
|
if (y > bottom) {
|
bottom = y;
|
}
|
if (x32 * 32 < left) {
|
var bit = 0;
|
while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {
|
bit++;
|
}
|
if ((x32 * 32 + bit) < left) {
|
left = x32 * 32 + bit;
|
}
|
}
|
if (x32 * 32 + 31 > right) {
|
var bit = 31;
|
while ((theBits >>> bit) === 0) {
|
bit--;
|
}
|
if ((x32 * 32 + bit) > right) {
|
right = x32 * 32 + bit;
|
}
|
}
|
}
|
}
|
}
|
if (right < left || bottom < top) {
|
return null;
|
}
|
return Int32Array.from([left, top, right - left + 1, bottom - top + 1]);
|
};
|
/**
|
* This is useful in detecting a corner of a 'pure' barcode.
|
*
|
* @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white
|
*/
|
BitMatrix.prototype.getTopLeftOnBit = function () {
|
var rowSize = this.rowSize;
|
var bits = this.bits;
|
var bitsOffset = 0;
|
while (bitsOffset < bits.length && bits[bitsOffset] === 0) {
|
bitsOffset++;
|
}
|
if (bitsOffset === bits.length) {
|
return null;
|
}
|
var y = bitsOffset / rowSize;
|
var x = (bitsOffset % rowSize) * 32;
|
var theBits = bits[bitsOffset];
|
var bit = 0;
|
while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {
|
bit++;
|
}
|
x += bit;
|
return Int32Array.from([x, y]);
|
};
|
BitMatrix.prototype.getBottomRightOnBit = function () {
|
var rowSize = this.rowSize;
|
var bits = this.bits;
|
var bitsOffset = bits.length - 1;
|
while (bitsOffset >= 0 && bits[bitsOffset] === 0) {
|
bitsOffset--;
|
}
|
if (bitsOffset < 0) {
|
return null;
|
}
|
var y = Math.floor(bitsOffset / rowSize);
|
var x = Math.floor(bitsOffset % rowSize) * 32;
|
var theBits = bits[bitsOffset];
|
var bit = 31;
|
while ((theBits >>> bit) === 0) {
|
bit--;
|
}
|
x += bit;
|
return Int32Array.from([x, y]);
|
};
|
/**
|
* @return The width of the matrix
|
*/
|
BitMatrix.prototype.getWidth = function () {
|
return this.width;
|
};
|
/**
|
* @return The height of the matrix
|
*/
|
BitMatrix.prototype.getHeight = function () {
|
return this.height;
|
};
|
/**
|
* @return The row size of the matrix
|
*/
|
BitMatrix.prototype.getRowSize = function () {
|
return this.rowSize;
|
};
|
/*@Override*/
|
BitMatrix.prototype.equals = function (o) {
|
if (!(o instanceof BitMatrix)) {
|
return false;
|
}
|
var other = o;
|
return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize &&
|
Arrays_1.default.equals(this.bits, other.bits);
|
};
|
/*@Override*/
|
BitMatrix.prototype.hashCode = function () {
|
var hash = this.width;
|
hash = 31 * hash + this.width;
|
hash = 31 * hash + this.height;
|
hash = 31 * hash + this.rowSize;
|
hash = 31 * hash + Arrays_1.default.hashCode(this.bits);
|
return hash;
|
};
|
/**
|
* @return string representation using "X" for set and " " for unset bits
|
*/
|
/*@Override*/
|
// public toString(): string {
|
// return toString(": "X, " ")
|
// }
|
/**
|
* @param setString representation of a set bit
|
* @param unsetString representation of an unset bit
|
* @return string representation of entire matrix utilizing given strings
|
*/
|
// public toString(setString: string = "X ", unsetString: string = " "): string {
|
// return this.buildToString(setString, unsetString, "\n")
|
// }
|
/**
|
* @param setString representation of a set bit
|
* @param unsetString representation of an unset bit
|
* @param lineSeparator newline character in string representation
|
* @return string representation of entire matrix utilizing given strings and line separator
|
* @deprecated call {@link #toString(String,String)} only, which uses \n line separator always
|
*/
|
// @Deprecated
|
BitMatrix.prototype.toString = function (setString, unsetString, lineSeparator) {
|
if (setString === void 0) { setString = 'X '; }
|
if (unsetString === void 0) { unsetString = ' '; }
|
if (lineSeparator === void 0) { lineSeparator = '\n'; }
|
return this.buildToString(setString, unsetString, lineSeparator);
|
};
|
BitMatrix.prototype.buildToString = function (setString, unsetString, lineSeparator) {
|
var result = new StringBuilder_1.default();
|
// result.append(lineSeparator);
|
for (var y = 0, height = this.height; y < height; y++) {
|
for (var x = 0, width = this.width; x < width; x++) {
|
result.append(this.get(x, y) ? setString : unsetString);
|
}
|
result.append(lineSeparator);
|
}
|
return result.toString();
|
};
|
/*@Override*/
|
BitMatrix.prototype.clone = function () {
|
return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice());
|
};
|
return BitMatrix;
|
}());
|
exports.default = BitMatrix;
|