lukevp / ESC-POS-.NET

Efficient, Easy to Use Thermal Printing & POS (Windows/Linux/OSX, WiFi/BT/USB/Ethernet)
MIT License
523 stars 171 forks source link

PDF417 max 255 characters #253

Closed Soushiro closed 2 weeks ago

Soushiro commented 9 months ago

I try to print a 2d code with the following command :

impresion.Print2DCode(TwoDimensionCodeType.PDF417, documento.Ted, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_15)

but it returns an error "string has more than 255 characters", I need to print a string of 350 characters which is the official stamp for electronic ballots in my country, I am generating the pdf stamp as an image and then I print it with: print.PrintImage(bytesPDF, true, true) , but the quality is blurry.

I take this opportunity to thank you for the great work you do, really thank you very much.

igorocampos commented 9 months ago

Hi, that 255 char cap is hard coded, and the reason is that EPSON's manual says it can't be larger than that, see below image

Right now there's no way of overriding that setting, but you could pull the code locally, and change it at least to see if it works for your printer.

lukevp commented 8 months ago

I see you mentioned something about your country's official ballots. Do they have to be PDF417? The reason I ask is if PDF417 is supposed to support larger data areas than ESCPOS currently supports then maybe we're doing something wrong.

Another possible interpretation of the above is that you can store more than 255 bytes, but you can only write 255 bytes to the symbol storage area at once, and pL/pH are used as offsets, so the true max size is then 65535. If that's the case and that's the right way to interpret this, then I think you would split your byte array on every 255 bytes, so byte 256 would be in a second call, and byte 512 would be in a third call, etc. And you would increment pH each time by one (so pL would be 0 and pH would be 0, then 1, then 2). I'm not sure if that's really how it works, but I don't know why they would have an offset based system like this if it didn't work that way though.

If you try this out and you're able to use the offset to print, then we could update the code around this QR format to take in longer bytes and auto split it and set offsets for the user (basically bake this into the code itself). That seems like a really helpful feature. We could have test coverage around this too.

Let me know if you try this and if you run into any issues.

lukevp commented 8 months ago

This document from Star makes it sound like the true data max size is 1024, and that you have to write it 255 bytes at a time to the buffer. This is probably why it's a buffered command as well and not an immediate print command - essentially there's a 1024 byte (1KB) staging area set aside for this. you write your data into it with multiple commands, and then you issue a print command. If the max was 255 then there probably wouldn't be a way to feed data into a buffer at all and it would print directly from the command.

Makes me wonder if this is a general thing across the other 2d code family or if it's only relevant to PDF417 because it stores more data?

PRs are very welcome so if you get this working, please consider contributing back as a PR so others can use it!

igorocampos commented 8 months ago

This document from Star makes it sound like the true data max size is 1024, and that you have to write it 255 bytes at a time to the buffer. This is probably why it's a buffered command as well and not an immediate print command - essentially there's a 1024 byte (1KB) staging area set aside for this. you write your data into it with multiple commands, and then you issue a print command. If the max was 255 then there probably wouldn't be a way to feed data into a buffer at all and it would print directly from the command.

Makes me wonder if this is a general thing across the other 2d code family or if it's only relevant to PDF417 because it stores more data?

PRs are very welcome so if you get this working, please consider contributing back as a PR so others can use it!

So you think we need to run the store command multiple times (255 chars each) and then in the end print out the barcode? It does make sense, but I would assume the printer just overwrites the stored bytes with a new command being sent... I would like someone to test it, if it works I can easily submit a PR with that change.

lukevp commented 8 months ago

Actually, I refreshed myself on ESCPOS notation a bit and I think this is the proper interpretation of the following image:

image

the confusing parts are the reuse of d1...dk and d in the definition, and the reuse of k in dk vs the k in the command specification.

They also define d as being between 2 and 255 (and Epson specifies as 0 to 255, which is probably more correct?), but the important point is - this is the definition of d, not the definition of k - i.e. they are saying a byte is a byte, and d can't be > 255, which is obvious because that's the max size of an 8-bit byte, so it doesn't even really need to be said but they said it anyway and confused the issue.

