sde1000 / quicktill

Figure out where all the money and stock went to
GNU General Public License v3.0
43 stars 8 forks source link

Receipt logos: add support for black-and-white binary netpbm images. #282

Closed jayaddison closed 4 months ago

jayaddison commented 4 months ago

Status

Screenshots

image

Related

Resolves #156.

sde1000 commented 4 months ago

You may find it easier to use the pillow library to load the image, convert it to black+white if necessary, and then access the raw data. It's already a dependency of quicktill (transitively via reportlab) so it's guaranteed to be available on till installations.

jayaddison commented 4 months ago

You may find it easier to use the pillow library to load the image, convert it to black+white if necessary, and then access the raw data. It's already a dependency of quicktill (transitively via reportlab) so it's guaranteed to be available on till installations.

Ach, I knew I should've checked more thorougly, or remembered that from dabbling with reportlab!

Would you prefer that approach, and if so, any thoughts on whether storing the logo in the DB makes sense, or is a filename reference OK? (it was finding the contents of a .css file in the config table that made me figure that DB-loading the contents might make sense)

sde1000 commented 4 months ago

I think storing the data as a config option in the database makes perfect sense. A shame it has to be base64 encoded, but that's on me for not having a binary config type! Something to note for the future.

jayaddison commented 4 months ago

I think storing the data as a config option in the database makes perfect sense. A shame it has to be base64 encoded, but that's on me for not having a binary config type! Something to note for the future.

No problem - yep, the base64 encoding is something of a tradeoff. I'll leave the config/storage as-is for now.

jayaddison commented 4 months ago

Ok, getting there.. the centre-alignment (or lack of) for the logo is wonky, though:

image

sde1000 commented 4 months ago

It prints!

Not sure why it's only showing half the image. The TM-T20 has 576 dots per line so I'd expect a 512×512 image to fit.

PXL_20240507_105234978

jayaddison commented 4 months ago

Ok, that's progress, of a sort :)

Is the black printed region near the left of your photo (outside of the circle) visible when viewing the input image?

A mini todo-list of issues:

sde1000 commented 4 months ago

I think points 1 and 3 are to do with the print mode — you're using mode 0, for "8-dot single-density", which makes the printer double each pixel horizontally and triple it vertically. Mode 33, "24-dot double-density" should give more sensible results, but you'll need to work in groups of 24 rows instead of 8.

My image does have black outside the circle — that must be the default background for convert. The input to convert was a PNG with transparency.

jayaddison commented 4 months ago

I think points 1 and 3 are to do with the print mode — you're using mode 0, for "8-dot single-density", which makes the printer double each pixel horizontally and triple it vertically. Mode 33, "24-dot double-density" should give more sensible results, but you'll need to work in groups of 24 rows instead of 8.

Ok, great - I think that the latest commit (6cca49c08ede64fffe98e9272091764fd6fa82a6) should address both of these. It doesn't affect the output from the PHP-based printer emulator I'm using, so that's difficult for me to check currently.

My image does have black outside the circle — that must be the default background for convert. The input to convert was a PNG with transparency.

Yep, there is an incantation required to select the background fill colour when converting a transparent image.. I'll try to figure that out again (seems I haven't kept a note of that).

sde1000 commented 4 months ago

Current status: PXL_20240508_182429270 MP Definitely missing a few rows! (Every other row, possibly?)

jayaddison commented 4 months ago

Intriguing. While I'm investigating that, and with credit to a StackOverflow thread, here's what worked for me to replace the transparent area with a white background in the output, albeit for a different input image:

$ convert images/pwa/icon-512.png -background white -alpha remove -monochrome emflogo.pbm
sde1000 commented 4 months ago

I'll make a note of that — but the black border is actually helpful for debugging so I'll keep it for now!

sde1000 commented 4 months ago

Line spacing is better, but it still looks like it's missing every other line: PXL_20240508_195855288 MP

sde1000 commented 4 months ago

Are you doing any kind of feed between lines? You could try LF after sending the data for the row? (Hypothesis: you're sending all the rows, but it's throwing some of them away because they are being printed to the right of the printable area.)

jayaddison commented 4 months ago

That could well explain it, yep - ok. I'm just trying to confirm from the documentation whether that should be a LF or a CR.

jayaddison commented 4 months ago

