metafloor / bwip-js

Barcode Writer in Pure JavaScript
Other
2.12k stars 305 forks source link

5 digits Numeric Micro QR code doesn't scan #20

Closed shinyat closed 8 years ago

shinyat commented 8 years ago

First of all, thank you so much for awesome API! This is amazing! I have implemented img tag using API but generated Micro QR code doesn't scan if the text is 5 digits numeric. For example, 50041 doesn't generate scannable Micro QR code but 500411 works fine. I have tested with various numbers and it seems to have a problem with 5 digits numeric data. I have compared with other online Micro QR code and the the last bottom line is slightly different from other Micro QR codes.

terryburton commented 8 years ago

BWIP-JS appears to match upstream (BWIPP), so if there is a bug then it's upstream so I'm grabbing this.

5 digits fit exactly into the 20 data bits available in an M1 symbol, as follows:

Char count = 5 (into 3 bits) => 101 50041 => 500 41 => 500 (3 digits into 10 bits) || 41 (2 digits into 7 bits) => 0111110100 || 0101001 Output: 101 0111110100 0101001

BWIPP does this correctly so any problem is occurring later in the process.

Can you test using a one, two, three and four digit codes and let me know if these work for you.

Also, can you please attach examples for 500411 that scan correctly for comparison.

Thanks.

metafloor commented 8 years ago

Hi Terry, this is what I am seeing from BWIPP, bwip-js and a 3rd party library that I have. BWIPP and bwip-js output the same (top two images, respectively), the Windows package image (bottom image) is different on the last two rows: 50041-bwipp 50041-bwipjs 50041-good

I do not have my hawkeye scanner available where I am right now so I cannot verify the images.

shinyat commented 8 years ago

I have tried one, two, three and four digit codes and they all scan fine. I'm using Symbol DS6707 2D scanner. Here are QR codes that scan fine (50041) and they are different from bwip-js. These are from Bartendar program and http://barcode.tec-it.com/en.

bartender

tec-it

Like metafloor mentioned, the last two rows are different. Lastly, here is bwip-js's QR code. bwip

terryburton commented 8 years ago

Thanks both.

I can find a few libraries that agree with BWIPP and most others don't. I don't have a hardware verifier that can test μQR at the moment so let's assume it's a bug.

The modules that disagree are precisely the ECC modules (see the M1 symbol).

M1 and M3 symbols have an exceptional property that final data codeword has four modules rather than eight. In the case of four or fewer digits the group of four modules are all zero and the output of BWIPP/JS agrees with the other libraries. With five digits these module are non-zero so perhaps the four-bit codeword has a strange contribution to the Reed Solomon encoding.

Would you mind performing a further test with the other generator to help validate this theory. Could you generate a 22-digit μQR, a 23-digit μQR and a 24-digit μQR with error correction level "L". 23/24 digit should be the tipping point between a M3 and M4 symbol for libraries that perform a straightforward numeric encoding of the data. 22-digits leaves the four-bit codeword empty, 23-digits fills it. For example, on BWIPP this would look like this:

(1234567890123456789012) (eclevel=L) (12345678901234567890123) (eclevel=L) (123456789012345678901234) (eclevel=L)

If the theory holds (and this isn't just some odd, unwritten quirk of M1 symbols) then we would expect the 22-digit symbols would match, the 23-digit symbol would disagree and the 24-digit symbol would match (albeit as an M4 symbol).

shinyat commented 8 years ago

A strange thing is happening. If I type 12345678901234567890123 in BWIPP, scanner reads 12345678901234567890116.

Here are comparison between BWIPP and BarTender. They all scans fine but 23 digits BWIPP Micro QR Code reads 116 instead of 123. (I'm certain that I typed correct number!) I'll try different 23 digits number.

qr2

As you've expected 23 digits are different.

shinyat commented 8 years ago

I generated Micro QR code for 12345678901234567890123 at http://www.terryburton.co.uk/barcodewriter/generator/ and It scanned exactly the same. The last 3 digits outputs 116 instead of 123. Also I have tried with different number. 12345678901234567890199 scans 12345678901234567890196. Again the last digit is off.

terryburton commented 8 years ago

@shinyat The bad scans are due to the error correction data being use to "correct" the final codeword.

My theory seems right and we seem to have nailed it. I can replicate the BarTender et al. behaviour by treating the short codeword of M1 and M3 symbols as a high-order nibble when contributing to the ECC.

I'll cut a new release of BWIPP later but in case @metafloor wants to beat me to it the fix is as follows:

diff --git a/src/qrcode.ps b/src/qrcode.ps
index 61e7bff..2a2e753 100644
--- a/src/qrcode.ps
+++ b/src/qrcode.ps
@@ -587,6 +587,9 @@ begin
         cws c cw put
     } for 

+    % Short final data byte in M1 and M3 symbols has high-order value
+    lc4b {cws cws length 1 sub 2 copy get 4 bitshift put} if
+
     % Calculate the log and anti-log tables
     /rsalog [ 1 255 { dup 2 mul dup 256 ge {285 xor} if } repeat ] def
     /rslog 256 array def
@@ -676,6 +679,7 @@ begin

     % Fixups for the short final data byte in M1 and M3 symbols
     lc4b {
+       cws dcws 1 sub 2 copy get -4 bitshift put
         dcws 1 sub 1 ncws 2 sub {
             /i exch def
             cws i cws i get 15 and 4 bitshift put
terryburton commented 8 years ago

I've updated the online generator with the updated code: http://www.terryburton.co.uk/barcodewriter/generator/

If you can confirm that this is working correctly for a few more M1 and M3 edge cases then I'll tag 2015-11-XX.

Thanks for all of the testing!

shinyat commented 8 years ago

Terry, The online generator scans perfectly including 5 / 23 digits numbers! Great! Do you have a plan to update bwip-js API in the future?

Thank you so much for the quick fix!

metafloor commented 8 years ago

@shinyat: I will update bwip-js after @terryburton cuts the new release. He provided a patch for code128.ps but the bwip-js code generator uses the monolithic release and it is a bit too error prone to patch in a separate code module into the monolithic file.

shinyat commented 8 years ago

@metafloor Ah, sorry! Thank you so much for your awesome work and sharing it!!! You guys are amazing!

terryburton commented 8 years ago

@metafloor Here you go: https://github.com/bwipp/postscriptbarcode/releases/tag/2015-11-24

@shinyat Thanks for the complements.

metafloor commented 8 years ago

@terryburton Thanks for the fast response!

@shinyat github and npmjs have been updated to bwip-js version 0.15.0 / BWIPP 2015-11-24.

Please close this issue when you are satisfied the update is working.

shinyat commented 8 years ago

Could you update online API as well?

http://api-bwipjs.rhcloud.com/

I don't have node server set up and currently relying on the API.

Thank you!!!

metafloor commented 8 years ago

Oops. Messed up that release. My development branch was working with some new peephole optimizations on the generated JavaScript and I failed to rollback one part of the toolchain, so the changes in BWIPP 2015-11-24 didn't actually get applied.

Please try again with bwip-js 0.15.1....

shinyat commented 8 years ago

Looks great! It scans now! I'll close this issue. Thank you!!!