| 418 | else: |
| 419 | |
| 420 | class ImageWriter(BaseWriter): # type: ignore[no-redef] |
| 421 | format: str |
| 422 | mode: str |
| 423 | dpi: int |
| 424 | |
| 425 | def __init__(self, format="PNG", mode="RGB", dpi=300) -> None: |
| 426 | """Initialise a new write instance. |
| 427 | |
| 428 | :params format: The file format for the generated image. This parameter can |
| 429 | take any value that Pillow accepts. |
| 430 | :params mode: The colour-mode for the generated image. Set this to RGBA if |
| 431 | you wish to use colours with transparency. |
| 432 | """ |
| 433 | super().__init__( |
| 434 | self._init, |
| 435 | self._paint_module, |
| 436 | self._paint_text, |
| 437 | self._finish, |
| 438 | ) |
| 439 | self.format = format |
| 440 | self.mode = mode |
| 441 | self.dpi = dpi |
| 442 | self._image: T_Image |
| 443 | self._draw: T_ImageDraw |
| 444 | |
| 445 | def _init(self, code: list[str]) -> None: |
| 446 | if ImageDraw is None: |
| 447 | raise RuntimeError("Pillow not found. Cannot create image.") |
| 448 | if len(code) != 1: |
| 449 | raise NotImplementedError("Only one line of code is supported") |
| 450 | line = code[0] |
| 451 | width, height = self.calculate_size(len(line), 1) |
| 452 | size = (int(mm2px(width, self.dpi)), int(mm2px(height, self.dpi))) |
| 453 | self._image = Image.new(self.mode, size, self.background) |
| 454 | self._draw = ImageDraw.Draw(self._image) |
| 455 | |
| 456 | def _paint_module(self, xpos: float, ypos: float, width: float, color): |
| 457 | size = [ |
| 458 | (mm2px(xpos, self.dpi), mm2px(ypos, self.dpi)), |
| 459 | ( |
| 460 | mm2px(xpos + width, self.dpi) - 1, |
| 461 | mm2px(ypos + self.module_height, self.dpi), |
| 462 | ), |
| 463 | ] |
| 464 | self._draw.rectangle(size, outline=color, fill=color) |
| 465 | |
| 466 | def _paint_text(self, xpos, ypos): |
| 467 | assert ImageFont is not None |
| 468 | |
| 469 | # check option to override self.text with self.human (barcode as |
| 470 | # human readable data, can be used to print own formats) |
| 471 | barcodetext = self.human if self.human != "" else self.text |
| 472 | |
| 473 | font_size = int(mm2px(pt2mm(self.font_size), self.dpi)) |
| 474 | if font_size <= 0: |
| 475 | return |
| 476 | font = ImageFont.truetype(self.font_path, font_size) |
| 477 | for subtext in barcodetext.split("\n"): |
no outgoing calls