# PT-E560BT Label Format (63 x 20 mm) Three-column label layout for the Brother P-touch EDGE **PT-E560BT**. ``` 0 20 mm 45 mm 63 mm +---------+------------+--------+ 0 | | static 1 | Q R | | LOGO | static 2 | C O | 1 mm non-printable gutter | 16x16 | static 3 | D E | | | VARIABLE | | +---------+------------+--------+ 20 mm 20 mm 25 mm 18 mm ``` ## Interface Run the new GUI: ```bash python label_printer_ptouch_gui.py ``` | Element | Purpose | |---|---| | **Inventory number** | The single variable value per label. Becomes the 4th text line **and** is embedded in the QR code. | | **PRINT LABEL** | Generates the PDF and sends it to the selected printer. | | **Preview area** | Renders the label at true print proportions. Updates as you type. | | **Advanced settings** | Logo image, the three static text lines, QR prefix/suffix, QR error correction. Saved to `label_config.json`. | The old three-row format is still available via `label_printer_gui.py` and is unchanged. ## Hardware constraints Verified against Brother's published specifications *and* the installed Windows driver (via `GetDeviceCaps`), which agree: | Spec | Value | Consequence | |---|---|---| | Print resolution | **180 dpi**, 128-dot head | 128 / 180 x 25.4 = **18.06 mm** is the hard height limit | | Max print height | **18.0 mm**, only with 24 mm tape | A 20 mm design cannot fit; it is not a margin setting | | Max tape width | 24 mm | **24 mm tape required** | Because the head reaches only ~18 mm of the 24 mm tape, ~3 mm is unused on each side. The label content is sized to the driver's **printable area**, read at runtime by `print_area.py`, rather than to the nominal media size. ### Driver resolution modes The Brother driver offers two modes, and the choice matters: | Mode | xdpi | ydpi | Notes | |---|---|---|---| | 1 | 180 | 180 | symmetric - use this | | 2 | 180 | 360 | **anisotropic**, 2x across the tape | In the anisotropic mode the driver reports twice the horizontal dots, and a page authored in millimetres can be scaled by the wrong factor and print short. `set_printer_resolution.py` reads and switches this setting: ```bash python set_printer_resolution.py # show current mode python set_printer_resolution.py --mode 180 # symmetric (recommended) python set_printer_resolution.py --restore # undo ``` ## Why the code is dot-aligned A thermal head cannot print a fraction of a dot. If a QR symbol is scaled to an arbitrary size, its modules end up unevenly sized (some 3 dots wide, some 4), which is the usual reason a small QR code will not scan. `build_code_bitmap()` snaps the symbol to an integer number of printer dots per module and returns the resulting exact physical size. At 16 mm available and 29 modules (a typical short payload), that is **3 dots per module = 12.28 mm**, which scans comfortably. `code_density_warning()` estimates density for the current payload and the GUI shows a warning when the code becomes too dense to be reliable, instead of silently printing an unscannable label. ## Code payload The code is composed as **fixed prefix + inventory + fixed suffix**, configured in Advanced settings: | Prefix | Inventory | Suffix | Encoded | |---|---|---|---| | `INV-` | `1234` | *(empty)* | `INV-1234` | | `INV-` | `1234` | `-A` | `INV-1234-A` | | *(empty)* | `1234` | *(empty)* | `1234` | The `Encodes:` line in Advanced settings shows the exact payload live as you type, so the result can be confirmed before printing. A legacy `{inventory}` template (e.g. `INV:{inventory}`) is still accepted and is migrated to prefix/suffix on first save, so older config files keep working. **Keep the payload short.** The QR is maximised to fill the printable height (~16.4 mm at 29 modules), which gives **4 printer dots per module** for a short payload. Longer strings raise the QR version, reducing dots per module; the GUI warns before printing a code that would be too dense to scan reliably. Error correction `L` allows a longer string than `M`/`Q`/`H` at the same physical size. ## Maximising the QR By default `qr_maximize` is enabled: the code column takes the full printable height so the symbol is as large as the hardware allows, and the text column shrinks to make room (never below `MIN_TEXT_COL_MM`, so the three static lines keep fitting). | Setting | QR size | Dots/module | |---|---|---| | `qr_maximize: false` (16 mm box) | 12.28 mm | 3 | | `qr_maximize: true` (default) | 16.37 mm | 4 | The symbol is flush to the right edge of the printable area when maximised. If your unit feeds the tape slightly off-centre, reduce `qr_box_mm` and set `qr_maximize: false` to leave clearance. ## Logo - Formats: PNG, JPG, JPEG, BMP, GIF. Greyscale and alpha are handled (transparent areas are flattened to white). - The logo is scaled to fit the 16 x 16 mm cell preserving aspect ratio. - Thermal transfer printing is 1-bit, so logos should be **black-and-white line art**. Photographs dither poorly. `logo_dither` controls this. ## Files | File | Role | |---|---| | `ptouch_label.py` | Layout engine: geometry, code generation, PDF + preview renderers | | `label_config.py` | Settings persistence (`label_config.json`) | | `label_printer_ptouch_gui.py` | Kivy GUI (this format) | | `print_label.py` | Printer discovery and silent printing (extended) | | `validate_ptouch_layout.py` | Geometry + QR round-trip validation | | `test_ptouch_pipeline.py` | End-to-end test (no hardware needed) | ## Tests ```bash python validate_ptouch_layout.py # page size, boxes, QR round-trip python test_ptouch_pipeline.py # config, PDF, printing, QR scaling ``` `validate_ptouch_layout.py` re-reads the rendered QR symbol out of the preview image, module by module, and compares it against the source matrix. That is what proves the preview and the PDF are the same layout, and that the symbol is geometrically intact after dot-alignment. ## Printing notes Only SumatraPDF printing honours the scale setting. The PDF is sent with `-print-settings noscale` because driver-side scaling ("fit to page") would distort the QR module pitch and break scanning. In the printer driver, set the media to the **63 x 20 mm** continuous tape and disable any auto-rotate. The TZe tape must be **24 mm**.