Skip to main content

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.

palettary.com/halftone


What Rosette Does

Rosette takes a color image and produces four SVG files:

  • cyan.svg
  • magenta.svg
  • yellow.svg
  • black.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

  1. 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.
  2. TAC limiting — any pixel where C+M+Y+K exceeds the --tac threshold is scaled down proportionally, preserving hue. SWOP is calibrated for 300% TAC on coated stock; screen printing and risograph workflows typically need 160–220%.
  3. Pre-blur — each channel is Gaussian-blurred at radius = cell_size/2 before sampling, smoothing tonal transitions into clean dot gradients.
  4. 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.
  5. Sampling — each dot's ink density is bilinear-sampled from the blurred channel at the dot centre position.
  6. 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.
  7. 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

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

rosette_halftone-1.0.0.tar.gz (158.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rosette_halftone-1.0.0-py3-none-any.whl (156.1 kB view details)

Uploaded Python 3

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

Hashes for rosette_halftone-1.0.0.tar.gz
Algorithm Hash digest
SHA256 904678a37bb19d8b5c528b58ff865a06bab433db0e9e84a575861bd481ed9aee
MD5 a3483dfe67b0fbd08f1a2b36bf6e5e6a
BLAKE2b-256 218942a46646a34f3147bab653660ce47c4821a4000130ec5978a067c38d7a8d

See more details on using hashes here.

File details

Details for the file rosette_halftone-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for rosette_halftone-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 50256cfd564c0fd17f4153a354de782e3c3578f4b032f790a37c47d2164e43f4
MD5 2822f57cdbf63c576e6df7d4843eb517
BLAKE2b-256 684d8b31c240f56b6d5f7014db677613226a1315c5d79a74d1955a7e680b92a5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page