WhyNotHugo / python-barcode

㊙️ Create standard barcodes with Python. No external dependencies. 100% Organic Python.
http://python-barcode.rtfd.io/
MIT License
558 stars 123 forks source link

GS1 always starts with Character Set B #110

Open noperator-zz opened 3 years ago

noperator-zz commented 3 years ago

Some codes can be encoded entirely with code C, but Code128() initializes self._charset = "B" unconditionally. Also, due to the (non-numeric) FNC 1 character at the start of a GS1 barcode, the library will always start with character set B anyway, even if self._charset was set to "C". https://github.com/WhyNotHugo/python-barcode/blob/83a0b4e87755f8dcb22c9cf35c52f6f3ae7a6993/barcode/codex.py#L175

The effect is that a switch to Code C is added after FNC 1, when it could have just started with character set C instead.

Expected (ignore the slash): START C -> FNC 1 -> 12 -> 00 -> 13 -> 00 -> 85 image

Actual: START B -> FNC 1 -> CODE C -> 12 -> 00 -> 13 -> 00 -> 85 gs128

import barcode
from barcode.writer import ImageWriter
sn = 1200130085
# START B -> FNC 1 -> CODE C -> barcode (code C)
code = barcode.get("gs1_128", str(sn), writer=ImageWriter())
code.save("gs128")
audoh-tickitto commented 3 years ago

Similar issue with Code128, it starts with charset B so it will never switch to charset A as A is a subset of B (for alphanumeric barcodes, at least).

I think there are some characters in charset A which are not included in charset B, so I think we will just need something a bit more sophisticated (both for GS1 and Code128) than just starting in one charset and changing if that does not support.

I sort of think we should just have these exposed via the constructor, with automatic resolution used only if not explicitly specified there.

WhyNotHugo commented 3 years ago

Yup, makes sense. The "next charset" should be evaluated at the rather than hardcoded.

lhopkins commented 2 years ago

@WhyNotHugo Any timeline for a fix on this? I'm happy to submit a PR.

WhyNotHugo commented 2 years ago

PRs welcome

QW-Is-Here commented 1 year ago

any updates for this bug ?

Kendlings commented 1 year ago

I recently tried to implement code to generate SSCC barcodes using this library, and since you can stay in char set C (since SSCC only contains numbers) i tried it by making the following class, which is a modification of the Code128 class with minimal changes to the existing code. This is neither a real solution (just a workaround for my case), nor clean (as you can probably remove most if not all of the contents of the method '_maybe_switch_charset'), but as far as I checked it seemed to generate the barcodes i want. Feel free to confirm if this class behaves properly for SSCC codes in case it is useful to you.

class Gs1_128_SSCC(barcode.codex.Code128): # ...\Lib\site-packages\barcode\codex.py """ Code128 SSCC implementation.

yohan-hicof commented 1 month ago

Hello, I encountered the same issue. There is probably a simple fix for that. First, since this is a GS1 code, we know that after the FNC1 we will have at least two digit for the AI. So in the class Gs1_128 add this line at the end of the init: self._charset = "C" Then, in the Code128 class, function _maybe_switch_charset, replace: if self._charset == "C" and not char.isdigit(): by if self._charset == "C" and not (char.isdigit() or ord(char)==241):

I did not fully test the second change, but since the FNC1 char is in all three charset, changing the charset before or after the FNC1 should not have any impact on any code.