Home > Software design >  Why the imagedata returned by upng-js is malformed?
Why the imagedata returned by upng-js is malformed?

Time:10-26

I'm using the upng-js module to read png files. In common sense the return value should be in RGBA form, so should be an Unit8Array with size 4*width*height. However when I'm reading an image with size 111*111 it returns an Unit8Array with size 49395. Here's my code:

const jsQR = require('jsqr');
const upng = require('upng-js');
const fs = require('fs');

const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAG8AAABvCAYAAADixZ5gAAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAYHSURBVHhe7d3Rlhs3DAPQ v8/usnJzIN9PPJehNLa2rDPioYCCBCSm/b2/ 9//ut/tkTg1uRtydufopu8fblr8jbmrslr8nZGYOPahzPvdrtNP9Yo2Mq3VoTi  /K/qM67/ snCUFdojbKG1 axHQKAJuCkqTFyDWygvAultaUl6l69PuHh1P9pE1lf0F koN9/vLPjTzmjyh7VgjoMtusk TdyIpYM0CfdY MXkSZEbpS1KZzEXZ5x4gWS81i62NmmAWbg81SNqUwwtYsk T5/bbyju7rpUXALFixsxS/2gmSXD752xTQJGI3 R9kb5mDd5W3nM7xta9Y2CpKKwSmioRf1bTb582m7wzkbbyXtuXqC29/0kgkrESXxVWHEbudqK20RqpWVKizCQBvVJPyTblw2knNnnPqEoTtPKCdL2l8lK1VTx9tX195/4rcIttc0UR3wliRTGVOlfg1uSdCKwm9W3kzfrwaJ9Zl1YZ7OlZVuyZ1iDr3/ZvTDd5Qs/rNU3eBT7bK08Gddo76a8HAmKq4LRmqWF0r02/FeOz4nlMrgpyMAGuyQusQ8Bq8qQ1n9csUd7flXL8KXn6kp9p7muQQ1ZUO6tm2UewHe4jtikfSNVWmalN3oE2vW02eSdYd3 nQtziI5QnnV65jIslrrDBNCUKGemaUYYQzEl5slGTN3fGC ZN3tl1kqJTVY2UXbHchz0lsEjRElhmWZ EnUrN6VlWrJecUVJe2q1N3mtKxCpbedLWF2vE7kbhK210KTF mJZ0JGsk6cnvbbOCkiRe ZbULLYv9TR5XyiMFAD3v5TUJk Q/4nkiUdLyhJ7lH3EimfVLN Sa4D0jtT8rW bs2K6BARZIyDKPnKuODEW/jMmdFWQw5NHQ6FpWhPQpX7ZZxvyxO7kwClwsl7ui7OSYaWeNFWKAOie1 QJbccaISltdLFfuirIAJfBK8FEIGvlnU2Tvm0KkUKArElJkvWiEqlNlCHWnVol2WZ6yMph5JCyf5N3ItnkvdafNJM05XLlpfFdbCctenUzyf7pVaEyYshFZOY1eQcCTd6FLMWCRBmpmkfXIXlETv9sWts05aUdJ16f7imHEUBljTRK5d4mdirnpeexFOgm7xkBITtWvMy8Ju 8FMPvdqPGfRt5UtDIjuTPikWk 8t301QsNaSNLhY6dDJRXgqEPJWlFiHACRkSjmSfFHSZo3GoafKEquc125Anfi3qTLtPOnEWiKmyU cQN5LzPtQpymvyPD3KzBOti73HV4VKB7XyhLZjTYm8WXe1kRVIE4g1iW1KmpV6UlsTKxalDteMbLPJe60SUUaTdyKQWq6oVsCVICZmKA4xqidWXmo1szoxBUvqFJKk/rSB0pERN1yaNtPuEPuVzq3MhibvAuG06wXEVt6BgGBbuipU7n9CkiRAsRoCAh6dV3xLcBi6V2qbFd9P7bHJe41YKy9Isz9KeZKmJGikipTZKemxEqZkf3GOt9lmk/eFrYV/sWaE55KZ1 RtTF46AyoWUbE4aTJZszpdp3foJYElPaTMjybvGYEm76IrZjnKrCAWv23Khytr5L4oSXW1amfVkJ6XHhbSn4QqhImnU9GD15C0NonyTd4FqmknCvFN3sWLQwpKmipnqW1FQ6TqTGtIf d7aGJ522zyXiOQBhxJ4zLLKW02eRuTJ10g9zDpuLRR0kAhNijPVGL1MqfTfWLbbPIuLshh4k1noTQx2WaT90PIE9upDHCxmtEa6VZZk9Yvey5J4JI201mVHj6dW03egUBsm628E7jCb3WzAtFHkDfLUtLklq7/uET9CbbZ5Pk9snRVWGGbTd7G5EnAEctKU58EpXQ SSNOs tPsM0mL227D02baVeKjYsa5PqRKnWk2vSMQ9dJlZf2iBQqT0cV xJlp00gr04r9iwFlibvQKDJOzuhlecNESsvVZvMmMovyGk90hwrlCR1iqWXZp4UIWvkjVRAlG NAkgJrElPYrOCDD2PpWC18hyxUjON0qZ/vle CwH6/yq8q7j 7msEmryNO6TJa/I2RmDj0lt5G5P3C5einFk/dclYAAAAAElFTkSuQmCC';