I think we want a CR but without an LF between image lines (I'm worried that adding the latter could reintroduce extraneous inter-line spacing).

However: a LF could be useful to provide the visual spacing after the image is printed, if I understand this correctly.

sde1000 commented 4 months ago

No difference from the previous attempt :-(

I'm not sure where to look next. I'll have a think.

sde1000 commented 4 months ago

This is using \n instead of \r at the end of each row: PXL_20240508_204241376 The printer doesn't print continuously, there is a brief pause where each little white line shows up. Thermal management of the print head, possibly? I will have to try an image with less solid black in it.

jayaddison commented 4 months ago

Brilliant!

jayaddison commented 4 months ago

The printer doesn't print continuously, there is a brief pause where each little white line shows up. Thermal management of the print head, possibly? I will have to try an image with less solid black in it.

Yep, I was wondering about that too. Even to the extent of considering a backtrack by a dot before each line; but not wanting to cause double-printing of any (dot)lines either.

sde1000 commented 4 months ago

Still stripey... PXL_20240508_205148621

jayaddison commented 4 months ago

Perhaps the stripes would disappear if we issue a single escpos.ep_bitimage_dd_v24 command that contains the correct width_info, but is followed by the payload of the entire image?

sde1000 commented 4 months ago

I don't think so — how would it know where the image stops? I expect we would get one valid row and then the remainder of the image data would be interpreted as text.

sde1000 commented 4 months ago

I can't take the more-itertools dependency at the moment. It isn't in Ubuntu 22.04 (it only has version 8.10.0) and the till needs to be able to run on Ubuntu 22.04 with system packages only.

sde1000 commented 4 months ago

Ubuntu 22.04 has python3-imagesize version 1.3.0 but that appears to work ok in this instance.

jayaddison commented 4 months ago

This may seem silly, but I'm going to rewrite that function from scratch. I haven't looked at the code for it (you'll have to take my word for that), but it's MIT-licensed whereas this is GPL -- it'd be fine to incorporate it with the appropriate inclusion of the license text, making it clear that it's vendored, etc, but I think it'll be simpler here for me to re-implement it (perhaps famous last words).

sde1000 commented 4 months ago

That sounds sensible. You might want to implement something that always returns the requested number of items in the batch, padding if necessary, because it could make dealing with images that aren't a multiple of 24 pixels high a bit simpler.

jayaddison commented 4 months ago

I forget what time of day this part of my EMF 2022 experience was:

image

(something slightly off about my reimplementation of _chunked at the moment..)

jayaddison commented 4 months ago

Ok, that's the batching/chunking code reimplemented, and seems to be working well here. The problem above was due to a missing if condition after the loop.

sde1000 commented 4 months ago

If I turn the print speed right down in the printer configuration, it prints without stripes: PXL_20240508_230945288 The current version has a decent space between the bottom of the image and the site name, too.

jayaddison commented 4 months ago

Excellent, that looks much better. How much time does that take to print?

sde1000 commented 4 months ago

It's quite slow. I need to spend some time this evening turning it up to see at what speed it breaks!

jayaddison commented 4 months ago

Sounds good. I also wonder whether an outlined version of the image might be preferable energy-wise (even if it doesn't affect the output speed).

FWIW: On a separate branch, I've pushed a commit https://github.com/jayaddison/quicktill/commit/af596773b44973b5d10e17829ea1890e8ed666d6 that migrates from P4 PBM (binary) to use P1 PBM (text) format instead; it's slightly simpler, although I don't know whether it's worthwhile. Adding the -compress none option to convert outputs that format instead.

sde1000 commented 4 months ago

After I accept the pull request I'm tempted to rework it to use Pillow to read the image and drop the imagesize dependency.

We should then be able to include images in pdf output too, fairly easily.

Finally, I went to add an "image" config type and add support to the web interface for uploading and displaying images in the config.

sde1000 commented 3 months ago

Followup: I just pushed a commit that removes the imagesize dependency and uses Pillow to load the image instead.

This allows the image to be anything understood by the Pillow library. For example, here's what it prints when I use a huge transparent PNG from https://www.miltonbrewery.co.uk/media/pumpclips/minotaur.png : PXL_20240509_213957260

jayaddison commented 3 months ago

Brilliant! Nice to have learned some ESC/P along the way here. Cheers :)