can't create a pdf417 code

Create issue
Issue #5 new
Former user created an issue

Hello,

I get the ouput below on this command :

from elaphe import barcode barcode('pdf417', '1234') _.show()

Output :

Traceback (most recent call last): File "<input>", line 1, in <module> File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 1483, in show _show(self, title=title, command=command) File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2123, in _show apply(_showxv, (image,), options) File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2127, in _showxv apply(ImageShow.show, (image, title), options) File "/usr/lib/python2.7/dist-packages/PIL/ImageShow.py", line 41, in show if viewer.show(image, title=title, options): File "/usr/lib/python2.7/dist-packages/PIL/ImageShow.py", line 66, in show self.show_image(image, options) File "/usr/lib/python2.7/dist-packages/PIL/ImageShow.py", line 85, in show_image return self.show_file(self.save_image(image), **options) File "/usr/lib/python2.7/dist-packages/PIL/ImageShow.py", line 81, in save_image return image._dump(format=self.get_format(image)) File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 488, in _dump self.load() File "/usr/lib/python2.7/dist-packages/PIL/EpsImagePlugin.py", line 283, in load self.im = Ghostscript(self.tile, self.size, self.fp) File "/usr/lib/python2.7/dist-packages/PIL/EpsImagePlugin.py", line 75, in Ghostscript raise IOError("gs failed (status %d)" % status) IOError: gs failed (status 256)

