DavBfr / dart_barcode

Barcode generation library
https://pub.dev/packages/barcode
Apache License 2.0
134 stars 39 forks source link

BarcodeWidget support GS1 DataMatrix (how to insert FNC1?) #43

Closed gh-pap closed 2 years ago

gh-pap commented 2 years ago

Hi there, there's probably a very easy answer to this but (after many hours) I just can't figure it out. I'm trying to make the BarcodeWidget support GS1 DataMatrix which requires the first char to be ascii decimal 232 (FNC1). I see the BarcodeWidget converts the input string into a Uint8List using utf8.encoder.convert(data). I've tried many ways to provide an input string such that the first byte of the BarcodeWidget 's resulting Uint8List will be 232 but I've been foiled at every turn. Is there some trick to achieving this? Any help would be massively appreciated.

Paul PaulArthurPeterson@gmail.com

DavBfr commented 2 years ago

Use BarcodeWidget.fromBytes to pass the Uint8List data directly without conversion.

gh-pap commented 2 years ago

Thanks (and thanks for the very fast response)! 🤦Embarrassing to see how blind I was! Just bought you a coffee to show my gratitude! Even though I'm now feeding it a proper Uint8List (where the first byte is decimal 232) I'm still not quite over the finish line. I don't expect any more of your time, but feel free to offer any clues as to why my decoder (Barcode Data Decoder Verifier by IDAutomation) is decoding è0109339687195565 vs the expected \<FNC1>0109339687195565. Thanks again for your help. Paul

DavBfr commented 2 years ago

Hmm, it's actually a text-only DataMatrix implementation: https://github.com/DavBfr/dart_barcode/blob/master/barcode/lib/src/datamatrix.dart#L34 The lib needs a higher-end implementation to allow you to encode whatever you want.

If you want to make a PR that's welcome: Add a parameter to the constructor: an enum DataMatrixType { raw, ascii } to call this _encodeText method or not. That can be extended with EDIFACT and Base 256 later.

See if you need to deal with the padding yourself or leave it as is, depending on your results.

gh-pap commented 2 years ago

Disclaimer: I truly have no idea what I'm doing, so please bear with me (I'm not a coder, I'm just trying to prototype a business idea -- I hadn't even heard of a "Data Matrix" a week ago haha).

Good news! I downloaded your entire https://github.com/DavBfr/dart_barcode and managed to make it work as a GS1 Data Matrix. Thanks for pointing me in the right direction re _encodeText. Your code is wonderfully easy to read; it's really beautiful.

Making your Data Matrix support GS1 required a few changes beyond "adding a parameter to the constructor: an enum DataMatrixType { raw, ascii } to call the _encodeText method or not". Here's a summary of the changes I made:

Change 1: there were 3 lines performing utf-8 conversion thus changing GS1's special \<FNC1> char [232] into [195, 168]. To bypass the utf-8 conversion I needed to change these 3 lines: change 1.1 (barcode/lib/src/barcode.dart) change: bool isValid(String data) => isValidBytes(utf8.encoder.convert(data)); to: bool isValid(String data) => isValidBytes(Uint8List.fromList(data.codeUnits));

change 1.2 (barcode/lib/src/barcode.dart) change: void verify(String data) => verifyBytes(utf8.encoder.convert(data)); to: void verify(String data) => verifyBytes(Uint8List.fromList(data.codeUnits));

change 1.3 (flutter/lib/src/widget.dart) change: data: utf8.encoder.convert(data), to: data: Uint8List.fromList(data.codeUnits),

Change 2: you mentioned _encodeText and that was the second change, however it ends up _encodeText still needs to be called (it's doing some magic I don't understand, but the magic is definitely needed) so I enhanced _encodeText to simply let [232] pass-through https://github.com/DavBfr/dart_barcode/blob/e8a66268452cb4ba25b2c15862aba8952d955a8f/barcode/lib/src/datamatrix.dart#L74 [I modified _encodeText as follows] ... if (c == 232) { result.add(c); } else { ... do exactly what _encodeText does today }

