Convert color images to CMYK-separated halftone SVG files for screen printing and risograph
Project description
Rosette
Convert a color image into ICC-accurate CMYK-separated halftone SVG files — one per channel, each a pure vector circle halftone at the correct screen angle.
Built for screen printing, risograph, and any additive color print workflow where you need clean separations as scalable vector art.
What Rosette Does
Rosette takes a color image and produces four SVG files:
cyan.svgmagenta.svgyellow.svgblack.svg
Each file contains only that channel's halftone dots as <circle> elements on a transparent background. Load them into Inkscape, Illustrator, or send directly to a print workflow.
Unlike raster-output tools, Rosette's SVGs are resolution-independent — scale them to any size without quality loss.
Installation
pip install rosette
Requires Python 3.10+. Dependencies: Pillow, NumPy, Click.
Usage
rosette IMAGE [OPTIONS]
Options
| Option | Default | Description |
|---|---|---|
--dots INTEGER |
100 | Dots per row (controls grid density) |
--preset TEXT |
us |
Screen angle preset (see table below) |
--angles C M Y K |
— | Manual per-channel angles in degrees; overrides --preset |
--min-radius FLOAT |
0 | Minimum dot radius as fraction of max (0–1) |
--channels TEXT |
cmyk |
Channels to generate: any combo of c, m, y, k |
--profile TEXT |
math |
CMYK conversion: math (geometric, recommended for screen/riso) or swop (ICC SWOP, offset stock) |
--gamma FLOAT |
1.5 |
Dot density curve. Higher = lighter/more open halftone. Lower = heavier. Range 0.5–3.0 typical |
--resample TEXT |
linear |
Resampling kernel: nearest, linear, lanczos2, lanczos3, spline36 |
--tac FLOAT |
220 |
Total Area Coverage limit (%). SWOP default 300; screen printing 160–200; riso 180–220 |
--output DIR |
./output |
Output directory |
--zip |
off | Package output SVGs into a single ZIP |
Setting dot density (--dots) and LPI
Because Rosette outputs SVG, LPI is not fixed at generation time — it's determined by how large you print the file. The relationship is simple:
--dots= target LPI × print width in inches
Use this table to find the right --dots value for your target LPI and print size:
| Target LPI | 4" wide | 5" wide | 8.5" wide | 11" wide | 17" wide |
|---|---|---|---|---|---|
| 35 lpi | 140 | 175 | 298 | 385 | 595 |
| 45 lpi | 180 | 225 | 383 | 495 | 765 |
| 55 lpi | 220 | 275 | 468 | 605 | 935 |
| 65 lpi | 260 | 325 | 553 | 715 | 1105 |
| 85 lpi | 340 | 425 | 723 | 935 | 1445 |
Typical ranges by process: screen printing 35–65 lpi · risograph 50–106 lpi · offset 85–150 lpi.
Image resolution note: for clean dot gradients, your input image should be at least --dots × 2 pixels wide. Below that, cell size drops under 2px and the blur/sampling pipeline has too little data to work with.
Examples
# Basic — US preset, 100 dots per row
rosette photo.jpg
# EU preset, higher density
rosette photo.jpg --preset eu --dots 150
# CMY only, no black plate, custom output directory
rosette photo.jpg --channels cmy --output ./separations
# Manual screen angles
rosette photo.jpg --angles 15 75 0 45
# Package into a ZIP
rosette photo.jpg --zip
# High-density black-only plate
rosette photo.jpg --channels k --dots 200 --output ./black-plate
CMYK Screen Angles
Halftone screens are rotated to prevent moiré patterns when the four color layers overlap. The classic approach assigns each channel a different angle:
| Preset | C | M | Y | K | Notes |
|---|---|---|---|---|---|
us |
15 | 75 | 0 | 45 | US standard — default |
eu |
15 | 45 | 0 | 75 | European standard |
alt-a |
15 | 45 | 30 | 45 | |
alt-b |
45 | 15 | 0 | 75 | |
alt-c |
45 | 75 | 0 | 15 | |
alt-d |
75 | 15 | 0 | 45 | |
alt-e |
75 | 45 | 0 | 15 | |
alt-f |
75 | 15 | 60 | 45 |
Why it matters: when two halftone screens at similar angles are overlaid, their dot patterns interfere and produce a visible grid artifact (moiré). Traditional offset printing separates the dominant inks (K and M) by 30°, with C 15° from K and Y on the least-visible 0° angle. Different presets trade off moiré characteristics — try eu if us shows artifacts on your specific press or paper.
For risograph and screen printing, angle choice also affects ink mixing behavior. Experimenting with the alt presets can produce different visual texture in overlapping color areas.
How It Works
- Load and convert — Pillow opens the image and converts to CMYK via ImageCms (lcms2) using the bundled Artifex CMYK SWOP ICC profile. If the image has an embedded ICC profile (AdobeRGB, P3, etc.) it is used as the input profile; otherwise sRGB is assumed. The SWOP profile handles black generation (GCR) internally.
- TAC limiting — any pixel where C+M+Y+K exceeds the
--tacthreshold is scaled down proportionally, preserving hue. SWOP is calibrated for 300% TAC on coated stock; screen printing and risograph workflows typically need 160–220%. - Pre-blur — each channel is Gaussian-blurred at radius = cell_size/2 before sampling, smoothing tonal transitions into clean dot gradients.
- Rotated grid — a dot grid is generated at the channel's screen angle, sized to cover the full image diagonal so no edge is missed at any rotation.
- Sampling — each dot's ink density is bilinear-sampled from the blurred channel at the dot centre position.
- Radius mapping — ink density maps to dot radius using area-proportional (square-root) scaling, so ink coverage is linear with density. Maximum radius is
cell_size × 0.47, keeping adjacent dots from merging in SVG solid-fill rendering. - SVG output — each channel becomes a standalone SVG with
<circle>elements, a transparent background, and a viewBox clipped to the original image dimensions.
License
AGPL-3.0-or-later. See LICENSE.
Acknowledgements
- Bundled ICC profiles (
sRGB.icc,SWOP.icc) are provided by Artifex Software as part of GPL Ghostscript, distributed here under AGPL-3.0. - Halftone approach and Pillow/ICC pipeline referenced from curegit/halftone-converter.
- Sampling and grid approach informed by evestera/svg-halftone.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rosette_halftone-1.0.0.tar.gz.
File metadata
- Download URL: rosette_halftone-1.0.0.tar.gz
- Upload date:
- Size: 158.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
904678a37bb19d8b5c528b58ff865a06bab433db0e9e84a575861bd481ed9aee
|
|
| MD5 |
a3483dfe67b0fbd08f1a2b36bf6e5e6a
|
|
| BLAKE2b-256 |
218942a46646a34f3147bab653660ce47c4821a4000130ec5978a067c38d7a8d
|
File details
Details for the file rosette_halftone-1.0.0-py3-none-any.whl.
File metadata
- Download URL: rosette_halftone-1.0.0-py3-none-any.whl
- Upload date:
- Size: 156.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50256cfd564c0fd17f4153a354de782e3c3578f4b032f790a37c47d2164e43f4
|
|
| MD5 |
2822f57cdbf63c576e6df7d4843eb517
|
|
| BLAKE2b-256 |
684d8b31c240f56b6d5f7014db677613226a1315c5d79a74d1955a7e680b92a5
|