const regex = /^data:. \/(. );base64,(.*)$/;
const matchObj = dataUrl.match(regex);
const ext = matchObj[1];
const data = matchObj[2];

const buf = Buffer.from(data, 'base64');
// console.log(buf);

fs.writeFileSync('test.' ext, buf);

const imgInfo = upng.decode(buf);
console.log(imgInfo);

const url = jsQR(imgInfo.data, imgInfo.width, imgInfo.height);
console.log(url);

Printed image info is below:

{
  tabs: { sRGB: 0 },
  frames: [],
  width: 111,
  height: 111,
  depth: 8,
  ctype: 6,
  data: Uint8Array(49395) [
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255,
    ... 49295 more items
  ]
}

The image is well restored on disk by writeFileSync function. Error thrown by jsQR:

/home/vector/node_modules/jsqr/dist/jsQR.js:412
        throw new Error("Malformed data passed to binarizer.");

CodePudding user response:

At first, let's convert your image to RGBA8 format, then create a Uint8ClampedArray - Input of jsQR.

// ...
const rgba8 = upng.toRGBA8(imgInfo)[0]; // convert to RGBA8
const qrArray = new Uint8ClampedArray(rgba8); // create Uint8ClampedArray array

const code = jsQR(qrArray, imgInfo.width, imgInfo.height);
console.log(code);

The output of your QR code will look like this (on my laptop):

{
  binaryData: [
    104, 116, 116, 112,  58,  47,  47, 116, 120, 122,  46,
    113, 113,  46,  99, 111, 109,  47, 112,  63, 107,  61,
     88,  87, 114, 102,  49, 105, 116,  45,  72, 105, 108,
    113, 101, 119, 121,  52,  71,  85,  51, 118, 119,  84,
     90,  77,  51,  70, 108,  57,  53,  49, 116, 116,  38,
    102,  61,  50,  49,  48,  48,  48,  53,  48,  49
  ],
  data: 'http://txz.qq.com/p?k=XWrf1it-Hilqewy4GU3vwTZM3Fl951tt&f=21000501',
  chunks: [
    {
      type: 'byte',
      bytes: [Array],
      text: 'http://txz.qq.com/p?k=XWrf1it-Hilqewy4GU3vwTZM3Fl951tt&f='
    },
    { type: 'numeric', text: '21000501' }
  ],
  version: 4,
  location: {
    topRightCorner: { x: 104.99999999999999, y: 6.0000000000000036 },
    topLeftCorner: { x: 6.000000000000003, y: 6.000000000000003 },
    bottomRightCorner: { x: 104.99999999999997, y: 104.99999999999997 },
    bottomLeftCorner: { x: 6.0000000000000036, y: 104.99999999999999 },
    topRightFinderPattern: { x: 94.5, y: 16.5 },
    topLeftFinderPattern: { x: 16.5, y: 16.5 },
    bottomLeftFinderPattern: { x: 16.5, y: 94.5 },
    bottomRightAlignmentPattern: { x: 85.5, y: 85.5 }
  }
}
  • Related