Wrong characters for Aztec decoder in `Decoder.MIXED_TABLE`
alexanderpopko opened this issue · 0 comments
Hi, and many thanks to all contributers for maintaining this library!
I encountered a bug when decoding Aztec codes. Will try to supply a fix and create a pull request.
Describe the bug
Decoding Aztec codes in some cases gives wrong results, i.e., '\x01'
/ '\x02'
/ '\x03'
/ '\x04'
/ '\x05'
/ '\x06'
/ '\x07'
/ '\x0b'
/ '\x1b'
/ '\x1c'
/ '\x1d'
/ '\x1e'
/ '\x1f'
/ '\x7f'
get decoded to '\\1'
/ '\\2'
/ '\\3'
/ '\\4'
/ '\\5'
/ '\\6'
/ '\\7'
/ '\\13'
/ '\\33'
/ '\\34'
/ '\\35'
/ '\\36'
/ '\\37'
/ '\\177'
.
To Reproduce
Run the following script and see the expected/received output. I ran it using:
- node: 20.14.0
- @zxing/library: 0.21.1
- sharp: 0.32.6
- typescript: 4.3.5
import {
AztecCodeReader,
AztecCodeWriter,
BarcodeFormat,
BinaryBitmap,
BitMatrix,
DecodeHintType,
HybridBinarizer,
RGBLuminanceSource,
ZXingStringEncoding,
} from '@zxing/library';
import sharp from 'sharp';
ZXingStringEncoding.customDecoder = (bytes) =>
Buffer.from(bytes).toString('latin1');
function getPixelArray(bits: BitMatrix): Uint8Array {
const width = bits.getWidth();
const height = bits.getHeight();
const colours: number[] = [];
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
colours.push(bits.get(x, y) ? 0 : 255);
}
}
return Uint8Array.from(colours);
}
async function getResizedImage(
pixels: Uint8Array,
sourceWidth: number,
sourceHeight: number,
targetWidth: number,
targetHeight: number
) {
return await sharp(Uint8Array.from(pixels), {
raw: {
width: sourceWidth,
height: sourceHeight,
channels: 1,
},
})
.toColourspace('b-w')
.resize({ width: targetWidth, height: targetHeight, kernel: 'nearest' })
.raw()
.toBuffer({ resolveWithObject: true });
}
function encodeImage(data: string): BitMatrix {
return new AztecCodeWriter().encode(data, BarcodeFormat.AZTEC, 0, 0);
}
async function decodeImage(bits: BitMatrix) {
// It seems to be necessary to increase the image size before decoding,
// otherwise Detector.getBullsEyeCorners will throw a NotFoundException.
const { data, info } = await getResizedImage(
getPixelArray(bits),
bits.getWidth(),
bits.getHeight(),
100,
100
);
const source = new RGBLuminanceSource(
Uint8ClampedArray.from(data),
info.width,
info.height
);
const binarizer = new HybridBinarizer(source);
const image = new BinaryBitmap(binarizer);
const hints = new Map([
[DecodeHintType.PURE_BARCODE, true],
[DecodeHintType.TRY_HARDER, true],
]);
return new AztecCodeReader().decode(image, hints).getText();
}
async function main() {
const input = '\x01\x02\x03\x04\x05\x06\x07\x0b\x1b\x1c\x1d\x1e\x1f\x7f';
const output = await decodeImage(encodeImage(input));
console.log('Expected:', Buffer.from(input, 'latin1').toString('hex'));
console.log('Received:', Buffer.from(output, 'latin1').toString('hex'));
}
main().then();
Expected behavior
'\x01\x02\x03\x04\x05\x06\x07\x0b\x1b\x1c\x1d\x1e\x1f\x7f'
gets decoded to '\x01\x02\x03\x04\x05\x06\x07\x0b\x1b\x1c\x1d\x1e\x1f\x7f'
.
Desktop (please complete the following information):
- OS: Ubuntu
- Version: 22.04.4