From 72e6e9333747f2f243fac046a412a6dec1492f99 Mon Sep 17 00:00:00 2001 From: n07070 Date: Thu, 12 Nov 2026 17:26:50 +0100 Subject: [PATCH] Add new printing options, change image conversion for Brother QL printers --- src/main.py | 40 +++++++++++++++++++++++++++--- src/printer.py | 21 +++++++++++++--- src/static/images/1x1.png | Bin 0 -> 153 bytes src/static/images/calibration.png | Bin 0 -> 8364 bytes src/templates/index.html | 22 ++++++++++------ src/web.py | 21 ++++++++++------ 6 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 src/static/images/1x1.png create mode 100644 src/static/images/calibration.png diff --git a/src/main.py b/src/main.py index 33d89e4..9f20795 100644 --- a/src/main.py +++ b/src/main.py @@ -173,9 +173,13 @@ def web_print_sms(): "No signature found for this print, using default signature : %s ", str(e) ) sign = configuration_file["defaults"]["signature"] + try: + do_cut = bool(request.form["cut"]) + except werkzeug.exceptions.BadRequestKeyError: + do_cut = False try: - web.print_sms(txt, sign) + web.print_sms(txt, sign, do_cut) except RuntimeError as e: app.logger.error("Whoops, we could not print an SMS because : %s ", str(e)) flash("Whoops, we could not print an SMS because :" + str(e), "error") @@ -219,9 +223,20 @@ def web_print_img(): flash("Submitted file has no filename !", "error") return redirect(url_for("index")) + try: + do_cut = bool(request.form["cut"]) + except werkzeug.exceptions.BadRequestKeyError: + do_cut = False + + try: + process_image = bool(request.form["process"]) + except werkzeug.exceptions.BadRequestKeyError: + process_image = False + + try: app.logger.debug("Sending the image to the printer.") - web.print_image(file, sign) + web.print_image(file, sign, do_cut, process_image) except RuntimeError as e: app.logger.error("The image could not be printed because : %s ", str(e)) flash("The image could not be printed because : " + str(e), "error") @@ -266,9 +281,16 @@ def api_print_sms(): "No signature found for this print, using default signature. : %s", str(e) ) sign = configuration_file["defaults"]["signature"] + + try: + do_cut = bool(request.form["cut"]) + except werkzeug.exceptions.BadRequestKeyError: + do_cut = False + + try: # comment: We try to print the SMS - web.print_sms(txt, sign) + web.print_sms(txt, sign, do_cut) except RuntimeError as e: return str(e), 500 # end try @@ -301,9 +323,19 @@ def api_print_image(): app.logger.error("Submitted file has no filename !") return "Submitted file has no filename !", 400 + try: + do_cut = bool(request.form["cut"]) + except werkzeug.exceptions.BadRequestKeyError: + do_cut = False + + try: + process_image = bool(request.form["process"]) + except werkzeug.exceptions.BadRequestKeyError: + process_image = False + try: app.logger.debug("Sending the image to the printer.") - web.print_image(file, sign) + web.print_image(file, sign, do_cut, process_image) except RuntimeError as e: return str(e), 500 diff --git a/src/printer.py b/src/printer.py index 66f81e5..ee337cb 100644 --- a/src/printer.py +++ b/src/printer.py @@ -460,22 +460,35 @@ class BrotherPrinter(Printer): """Print text after converting it to an image""" self._print_img(text_to_image(msg)) - def _print_img(self, data): + def _print_img(self, data, process=False): """ Print a raster image via a Brother QL printer """ self.ready = False + + if process: + try: + self.app.logger.debug("Proccessing the image") + processed_path = _process_image(self, data) + except RuntimeError as e: + self.app.logger.error( + "Error while processing the image, aborting print : %s", str(e) + ) + raise e + else: + processed_path = data + self.app.logger.warning("Not proccessing the image") try: selected_backend = guess_backend(self.printer_info.identifier) BACKEND_CLASS = backend_factory(selected_backend)['backend_class'] BACKEND_STRING_DESCR = self.printer_info.identifier - except Exception as e: + except Exception: self.app.logger.error("Couldn't guess the backend to use from the printer string descriptor") try: - im = Image.open(data) + im = Image.open(processed_path) qlr = BrotherQLRaster(self.printer_info.model) - create_label(qlr, im, self.printer_info.label_type, threshold=70, cut=False, rotate=0) + create_label(qlr, im, self.printer_info.label_type, cut=False, dither=True) # noinspection PyCallingNonCallable be = BACKEND_CLASS(BACKEND_STRING_DESCR) diff --git a/src/static/images/1x1.png b/src/static/images/1x1.png new file mode 100644 index 0000000000000000000000000000000000000000..ef90d30fb27334d661720d66217820c2afaf2b43 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0y~yVEh7PGjcEi$>noS9|m!XgWR1MZ=Tet2Xa`_9eo`c z7&i8E|4C#8@)eRjf_xbms?-=58d?|_egTCVUNA6}8Za=tN?>5Hn!&&zUNC1@pbbz$ w+|$J|#Nu@Fpa1{u4{J!UE=~~XX?n=Y(4)chfA62@O+Y0Kp00i_>zopr0P3bHCIA2c literal 0 HcmV?d00001 diff --git a/src/static/images/calibration.png b/src/static/images/calibration.png new file mode 100644 index 0000000000000000000000000000000000000000..066baf12b8391cb65f368c1ec92a5184c35d5220 GIT binary patch literal 8364 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 SK_&?NotIIPPCI+)_J0BB(z5vg literal 0 HcmV?d00001 diff --git a/src/templates/index.html b/src/templates/index.html index 4a7be1e..b20aeb7 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -6,13 +6,13 @@

Print a short message

- +
-
+
- +

@@ -28,11 +28,17 @@

-
-
- +
+
+ +
+
+ +

diff --git a/src/web.py b/src/web.py index 90f88ea..173ae06 100644 --- a/src/web.py +++ b/src/web.py @@ -16,7 +16,7 @@ class Web: self.print_queue = print_queue self.app = app - def print_sms(self, texte, sign: str) -> bool: + def print_sms(self, texte, sign: str, do_cut: bool) -> bool: """ Get text and a signature, prints the text and cuts after that. """ @@ -29,14 +29,18 @@ class Web: # are added back to back, another task could be # inserted between the two. sms = self.print_queue.enqueue(TextTask(content=texte, signature=sign)) - cut = self.print_queue.enqueue(CutTask()) + self.app.logger.info("Added a SMS task at position %s", sms) + + if do_cut: + cut = self.print_queue.enqueue(CutTask()) + self.app.logger.info("Added a CUT task at position %s", cut) except Exception as e: self.app.logger.error(e) raise RuntimeError("Could not add SMS to queue, " + str(e)) from e - self.app.logger.info("Added two new tasks at position %s and %s", sms, cut) + return True - def print_image(self, image, sign: str) -> bool: + def print_image(self, image, sign: str, do_cut: bool, process_image: bool) -> bool: """ Get an image and a signature, prints the image and cuts after that. """ @@ -56,16 +60,17 @@ class Web: secure_filename(image.filename), ), signature=sign, - process=True, + process=process_image, ) ) + self.app.logger.info("Added a IMG task at position %s", img) - cut = self.print_queue.enqueue(CutTask()) + if do_cut: + cut = self.print_queue.enqueue(CutTask()) + self.app.logger.info("Added a CUT task at position %s", cut) except Exception as e: raise RuntimeError("Could not add IMG to queue" + str(e)) from e - self.app.logger.info("Added two new tasks at position %s and %s", img, cut) - return True # def login(self, username: str, password: str) -> bool: