Need Code 128 start code when scanning via intent

187 views
Skip to first unread message

Douglas Henke

unread,
Oct 25, 2013, 4:38:50 PM10/25/13
to zx...@googlegroups.com
I'm writing an Android application that uses scanning via intent to read Code 128 barcodes encoding GS1-128 elements.

Using the getRawBytes() method of the IntentResult, I can do my own Code128 decoding and pull out the GS1-128 elements. This works great, with one minor caveat: the raw data stream has everything except for the start symbol.

Right now, I'm kludging around it by assuming that whatever I've scanned starts in Code C.

I get the right results with all the examples I've tried, but given what I've seen of the various vendors and implementers out there... let's just say that the fewer assumptions I make in my code, the better I'll sleep at night.

I'm considering writing something that'll look at the data returned by both getRawBytes() and and getContents(), and deduce the correct start code by comparing the two. Before I do so, I thought I'd ask here and see if I'm missing a better way of finding out the start code. (If not: please consider this a request for a clean way to do that.)

Thanks, and happy hacking!

Sean Owen

unread,
Oct 25, 2013, 4:40:54 PM10/25/13
to zx...@googlegroups.com
Can you suggest a patch? this might be something that reasonably belongs in a byte representation, yes.

Douglas Henke

unread,
Oct 25, 2013, 5:32:43 PM10/25/13
to zx...@googlegroups.com
If you were starting from scratch, I'd have said just include it as the first byte of the array returned by getRawBytes(). However, I'd be wary of making such a change now, for fear of breaking existing applications. (OTOH, if someone else is looking at the raw bytes for Code 128 barcodes, they've got the same basic problem I do.)

I guess my preferences, in order, would be:

1) Have the current behavior be the default, but create a new boolean extra I can add that lets me say I want the start symbol included if I getRawBytes() on a Code 128 barcode. In other words, let me do something like:

   final IntentIntegrator scan = new IntentIntegrator(someActivity);
   scan.addExtra(Intents.Scan.CODE128_INCLUDE_START, true);
   scan.initiateScan();

2) Create a new method getAllRawBytes() that works like getRawBytes() except that for Code 128, it include the start symbol.

3) Create a new method byte getStartSymbol() that gives me the start symbol for Code 128 and throws an exception else.

4) Let me get the start symbol with something like:

    myIntent.getByteExtra(Intents.Scan.SCAN_RESULT_CODE128_START);

Do any of those make sense from a design standpoint?

Sean Owen

unread,
Oct 25, 2013, 6:50:26 PM10/25/13
to zx...@googlegroups.com
I'm not so concerned about backwards compatibility as long as the changed is principled. Looking at the source code though it looks like it intends to output every code word as the raw bytes but does not include the initial code start. It is an interesting question whether this is really part of the payload; it's really the guard pattern and that is generally not considered part of the raw content elsewhere. What's the use case for needing to know what the code set is -- does it matter a lot in GS1?

Douglas Henke

unread,
Oct 28, 2013, 11:37:42 AM10/28/13
to zx...@googlegroups.com
The basic reason that the start code is important is that there are three different ones, and which one is present determines how all the following codes are interpreted. Anything that's looking at the raw data for Code 128 needs to know (or make assumptions about) the start code in order to interpret that raw data in a meaningful way. (My understanding is that most other symbologies either have no guard pattern, or only have a single guard pattern. Code 128 is a bit unusual in this regard.)

For GS1-128 in particular, the reason I don't just use the getContents() method and let zxing interpret the data for me is that I need to know the location of the FNC1 symbols, which don't appear in the "cooked" output from getContents(). (A single Code 128 barcode may encode one or more GS1-128 elements. Some types of elements are variable-length. When a variable-length element is present that isn't the final element, the standard relies on FNC1 as a delimiter.)

As an aside, the raw data for Code 128 already includes the checksum symbol and stop symbol, neither of which are really part of the content -- but both of which I'm glad I can get to if I want/need to.

Sean Owen

unread,
Oct 28, 2013, 12:03:25 PM10/28/13
to zx...@googlegroups.com
OK that's a reasonably good reason, that there are many guard patterns. I agree on this.

FNC1 is translated to ASCII 29 already for you -- does that help? AFAIK this is what GS1 specifies already, so you should be able to find it.

Does that solve your problem? or else, yes what about a patch? might be the fastest way to communicate exactly what you want the output to contain.

Douglas Henke

unread,
Oct 28, 2013, 2:33:09 PM10/28/13
to zx...@googlegroups.com

FNC1 is translated to ASCII 29 already for you -- does that help? AFAIK this is what GS1 specifies already, so you should be able to find it.
Does that solve your problem?

If that were the case, it would indeed solve my problem. However, I've just re-tested to be sure, and the result from the getContents() method of IntentResult does not seem to contain an ASCII 29 (or any other marker) for the FNC1.

My test case:

http://www.morovia.com/free-online-barcode-generator/

In barcode format, select GS1-128 (UCC/EAN-128).
For data to encode, input: (37)1234(21)5678
Leave all other fields at default. Click submit.

When I dump the data from getContents(), I see the characters with (decimal) values:
51, 55, 49, 50, 51, 52, 50, 49, 53, 54, 55, 56
corresponding to ASCII characters:
371234215678

When I dump the getRawBytes() data, I get (decimal) values:
102, 37, 12, 34, 102, 21, 56, 78, 45, 106

There, each "102" is an FNC1, the 45 is the checksum, the 106 is the stop marker and all the other values are two packed digits a la Code 128 CODE C.

I'm certainly open to the idea that I'm doing something wrong, but I'm fairly confident that those really are the results I'm seeing. (I've used two different data dumpers and the Eclipse debugger. I've also checked that I get the same results with actual printed barcodes from a real supplier.)
 
or else, yes what about a patch? might be the fastest way to communicate exactly what you want the output to contain.

Sounds like a plan. I'll get to work on it.

Douglas Henke

unread,
Oct 28, 2013, 3:02:24 PM10/28/13
to zx...@googlegroups.com
Attached is a context diff against rev 2902 that should do what I'm talking about.

While I was in there (there being core/src/com/google/zxing/oned/Code128Reader.java), I spotted why the FNC1 isn't marked in the decoded data: That's conditional on the boolean convertFNC1 being true in method decodeRow(). That, in turn, only happens if DecodeHintType.ASSUME_GS1 is in the hints.

So, in short: yep, I was doing something dumb. :-)

But, I still think the patch is worth considering, for the reasons we went over upthread.

Thanks for all your work on what is a very useful thing!
code128-start.patch

Sean Owen

unread,
Oct 28, 2013, 6:47:00 PM10/28/13
to zx...@googlegroups.com
Oh right now I remember that. Yes, that's why FNC1 wasn't translated.

Does anyone have objections to this change?
Reply all
Reply to author
Forward
0 new messages