Comments (16)

  1. Richard Vézina

    Could it be possible that barcode.ps need update?

    Response one here talk about issue with eps generation in elaphe, that why I thought about that :

    http://stackoverflow.com/questions/7080119/any-good-pdf417-barcode-libraries-for-python

    I would help to test elaphe...

    Also, documentation is scarce.

    Notice that there is an extra close parenthesis on the main page of the repo...

    This :

    >>> from elaphe import barcode
    >>> barcode('qrcode',
    ...         'Hello Barcode Writer In Pure PostScript.',
    ...         options=dict(version=9, eclevel='M'),
    ...         margin=10, data_mode='8bits'))   # Generates PIL.EpsImageFile instance
    <PIL.EpsImagePlugin.EpsImageFile ... at ...>
    >>> _.show()            # Show the image
    

    Should be :

    >>> from elaphe import barcode
    >>> barcode('qrcode',
    ...         'Hello Barcode Writer In Pure PostScript.',
    ...         options=dict(version=9, eclevel='M'),
    ...         margin=10, data_mode='8bits')   # Generates PIL.EpsImageFile instance
    <PIL.EpsImagePlugin.EpsImageFile ... at ...>
    >>> _.show()            # Show the image
    
  2. Richard Vézina

    Forget about this issue (Anonymous is me by the way, don't why, maybe I wasn't connected when I post it).

    I found my mistake :

    from elaphe import barcode
    barcode('qrcode', 'Hello Barcode Writer In Pure PostScript.', options=dict(version=9, eclevel='M'), margin=10, data_mode='8bits').show()
    barcode('code128', '^104^102Count^0990123456789^101!', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('pdf417', '^453^178^121^239', options=dict(columns=2, rows=10), margin=1, scale=2).show()
    barcode('upc', '78858101497', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('royalmail', 'LE28HS9Z', options=dict(includetext=False), scale=2, margin=1).show()
    barcode('datamatrix', '^142^164^186', options=dict(columns=32, rows=32), margin=1, scale=2.0).show()
    barcode('code11', '0123456789', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('code25', '0123456789', options=dict(includetext=False, includecheck=False), scale=2, margin=1).show()
    barcode('code39', 'THIS IS CODE39', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('code93', 'THIS IS CODE93', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('japanpost', '1231FZ13XHS', options=dict(includetext=False), scale=2, margin=1).show()
    barcode('azteccode', '00100111001000000101001101111000010100111100101000000110', margin=1).show()
    barcode('auspost', '5956439111ABA 9', options=dict(includetext=False), scale=2, margin=1).show()
    barcode('ean13', '977147396801', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('interleaved2of5', '24012345678905', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('raw', '331132131313411122131311333213114131131221323', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('kix', '1231FZ13XHS', options=dict(includetext=False), scale=2, margin=1).show()
    barcode('postnet', '012345', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('pharmacode', '117480', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('plessey', '012345ABCD', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('symbol', 'fimd', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('onecode', '0123456709498765432101234567891', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('maxicode', '^059^042^041^059^040^03001^02996152382802^029840^029001^0291Z00004951^029UPSN^02906X610^029159^0291234567^0291^0471^029^029Y^029634 ALPHA DR^029PITTSBURGH^029PA^030^062^004^063', options=dict(mode=2), margin=1, scale=4).show()
    barcode('msi', '0123456789', options=dict(includetext=True), scale=2, margin=1).show()
    barcode('rss14', '24012345678905', options=dict(linkage=True, includetext=True), scale=2, margin=1).show()
    barcode('rationalizedCodabar', 'A0123456789B', options=dict(includetext=True, includecheck=True), scale=2, margin=10).show()
    

    Have go in each differents barcode and copy the doctest and test it.

    I think there is error in "rationalizedCodabar" doctest though, I had to change "includetext" and "includecheck" to True from None in other to get this barcode working as well :

    barcode('rationalizedCodabar', 'A0123456789B', options=dict(includetext=True, includecheck=True), scale=2, margin=10).show()
    

    Should we had more doctest in barcode() to improve doc by examples with the lines above in init.py ? It may improve test coverage also...

    I can send you a patch for that...

  3. Richard Vézina

    Update on this :

    I wrote this 2 functions... Far from be usable in prod, but actually working.

    def byte_string_to_cw(string):
        if isinstance(string, str):
            try:
                string.decode('ascii')    
            except UnicodeDecodeError:
                raise Exception('Not 100% ascii string')
        else:
            raise Exception('Not ascii string')
        cw = []
        if len(string) % 6 == 0:
            cw.append('^924')  # If length of string is a multiple of 6 switch to "Byte" mode with 924 CW
        else:
            cw.append('^901')  # Else switch normally to "Byte" mode
        true_flag = True
        while true_flag is True:
            string_to_byte = string[0:6]  # 6 bytes
            if len(string_to_byte) == 6:  # 6 bytes to 5 cws
                byte_sum = ord(string_to_byte[0]) * 256**5 + \
                    ord(string_to_byte[1]) * 256**4 + \
                    ord(string_to_byte[2]) * 256**3 + \
                    ord(string_to_byte[3]) * 256**2 + \
                    ord(string_to_byte[4]) * 256 + \
                    ord(string_to_byte[5])
                for i in range(0, 5):
                    cw.insert(1, '^%d' % (byte_sum % 900))
                    byte_sum = byte_sum / 900
                string = string[6:]  # Remaining characters
            elif len(string_to_byte) < 6: # Remaining characters byte to cw
                for i in range(0, len(string_to_byte)):
                    cw.append('^%03d' % ord(string_to_byte[i]))
                true_flag = False  # There is no remaining characters
        return ''.join(cw)
    
    from elaphe import barcode
    bc = barcode('pdf417', byte_string_to_cw(string), options=dict(eclevel=2, compact=False, columns=2, rows=10), margin=1, scale=2)
    bc.save('test.png')
    
    def long_integer_to_cw(numeric):
        try:
            long(numeric)
        except ValueError:
            raise ValueError
        true_flag = True
        cw = ['^902']  # Set numeric mode
        while true_flag is True:
            working_numeric = long(str(numeric)[0:44])
            if len(str(working_numeric)) == 44:
                for i in range(0, 15):
                    cw.insert(1, '^%03d' % (working_numeric % 900))
                    working_numeric = working_numeric / 900
                numeric = long(str(numeric)[44:])
            elif len(str(working_numeric)) < 45:
                working_numeric = long(str(numeric)[0:44]) + 10**(len(str(numeric)[0:44]))  # Add 1 above the long integer
                for i in range(0, len(str(numeric)) / 3 + 1):
                    cw.insert(1, '^%03d' % (working_numeric % 900))
                    working_numeric = working_numeric / 900
                true_flag = False
        return ''.join(cw)
    

    Can be call like this :

    from elaphe import barcode
    bc = barcode('pdf417', long_integer_to_cw(numeric), options=dict(eclevel=2, compact=True, columns=2, rows=10), margin=1, scale=2)
    bc.save('test.png')
    

    They are base on the description of "Byte" and "Numeric" mode algo describe here :

    http://grandzebu.net/informatique/codbar-en/pdf417.htm

    Now, my question is, should we do this high level encoding to produce PDF417 with elaphe? As far as I had read/tried elaphe it seems to me that writing those func was the way to go, since my understanding of the way elaphe invoque BWIPP is pretty weak...

    So, was it a missing piece of code in elaphe (in other word should I keep improving those func) or there is a way to delegate to BWIPP the task of the high level encoding of the string, since BWIPP is able to do it??

    NOTE : The output barcode "test.png" where tested ("scanned") with these sites :

    http://online-barcode-reader.inliteresearch.com/

    http://www.onlinebarcodescan.com/

    The former was use for test the long_integer_to_cw() func mostly, since the later was failing to decode the bc obtained with this high level encoding algo. I didn't make further tests for the byte_to_cw() with the former online scanner... The later online barcode reader also failed to decode MicroPDF417 (compact=True option) and they where decoded with the former, so I guess the former online barcode reader is a better barcode reader implementation. More tests should be done... I don't have a real barcode reader for conduct further test for now. If someone has one thanks for report any experience :)

    Thanks and regards

    Richard

  4. R1O

    Hi!

    Hardirc, thank you for your messages, especially for 2 functions. But in the first function there is a little mistake, therefore my barcode was generated incorrect... (Second function a didn't test). Look at this part of code:

    for i in range(0, 5):
        cw.insert(1, '^%d' % (byte_sum % 900))
        byte_sum = byte_sum / 900
    

    So, every 6 bytes are converted to 5 cws in a loop. And you use insert function, that takes as first argument - number 1. It means that after second iteration - the second part with 6 bytes will be left of first part and as result we will have the mirror string of cws:

    "abcdefghijkl" --> Barcode image --> convert from barcode --> "ghijklabcdef".

    So, it's simple to correct. For example, the insert function can use "index" variable as first argument:

    def byte_string_to_cw(string):
        if isinstance(string, str):
            try:
                string.decode('ascii')
            except UnicodeDecodeError:
                raise Exception('Not 100% ascii string')
        else:
            raise Exception('Not ascii string')
        cw = []
        if len(string) % 6 == 0:
            cw.append('^924')  # If length of string is a multiple of 6 switch to "Byte" mode with 924 CW
        else:
            cw.append('^901')  # Else switch normally to "Byte" mode
        true_flag = True
        index = 1 #<-----------------------
        while true_flag is True:
            string_to_byte = string[0:6]  # 6 bytes
            if len(string_to_byte) == 6:  # 6 bytes to 5 cws
                byte_sum = ord(string_to_byte[0]) * 256**5 + \
                    ord(string_to_byte[1]) * 256**4 + \
                    ord(string_to_byte[2]) * 256**3 + \
                    ord(string_to_byte[3]) * 256**2 + \
                    ord(string_to_byte[4]) * 256 + \
                    ord(string_to_byte[5])
                for i in range(0, 5):
                    cw.insert(index, '^%03d' % (byte_sum % 900)) #<-----------------------
                    byte_sum = byte_sum / 900
                index += 5 #<-----------------------
                string = string[6:]  # Remaining characters
            elif len(string_to_byte) < 6: # Remaining characters byte to cw
                for i in range(0, len(string_to_byte)):
                    cw.append('^%03d' % ord(string_to_byte[i]))
                true_flag = False  # There is no remaining characters
        return ''.join(cw)
    

    --

    Best Regards

    R1O

  5. Richard Vézina

    Thanks for comment... I will check, it was more draft version than anything else. Though I am a bit disappointed I didn't have comment from whosayin the project owner...

    Richard

  6. Richard Vézina

    Yes you are right R10... I guess the length of my test string (PDF417) was not enough long to fall on this bug. Thanks to pointed it out and made the corrections.

  7. R1O

    You are welcome... Hardic, tell me, please: in specification of pdf417 was said that the first codeword always must be a Symbol Length Descriptor. Is there it in return value of your byte_string_to_cw function?

    Now I make my own version of pdf417 barcode generation on Python and I want to know - should I add Symbol Length Descriptor to cw list.

    If I should, then how to encode Symbol Length Descriptor? At the output we must have 1 codeword, but after using long_integer_to_cw function for our Descriptor, we will have minimum 2 codewords: ^902^xxx... I don't understand...

  8. Richard Vézina

    You are right : "First CW indicates CW total number of the code including: datas, CW of stuffing and itself but excluding CW correction."

    http://grandzebu.net/informatique/codbar-en/pdf417.htm

    I don't think I take care of this aspect...

    Note that BWIPP should take care of all this, read this thread and Terry answer (it true at least for DataMatrix, but my guess is that it's applied aussi for PDF-417) :

    https://groups.google.com/d/msg/postscriptbarcode/6b1ytXVChIE/O5iwjsOZWpEJ

    I am not fully understand Elaphe and I think that there is more work to do to let BWIPP do the work. For now, for PDF-417, it seems to me that Elaphe force you to pass code word to BWIPP, but it should also let you pass your string directly and let BWIPP handle it... It is not clear to me what process should be done or not at high level processing with Elaphe. But to me it a waste of time to implement the high level encoding in Elaphe since it a code duplication if this is already (or will be) included in BWIPP.

    Also, I am a newbie in barcode world and didn't know all the thing I recently learn about high-level encoding and there is many aspect that should be manage by the encoding, like the redundancy, the error correction (hello reed-solomon), space optimisation... Coding this could be a good exercise, but I have not time doing it... So I hope that I can rely on BWIPP to the high-level encoding for DataMatrix BC, that will be the BC I will use for many concern, mainly the density of the BC. In this aspect DataMatrix is the big winner in the 2D BC and in my application space is crucial...

    :)

    Richard

  9. Richard Vézina

    I will, study Elaphe in further details to see how it works with passing string directly to BWIPP. If this is not actually possible for PDF417 and Datamatrix BC, I will refactor these classes to allow that and send a PR.

    :)

    Thanks Terry!

    Richard

  10. Yasushi Masuda repo owner

    Hello,

    I replaced BWIPP to recent version to find some tests got broken (such as AztecCode which uses low level binary encoding). Let me handle it...

  11. Yasushi Masuda repo owner

    Hardirc, Elaphe passes message to BWIPP directly, so if you call barcode('symbology', 'your message'), you will get a PostScript code:

    %!PS-Adobe-2.0 ... (BWIPP resource) gsave 0 0 moveto 1.0 1.0 scale (your message) () /symbology /uk.co.terryburton.bwipp ... grestore showpage

    You can see some decoders in elaphe; those are used to calculating number of codewords in a message, which is then used to calculate size of symbol (EPS bundingbox size). (So I think I'll want to use your decoder for Pdf417._Renderer._code_bbox...)

    In develop branch, now you can say Pdf417().render('1234').

    Sorry for bad correspondence.

    Thanks

  12. Yasushi Masuda repo owner

    Hello,

    Finally d684e7c supports following:

    bc.render('PDF417', ...) bc.render('P^068F417', ...) bc.render('A truncated PDF417', options=dict(columns=4, compact=True)) bc.render('String error correction', options=dict(columns=2, eclevel=5)) bc.render('^453^178^121^239', options=dict(raw=True, columns=2))

    Seems to work for me.

  13. Log in to comment