Issue #84 new

Code 128 generation produces unreadable barcodes

Marius Gedminas
created an issue

If I generate two barcodes with the following code

import elaphe
elaphe.barcode('code128', 'Wikipedia').save('wiki.png')
elaphe.barcode('code128', 'Count0123456789!').save('count.png')

then attempt to decode them with zbarimg, I get an error on wiki.png. count.png works.

If I compare the Elaphe-generated barcode with the sample from Wikipedia, after scaling Elaphe's image a bit and adding some padding to make them easier to compare visually, I see that Elaphe's barcode is incomplete.

Elaphe's image:

wikipedia.png

Scaled and with padding added[*]:

out.png

Compare with a working image from Wikipedia:

good.png

Actually, Elaphe's image seems truncated: if I adjust the scale factor and add some padding on the right[+], I get

truncated.png

[*] The command I used to scale the image and add some padding was

convert wikipedia.png -scale 439x150\! -gravity center -extent 459x170  out.png

[+] The command used was

convert wikipedia.png -scale 404x150\! -gravity center -extent 424x170 -gravity west -extent 459x170 truncated.png

Comments (5)

  1. Marius Gedminas reporter

    The formula used to compute the barcode width in the current Elaphe release (0.6.0) is

    self._count_chars(codestring)*11+11+13
    

    It is incorrect: Code 128 needs a start code (11pt), then 11pt times the number of characters, then a check character (11pt) and a stop code (13pt). So it should be

    11+self._count_chars(codestring)*11+11+13
    

    But even that only works if barcode.ps won't decide to add additional code switching/shifting characters into the output. Which, in fact, it does.

    The formula used by current master is

    self._count_chars(codestring)*11+2
    

    and it may work for the sample used ("Count0123456789!"), but that's an accident: barcode.ps switches to Code C which can encode pairs of digits using one character, so the missing start/checksum/stop and two code switching characters get exactly compensated by the 10 digits occupying the space of 5.

  2. Marius Gedminas reporter

    Note that _count_chars(codestring)*11+11+11+13 cannot be used as a maximum width of the barcode: if you mix lowercase letters and ASCII control characters in the string, or if you attempt to put Latin-1 characters in the string, the encoding will need at least one extra code switch character.

    I think there are only five ways to fix this properly:

    • understand the encoding logic in code128.ps and reimplement it in Python
    • shell out into a GhostScript interpreter and have it compute the dimension for us (see dimensions.ps)
    • automatically transpile the PostScript code into Python (hey, somebody did that for JavaScript)
    • implement a PostScript interpreter in Python
    • render the image with an excessively-large bounding box, then scan the bitmap looking for the rightmost black pixel
  3. Terry Burton

    This is the most usual approach taken by other frontends: "render the image with an excessively-large bounding box, then scan the bitmap looking for the rightmost black pixel."

    This is the neatest approach: "shell out into a GhostScript interpreter and have it compute the dimension for us (see dimensions.ps)"

    I plan to add this functionality into the renderers in the main BWIPP library so that you can supply a "showbbox" option to have the dimensions written to stdout after the symbol is plotted. If that's useful I can add this sooner rather than later.

  4. Log in to comment