Similarly they declare the value of pL and pH as minimum 0 and maximum 255 in decimal, because that's the maximum value a single byte can hold. If you ignore all the a byte is a byte stuff, then I think the implementation becomes clearer:

image

The data size (k) has a "calculated size - 3" because it is implying the above constraint that the fixed sub-command length is always included in the size length (i.e. pL + pH include the 3 bytes of the Sub-Command, they are not just the data length).

Given a data length of 629 characters as an example, this would be the calculation in pseudocode:

string data = "some ... string of 629 bytes in length"; // assume this is actually the right length
int k = data.Length;
int dataLength = k + 3; // should be 632
byte pH = dataLength / 256; // implies int division. should be 2
byte pL = dataLength % 256; // should be 120
var command = $"\x1D\x28\x6B{pL}{pH}\x31\x50\x30" + data;

the reason pL is 120 and pH is 2 is because dataLength = 629, and with the fixed sub-command, the length is 632. 2 x 256 = 512 and 512 + 120 = 632.

Hopefully that makes sense! I have a printer I can test this on if you want to do an implementation, but I don't know what valid PDF417 data looks like. I do see that it is some type of structured data, so we could potentially provide helpers on building the PDF417 headers.

Also, I'm not sure where I got 1024 as the max size, I think I misinterpreted something.

igorocampos commented 8 months ago

Hmm, that actually makes sense! Ok, I can fix it then, and probably double-check other bar codes they may have mistakenly similar caps in place.

Soushiro commented 8 months ago

Indeed, the electronic stamps of official documents must come stamped with a PDF417, which contains a variable paragraph of the electronic signature of the same document, this paragraph varies between 350 and 450 characters, in previous systems the way to solve it was to generate the PDF417 as a BMP graph and then drawing this on the receipt as an image.

El dom, 14 ene 2024 a las 20:08, Luke Paireepinart (< @.***>) escribió:

I see you mentioned something about your country's official ballots. Do they have to be PDF417? The reason I ask is if PDF417 is supposed to support larger data areas than ESCPOS currently supports then maybe we're doing something wrong.

Another possible interpretation of the above is that you can store more than 255 bytes, but you can only write 255 bytes to the symbol storage area at once, and pL/pH are used as offsets, so the true max size is then 65535. If that's the case and that's the right way to interpret this, then I think you would split your byte array on every 255 bytes, so byte 256 would be in a second call, and byte 512 would be in a third call, etc. And you would increment pH each time by one (so pL would be 0 and pH would be 0, then 1, then 2). I'm not sure if that's really how it works, but I don't know why they would have an offset based system like this if it didn't work that way though.

If you try this out and you're able to use the offset to print, then we could update the code around this QR format to take in longer bytes and auto split it and set offsets for the user (basically bake this into the code itself). That seems like a really helpful feature. We could have test coverage around this too.

Let me know if you try this and if you run into any issues.

— Reply to this email directly, view it on GitHub https://github.com/lukevp/ESC-POS-.NET/issues/253#issuecomment-1891104289, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOSEIR2WXSABIZGMAK5PKJDYORQOXAVCNFSM6AAAAABA66Y42CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOJRGEYDIMRYHE . You are receiving this because you authored the thread.Message ID: @.***>

-- Luis Perez Vasquez *Especialista en Proyectos y Soluciones *Tecnológicas www.tokem.cl http://www.tokem.cl

igorocampos commented 8 months ago

@lukevp, I submitted PR #259

I double checked all barcodes, there was just a couple more that had different values based on EPSON's manual, However I've also had to use STAR's manual to get GS1 Barcode limitations (not sure way, but it's not part of EPSON's manual that I have).

I also noted the library doesn't implement (0 <= m <= 6) barcodes, which seems to be a way to have unlimited length for CODABAR, ITF and CODE39, for it seeks a NUL byte (0x00) of the command to know when it ended. However, I'd suggest testing it out to see if that tracks. And that might not even be possible when dealing with regular printing (portrait), because once the barcode exceeds the printing area (paper width when portrait), printer will simply feed paper ( per "If the horizontal size exceeds printing area, the printer only feeds the paper").

image

image