summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst162
-rw-r--r--bruder/__init__.py (renamed from bruder.py)17
-rw-r--r--bruder/__main__.py2
-rw-r--r--pyproject.toml40
-rw-r--r--svg_util.py2
5 files changed, 215 insertions, 8 deletions
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..906ac66
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,162 @@
+Bruder: Print pictures as collages with label tape printers
+===========================================================
+
+``bruder`` is a tool that helps you create collages out of label tape printed with a label printer such as Brother's
+P-touch devices.
+
+``bruder dither`` takes an SVG file with your design and some lines representing the labels' locations, and
+outputs a list of dithered PNG files, one for each label, ready for printing. Optionally, ``bruder print`` can also directly
+print these rendered images for you using the ``ptouch-print`` tool.
+
+For creating and tweaking your design, ``bruder`` has several helper utilities built-in. ``bruder template`` will generate a
+template with a label tape layout you give it that you can use to base your design off of. ``bruder preview`` will render
+a preview that approximates how the printed labels will look when you lay them out. ``bruder assembly`` will render an
+assembly diagram with labels indicating each label tape's number in the order output by ``bruder dither`` or `bruder
+print`.
+
+Quick start
+-----------
+
+1. Install ``bruder`` from PyPI using `pip install bruder`, and install ``usvg``, ``resvg``, ``didder`` and ``ptouch-print`` as
+ shown below under Dependencies_.
+2. Run ``bruder template template.svg`` to create a template with pre-generated label tape areas. The default tape width
+ is 24mm, but you can adjust this as you wish.
+3. Create a new SVG document and design your artwork in it.
+4. Copy the label tape areas from the template into your artwork SVG and save the resulting SVG. ``bruder`` will later
+ identify these areas by their color. You can copy or delete these, change the length of them, and move and rotate
+ them as you wish. Just make sure you don't skew or shear them and that you don't change their width so that they
+ still match the width of the tape that's physically in the printer you're using.
+5. Run ``bruder preview artwork_with_label_areas.svg`` on this SVG to render a preview image. By default, ``bruder`` will
+ open this preview image in your browser. If that doesn't work, run ``bruder preview [input].svg preview_out.svg`` to
+ write it to `preview_out.svg` and open that file with an SVG viewer of your choice. Adjust the content of your design
+ as necessary.
+6. Run ``bruder print artwork_with_label_areas.svg`` to print your artwork to a brother P-touch label printer connected
+ via USB.
+
+Dependencies
+------------
+
+usvg
+ ``usvg`` can be installed using ``cargo install usvg``.
+
+ ``usvg`` is used by ``bruder`` to simplify the input SVG file before processing it.
+
+resvg
+ ``resvg`` can be installed using ``cargo install resvg``.
+
+ ``bruder`` uses ``resvg`` to rasterize the SVG file.
+
+didder
+ ``didder`` can be installed from source at `https://github.com/makew0rld/didder <https://github.com/makew0rld/didder>`__.
+
+ ``bruder`` uses ``didder`` to dither the rasterized input, because these thermal label printers can only print two
+ colors and do not support grayscale.
+
+ptouch-print (optional)
+ ``ptouch-print`` can be installed from source at `https://git.familie-radermacher.ch/linux/ptouch-print.git <https://git.familie-radermacher.ch/linux/ptouch-print.git>`__.
+
+ ``bruder`` uses ``ptouch-print`` when you ask it to print the generated labels using ``bruder print``. You can also use
+ ``bruder dither`` to just generate a pile of PNGs, and use something else to print them.
+
+Command-Line Interface Usage
+----------------------------
+
+You can override where ``bruder`` looks for ``usvg``, ``resvg``, ``didder`` and ``ptouch-print`` by passing the full path to a
+binary through the environment variables ``USVG``, ``RESVG``, ``DIDDER`` and ``PTOUCH_PRINT``.
+
+You can override didder's dithering settings by passing the environment variable `DIDDER_ARGS`. The default value used
+when this variable is not set is `edm --serpentine FloydSteinberg`.
+
+.. code-block:: shell
+
+ bigdata~/p/bruder <3 python -m bruder --help
+ Usage: python -m bruder [OPTIONS] COMMAND [ARGS]...
+
+ Options:
+ --help Show this message and exit.
+
+ Commands:
+ assembly
+ dither
+ preview
+ print
+ template
+
+``bruder template``
+~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: shell
+
+ bigdata~/p/bruder <3 python -m bruder template --help
+ Usage: python -m bruder template [OPTIONS] [OUTPUT_SVG]
+
+ Options:
+ --num-rows INTEGER Number of tapes
+ --tape-width FLOAT Width of tape
+ --tape-border FLOAT Width of empty border at the edges of the tape in mm
+ --tape-spacing FLOAT Space between tapes
+ --tape-length FLOAT Length of tape segments
+ --magic-color TEXT SVG color of tape
+ --help Show this message and exit.
+
+``bruder preview``
+~~~~~~~~~~~~~~~~~~
+
+.. code-block:: shell
+
+ bigdata~/p/bruder <3 python -m bruder preview --help
+ Usage: python -m bruder preview [OPTIONS] [INPUT_SVG] [OUTPUT_SVG]
+
+ Options:
+ --magic-color TEXT SVG color of tape
+ --dpi FLOAT Printer bitmap resolution in DPI
+ --pixel-height INTEGER Printer tape vertical pixel height
+ --help Show this message and exit.
+
+``bruder dither``
+~~~~~~~~~~~~~~~~~
+
+.. code-block:: shell
+
+ bigdata~/p/bruder <3 python -m bruder dither --help
+ Usage: python -m bruder dither [OPTIONS] [INPUT_SVG] OUTPUT_DIR
+
+ Options:
+ --magic-color TEXT SVG color of tape
+ --dpi FLOAT Printer bitmap resolution in DPI
+ --pixel-height INTEGER Printer tape vertical pixel height
+ --help Show this message and exit.
+
+``bruder print``
+~~~~~~~~~~~~~~~~
+
+.. code-block:: shell
+
+ bigdata~/p/bruder <3 python -m bruder print --help
+ Usage: python -m bruder print [OPTIONS] [INPUT_SVG]
+
+ Options:
+ --magic-color TEXT SVG color of tape
+ --dpi FLOAT Printer bitmap resolution in DPI
+ --pixel-height INTEGER Printer tape vertical pixel height
+ --confirm / --no-confirm Ask for confirmation before printing each tape
+ --tape TEXT The index numbers of which tapes to print. Comma-
+ separate list, each entry is either a single
+ number or a "3-5" style range where both ends are
+ included.
+ --help Show this message and exit.
+
+``bruder assembly``
+~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: shell
+
+ bigdata~/p/bruder <3 python -m bruder assembly --help
+ Usage: python -m bruder assembly [OPTIONS] [INPUT_SVG] [OUTPUT_SVG]
+
+ Options:
+ --magic-color TEXT SVG color of tape
+ --dpi FLOAT Printer bitmap resolution in DPI
+ --pixel-height INTEGER Printer tape vertical pixel height
+ --help Show this message and exit.
+
diff --git a/bruder.py b/bruder/__init__.py
index 1b46033..f6f9ab5 100644
--- a/bruder.py
+++ b/bruder/__init__.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import tempfile
-import shutil
import webbrowser
import re
import base64
@@ -19,6 +18,9 @@ from bs4 import BeautifulSoup
from svg_util import *
+__version__ = "v1.0.0-rc1"
+
+
def run_cargo_command(binary, *args, **kwargs):
# By default, try a number of options:
candidates = [
@@ -161,7 +163,8 @@ def do_dither(soup, magic_color, dpi, pixel_height):
tmp_svg.flush()
run_cargo_command('resvg', tmp_svg.name, tmp_png.name, width=round(Inch(path_len, 'mm')*dpi), height=pixel_height)
- run_command('didder', 'edm', '--serpentine', 'FloydSteinberg', palette='black white', i=tmp_png.name, o=tmp_dither.name)
+ args = shlex.split(os.environ.get('DIDDER_ARGS', 'edm --serpentine FloydSteinberg'))
+ run_command('didder', *args, palette='black white', i=tmp_png.name, o=tmp_dither.name)
yield (x1, y1, path_angle, stroke_w, path_len), tmp_dither.read()
@@ -212,7 +215,7 @@ def cli():
@click.option('--tape-border', type=float, default=3, help='Width of empty border at the edges of the tape in mm')
@click.option('--tape-spacing', type=float, default=2, help='Space between tapes')
@click.option('--tape-length', type=float, default=250, help='Length of tape segments')
-@click.option('--magic-color', type=str, default='#cc0000', help='SVG color of tape')
+@click.option('--magic-color', type=str, default='#cc0301', help='SVG color of tape')
@click.argument('output_svg', type=click.File(mode='w'), default='-')
def template(num_rows, tape_width, tape_border, tape_spacing, tape_length, magic_color, output_svg):
pitch = tape_width + tape_spacing
@@ -234,7 +237,7 @@ def template(num_rows, tape_width, tape_border, tape_spacing, tape_length, magic
@cli.command('print')
-@click.option('--magic-color', type=str, default='#cc0000', help='SVG color of tape')
+@click.option('--magic-color', type=str, default='#cc0301', help='SVG color of tape')
@click.option('--dpi', type=float, default=180, help='Printer bitmap resolution in DPI')
@click.option('--pixel-height', type=int, default=127, help='Printer tape vertical pixel height')
@click.option('--confirm/--no-confirm', default=True, help='Ask for confirmation before printing each tape')
@@ -268,7 +271,7 @@ def cli_print(input_svg, tape, magic_color, dpi, pixel_height, confirm):
@cli.command()
-@click.option('--magic-color', type=str, default='#cc0000', help='SVG color of tape')
+@click.option('--magic-color', type=str, default='#cc0301', help='SVG color of tape')
@click.option('--dpi', type=float, default=180, help='Printer bitmap resolution in DPI')
@click.option('--pixel-height', type=int, default=127, help='Printer tape vertical pixel height')
@click.argument('input_svg', type=click.File(mode='r'), default='-')
@@ -278,7 +281,7 @@ def preview(input_svg, output_svg, magic_color, dpi, pixel_height):
@cli.command()
-@click.option('--magic-color', type=str, default='#cc0000', help='SVG color of tape')
+@click.option('--magic-color', type=str, default='#cc0301', help='SVG color of tape')
@click.option('--dpi', type=float, default=180, help='Printer bitmap resolution in DPI')
@click.option('--pixel-height', type=int, default=127, help='Printer tape vertical pixel height')
@click.argument('input_svg', type=click.File(mode='r'), default='-')
@@ -288,7 +291,7 @@ def assembly(input_svg, output_svg, magic_color, dpi, pixel_height):
@cli.command()
-@click.option('--magic-color', type=str, default='#cc0000', help='SVG color of tape')
+@click.option('--magic-color', type=str, default='#cc0301', help='SVG color of tape')
@click.option('--dpi', type=float, default=180, help='Printer bitmap resolution in DPI')
@click.option('--pixel-height', type=int, default=127, help='Printer tape vertical pixel height')
@click.argument('input_svg', type=click.File(mode='r'), default='-')
diff --git a/bruder/__main__.py b/bruder/__main__.py
new file mode 100644
index 0000000..aa0ea12
--- /dev/null
+++ b/bruder/__main__.py
@@ -0,0 +1,2 @@
+import bruder
+bruder.cli()
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..f71352a
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,40 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools]
+py-modules = ['bruder']
+
+[project]
+name = "bruder"
+version = "v1.0.0-rc1"
+description = "Print pictures as collages using label tape printers"
+readme = "README.rst"
+authors = [{name = "jaseg", email = "code@jaseg.de"}]
+license = {text = "GPLv2+ or LGPLv2.1+"}
+requires-python = ">=3.10"
+keywords = ['graphics', 'svg', 'printing', 'printer', 'label', 'label printer', 'brother', 'p-touch', 'dithering',
+ 'image processing', 'collage']
+dependencies = ['click', 'beautifulsoup4']
+classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: End Users/Desktop',
+ 'License :: OSI Approved :: BSD License',
+ 'Natural Language :: English',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Programming Language :: Python :: 3.12',
+ 'Topic :: Multimedia :: Graphics :: Editors :: Vector-Based',
+ 'Topic :: Multimedia :: Graphics :: Presentation',
+ 'Topic :: Printing',
+ 'Topic :: Scientific/Engineering :: Image Processing',
+ 'Topic :: System :: Hardware :: Universal Serial Bus (USB) :: Printer',
+ 'Topic :: Utilities',
+]
+
+[project.urls]
+homepage = "https://github.com/jaseg/bruder"
+
diff --git a/svg_util.py b/svg_util.py
index 6f6ac5f..009e9a5 100644
--- a/svg_util.py
+++ b/svg_util.py
@@ -6,7 +6,7 @@ from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class LengthUnit:
- """ Convenience length unit class. Used in :py:class:`.GraphicObject` and :py:class:`.Aperture` to store lenght
+ """ Convenience length unit class. Used in :py:class:`.GraphicObject` and :py:class:`.Aperture` to store length
information. Provides a number of useful unit conversion functions.
Singleton, use only global instances ``utils.MM`` and ``utils.Inch``.