From ad0cc367cabcd150aefcd69144da6ba2fb89b731 Mon Sep 17 00:00:00 2001 From: Sam Stevens Date: Mon, 25 Dec 2023 08:28:15 +0000 Subject: [PATCH 1/5] Readme updates & Docker compose example --- README.md | 15 ++++++++++++--- docker-compose.yml | 11 +++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 docker-compose.yml diff --git a/README.md b/README.md index 4da1b8f..68c1bea 100644 --- a/README.md +++ b/README.md @@ -65,13 +65,20 @@ This has been tested with python 3.10, newer may work fine. You will need to install the `libdmtx` library for the barcodes to generate, see [pylibdmtx](https://pypi.org/project/pylibdmtx/) documentation on pypi. -Its advisable to run and install in a venv. For example: +Its advisable to run and install in a [venv](https://docs.python.org/3/library/venv.html). For example: ``` + # Create and enter the venv python -m venv .venv source ./.venv/bin/activate + # Install packages + python -m pip install -U -r requirements + + # exit with ./.venv/bin/deactivate ``` +For development you can use `flask run --debug` to run the service on port 5000. Alternatively use `gunicorn -c gunicorn_conf.py app:app` to run the service on port 8000. + ## TODO - Endless Labels @@ -81,9 +88,11 @@ Its advisable to run and install in a venv. For example: A Dockerfile is included based on a python 3.10 alpine image. The default port is 8000. -Published to Dockerhub as [sam159/brotherql_grocylabels](https://hub.docker.com/r/sam159/brotherql_grocylabels) +Published to Dockerhub as [sam159/brotherql_grocylabels](https://hub.docker.com/r/sam159/brotherql_grocylabels) for architectures amd64, arm64, and armv7. + +As an example, you can launch this with `docker run -d -p 8000:8000 -e PRINTER_MODEL=QL-500 -e PRINTER_PATH=file:///dev/usb/lp1 sam159/brotherql_grocylabels:latest`. -As an example, you can launch this with `docker run -d -p 8000:8000 -e PRINTER_MODEL="QL-500" -e PRINTER_PATH="file:///dev/usb/lp1" sam159/brotherql_grocylabels:latest` +An example `docker-compose.yml` file can be found [here](docker-compose.yml). ## Contributing diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1c87fce --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3.8" + +services: + printer: + image: sam159/brotherql_grocylabels:latest + restart: unless-stopped + environment: + - PRINTER_MODEL=QL-500 + - PRINTER_PATH=file:///dev/usb/lp1 + ports: + - 8000:8000 From d2a7efe5cfc55f271fb787558c96e408a696d705 Mon Sep 17 00:00:00 2001 From: Sam Stevens Date: Mon, 25 Dec 2023 08:36:37 +0000 Subject: [PATCH 2/5] Scaling barcode by 2x or 4x if there is space on the label Set Datamatrix barcode to auto shape instead of fixed --- imaging.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/imaging.py b/imaging.py index 5d2e26a..022650e 100644 --- a/imaging.py +++ b/imaging.py @@ -2,11 +2,17 @@ from PIL import Image, ImageColor, ImageFont, ImageDraw def createBarcode(text: str): - encoded = encode(text.encode('utf8'), "Ascii", "32x32") + encoded = encode(text.encode('utf8'), "Ascii", "ShapeAuto") barcode = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels) return barcode def createLabelImage(labelSize : tuple, text : str, textFont : ImageFont, textMaxLines : int, barcode : Image, dueDate : str, dueDateFont : ImageFont): + # increase the size of the barcode if space permits + if (barcode.size[1] * 4) < labelSize[1]: + barcode = barcode.resize((barcode.size[0] * 4, barcode.size[1] * 4), Image.Resampling.NEAREST) + if (barcode.size[1] * 2) < labelSize[1]: + barcode = barcode.resize((barcode.size[0] * 2, barcode.size[1] * 2), Image.Resampling.NEAREST) + label = Image.new("RGB", labelSize, ImageColor.getrgb("#FFF")) barcode_padding = [0, (int)((label.size[1] / 2) - (barcode.size[1] / 2))] label.paste(barcode, barcode_padding) From eaf8896abb03e96bf98b813f7d2e21c541b61cfc Mon Sep 17 00:00:00 2001 From: Sam Stevens Date: Mon, 25 Dec 2023 08:48:16 +0000 Subject: [PATCH 3/5] Centering name on label and right aligning due date --- imaging.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/imaging.py b/imaging.py index 022650e..5223ef9 100644 --- a/imaging.py +++ b/imaging.py @@ -18,17 +18,25 @@ def createLabelImage(labelSize : tuple, text : str, textFont : ImageFont, textMa label.paste(barcode, barcode_padding) draw = ImageDraw.Draw(label) + + (nameText, nameTextWidth) = wrapText(text, textFont, label.size[0] - barcode.size[0], textMaxLines) + nameMaxWidth = label.size[0] - barcode.size[0] + nameLeftMargin = (nameMaxWidth - nameTextWidth) / 2 + + print((nameTextWidth, nameMaxWidth, nameLeftMargin)) + draw.multiline_text( - [barcode.size[1], 0], - wrapText(text, textFont, label.size[0] - barcode.size[0], textMaxLines), + [barcode.size[0] + nameLeftMargin, 0], + nameText, fill = ImageColor.getrgb("#000"), - font = textFont + font = textFont, + align = "center" ) if dueDate: - (_, _, _, ddbottom) = dueDateFont.getbbox(dueDate) + (_, _, ddRight, ddBottom) = dueDateFont.getbbox(dueDate) draw.text( - [barcode.size[1], label.size[1] - ddbottom], + [label.size[0] - ddRight, label.size[1] - ddBottom], dueDate, fill = ImageColor.getrgb("#000"), font = dueDateFont @@ -40,6 +48,7 @@ def wrapText(text : str, font : ImageFont, maxWidth : int, maxLines : int): parts = text.split(" ") parts.reverse() lines = [] + longestLine = 0 # break words that are too long for a single line trimmedParts = [] @@ -71,10 +80,13 @@ def wrapText(text : str, font : ImageFont, maxWidth : int, maxLines : int): # finished with the line if len(nextLine) > 0: - lines.append(' '.join(nextLine)); + lines.append(' '.join(nextLine)) + lineLength = font.getlength(' '.join(nextLine)) + if lineLength > longestLine: + longestLine = lineLength if len(lines) > maxLines: lines = lines[0:maxLines] lines[-1] += '...' - return '\n'.join(lines) \ No newline at end of file + return ('\n'.join(lines), longestLine) \ No newline at end of file From 1d017f7d74730855bf20a016dc28df3abc5410ee Mon Sep 17 00:00:00 2001 From: Sam Stevens Date: Mon, 25 Dec 2023 08:51:30 +0000 Subject: [PATCH 4/5] Updated example label --- README.md | 2 +- example.png | Bin 11996 -> 15026 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68c1bea..b4be288 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Brother QL Grocy Label Printer Service -![Example Label](example.png) +Example Label This project is intended to be a webhook target for [Grocy](https://github.com/grocy/grocy) to print labels to a brother QL label printer. Datamatrix barcodes are used instead of QR or linear barcodes, this matches what Grocy uses by default. diff --git a/example.png b/example.png index 3caf9c1e528c5d813973feaf936bf5c75b9f0092..3a2c59cf36be7f3f862af1dd616ec03c4db9b4a7 100644 GIT binary patch literal 15026 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 literal 11996 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 Date: Mon, 25 Dec 2023 08:54:31 +0000 Subject: [PATCH 5/5] Updated changelog for 0.2.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bdfd491 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# 0.2.0 + +- Scaling barcode by 2x or 4x space permitting +- Centered text \ No newline at end of file