I'm happy to learn Git and GitHub (have never used source control) and learn how to submit a PR but I worry the above changes might create backward compatibility issues and I'm not sure how or where to add an option (e.g., such as your proposed enum DataMatrixType { raw, ascii }) that would accommodate all the above changes.

Could you offer me any advice on the next step? Would be great to have GS1 support in your official barcode package, I'm just not sure what I should do next.

BTW, regarding your comment "That can be extended with EDIFACT and Base 256 later" I don't believe such an extension will ever be required. Paragraph 2 of section 2.1 of the GS1 Data Matrix Guidelines essentially mandates "ISO/IEC 646 (equivalent to ASCII table 256) for all information".

DavBfr commented 2 years ago

Nice work! For the next step, you can click on the FORK button on the top right of the GitHub Repository. Then it's your own copy. You can "clone" this version to your local computer, apply your changes here, and push the modifications using a tool or the git commit / git push commands. From there, on your GitHub page, click on the link "Create a Pull Request" and I'll take over.

gh-pap commented 2 years ago

Thanks so much for your guidance, really helpful. Just submitted the pull-request. Please make sure to read the "Testing" and "Concerns" sections. Thanks!

DavBfr commented 2 years ago

I changed the way it works. Can you try the branch datamatrix-gs1? https://github.com/DavBfr/dart_barcode/tree/datamatrix-gs1

Use it like this:

BarcodeWidget.fromBytes(
  barcode: Barcode.dataMatrix(), // Barcode type and settings
  data: (DataMatrixEncoder()
        ..fnc1()
        ..ascii('01034531200000111719112510ABCD1234')
        ..fnc1()
        ..ascii('2110'))
      .toBytes(),
  width: 200,
  height: 200,
)

Let me know how that works.

gh-pap commented 2 years ago

Just tested it and it works perfectly! And thanks for the fnc1() and ascii() helpers, those are so much easier for me than dealing with bytes - beyond awesome! FYI, here in Australia GS1 has mandated that Aussie food retailers switch from barcode to data matrix by 2027 (due to features like expiry date and more importantly product recall). The largest supermarket change has already started the change (example below). image

DavBfr commented 2 years ago

Fixed in barcode version 2.2.2

gh-pap commented 1 year ago

Full disclosure: I have no idea what I'm doing haha. Have never used github before (other than I reported an issue a few weeks ago), I haven't coded since 1986, and I've just started learning Dart, Flutter, Firebase, Firestore, etc. That said, I'm quite keen on implementing an idea I've had (happy to say more about that in a private email if you're interested) and implementing the idea requires GS1-compatible barcodes and Data Matrix codes, and your implementation of those components (as well as PDF which is also required) is truly elegant and straightforward so my plan is to read/watch some tutorials about GitHub, learn how to clone, branch, and make a PR, and then I'll get back to you (will probably take me a few days). I mention this because at some point you may ask yourself "does this guy even know what he's doing?" and I wanted to warn you in advance the answer to that question is "nope". So don't hesitate to call me out if/when I do something blatantly (or subtly) ridiculous.

Cheers, pp

On Sun, 7 Aug 2022 at 11:23, David PHAM-VAN @.***> wrote:

Hmm, it's actually a text-only DataMatrix implementation: https://github.com/DavBfr/dart_barcode/blob/master/barcode/lib/src/datamatrix.dart#L34 The lib needs a higher-end implementation to allow you to encode whatever you want.

If you want to make a PR that's welcome: Add a parameter to the constructor: an enum DataMatrixType { raw, ascii } to call this _encodeText method or not. That can be extended with EDIFACT and Base 256 later.

See if you need to deal with the padding yourself or leave it as is, depending on your results.

— Reply to this email directly, view it on GitHub https://github.com/DavBfr/dart_barcode/issues/43#issuecomment-1207309673, or unsubscribe https://github.com/notifications/unsubscribe-auth/AZIXCJCJPSX7MX6Q3ILO5BDVX4F2XANCNFSM55ZEA55A . You are receiving this because you authored the thread.Message ID: @.***>