Skip to main content

pkgprint

Print and packaging math — straight to your Python project.

PyPI version Python 3.8+ License: MIT Tests

pkgprint is a Python library for the fiddly arithmetic behind print and packaging production: unit conversions, colour model translations, standard paper and box sizes, bleed calculations, print-readiness file checking, WCAG colour contrast validation, and box dieline layout. It's built for developers who work with print pipelines, packaging design tools, or any application that touches commercial print — people who need correct, well-tested answers, not approximations. The core math is zero-dependency; Pillow is only pulled in when you actually check image files.


Installation

pip install pkgprint

Quick Start

import pkgprint

# Look up a standard size and convert to inches
w, h = pkgprint.paper_size("A4")                    # (210, 297)
pkgprint.mm_to_inches(w)                            # 8.267716535433072

# Add 3 mm bleed to a US business card
pkgprint.add_bleed(89, 51)                          # (95, 57)

# Translate a brand colour between colour models
pkgprint.cmyk_to_rgb(0, 100, 100, 0)               # (255, 0, 0)
pkgprint.rgb_to_hex(255, 0, 0)                      # '#FF0000'

# Check text contrast against WCAG AA
pkgprint.contrast_ratio((0, 0, 0), (255, 255, 255)) # 21.0
result = pkgprint.check_wcag_compliance((140, 140, 140), (255, 255, 255))
result.passed                                        # False  (3.36:1 < 4.5)

# Calculate flat sheet size for a shipping box (RSC style)
pkgprint.rsc_flat_size(300, 200, 150)               # (1035.0, 350)

Why pkgprint?

  • Zero-dependency core. Unit conversions, colour math, paper sizes, bleed calculations — none of it needs an external package. Pillow is only imported when you call check_dpi, check_color_mode, or check_dimensions.
  • Formulas from the field. The WCAG relative luminance uses the exact sRGB gamma correction; RSC flat-size formulas match industry practice; paper sizes reference ISO 216 and ANSI standards. Shortcuts are flagged explicitly in docstrings.
  • Rigorous tests. 220+ tests covering normal cases, edge cases, and error paths. The suite caught a real production edge case during development: 2480 × 3508 px — the widely-cited "A4 at 300 DPI" pixel count — actually resolves to 299.97 DPI due to mm→inch rounding, and fails a 300 DPI check. pkgprint ships the correct 2481 px threshold.
  • MIT licensed, commercially free. Use it in client projects, SaaS products, or internal tooling without restriction.

Feature Overview

Module Description Functions
units mm ↔ inches ↔ points, DPI ↔ PPI conversions 6
color CMYK ↔ RGB ↔ hex colour model conversions 4
paper Standard paper sizes (ISO, ANSI, US) and common box dimensions 3
print_specs Bleed, safe margin, and trim size calculations 3
check Image file print-readiness: DPI, colour mode, and dimension checks 4 + 2 types
accessibility WCAG 2.1 contrast ratio checking and colour adjustment 4 + 1 type
dieline Flat sheet and named panel layout for RSC and Mailer box styles 3 + 1 type

Module Reference

📏 units — Measurement Conversions

Converts between the measurement units used throughout print and design workflows. DPI and PPI functions are semantic aliases — numerically identical, provided for clarity in code that mixes screen and print contexts.

Function Converts
mm_to_inches(mm) millimetres → inches
inches_to_mm(inches) inches → millimetres
mm_to_points(mm) millimetres → PostScript points (1 pt = 1/72 in)
points_to_mm(points) PostScript points → millimetres
dpi_to_ppi(dpi) DPI → PPI (identity, semantic alias)
ppi_to_dpi(ppi) PPI → DPI (identity, semantic alias)
import pkgprint

pkgprint.mm_to_inches(25.4)     # 1.0
pkgprint.mm_to_inches(210)      # 8.267716535433072  (A4 width)
pkgprint.inches_to_mm(1)        # 25.4
pkgprint.mm_to_points(25.4)     # 72.0  (1 inch = 72 pt)

🎨 color — Colour Model Conversions

Converts between the colour models used in print (CMYK) and screen/web (RGB, hex) workflows. CMYK channels use the 0–100 scale (percentage); RGB channels use 0–255.

Function Converts
cmyk_to_rgb(c, m, y, k) CMYK (0–100 each) → RGB (0–255 each)
rgb_to_cmyk(r, g, b) RGB (0–255 each) → CMYK (0–100 each)
hex_to_rgb(hex_str) Hex colour string → RGB tuple
rgb_to_hex(r, g, b) RGB tuple → hex colour string
import pkgprint

pkgprint.cmyk_to_rgb(0, 100, 100, 0)    # (255, 0, 0)   — pure red
pkgprint.cmyk_to_rgb(0, 0, 0, 100)      # (0, 0, 0)     — process black
pkgprint.rgb_to_cmyk(255, 0, 0)         # (0.0, 100.0, 100.0, 0.0)
pkgprint.rgb_to_hex(255, 0, 0)          # '#FF0000'
pkgprint.hex_to_rgb('#FF0000')          # (255, 0, 0)

📄 paper — Standard Paper & Box Sizes

Looks up standard paper sizes (ISO A-series, B-series, US Letter/Legal/Tabloid, business cards) and common shipping box sizes. All dimensions are in millimetres. Lookups are case-insensitive.

Function Returns
paper_size(name) (width_mm, height_mm) for a named paper size
list_paper_sizes() Sorted list of all available paper size names
box_size(name) (length_mm, width_mm, height_mm) for a named box size
import pkgprint

pkgprint.paper_size("A4")                 # (210, 297)
pkgprint.paper_size("Letter")             # (216, 279)
pkgprint.paper_size("Business Card US")   # (89, 51)
pkgprint.paper_size("Business Card ISO")  # (85, 55)
pkgprint.box_size("RSC Medium")           # (305, 229, 152)

pkgprint.list_paper_sizes()[:4]
# ['A0', 'A1', 'A2', 'A3']

Note on business card sizes: ISO/European business cards are 85×55 mm; US business cards are 89×51 mm (3.5"×2"). Both are available under distinct names.


✂️ print_specs — Bleed, Margin & Trim Calculations

Calculates the three key dimension sets in any print-ready file: the bleed size (artwork canvas with bleed added), the safe area (the zone guaranteed not to be trimmed), and the trim size (finished size recovered from a bled-up file).

Function Purpose
add_bleed(w, h, bleed_mm=3) Add bleed to both dimensions; returns (bleed_w, bleed_h)
safe_margin(w, h, margin_mm=5) Subtract safe margin; returns (safe_w, safe_h)
trim_size(w, h, bleed_mm=3) Recover trim size from a bled-up file; returns (trim_w, trim_h)
import pkgprint

# US business card: 89×51 mm trim, 3 mm bleed → canvas size
pkgprint.add_bleed(89, 51)               # (95, 57)

# A4 with 5 mm bleed
pkgprint.add_bleed(210, 297, bleed_mm=5) # (220, 307)

# Safe text area inside A4 (5 mm margin from each edge)
pkgprint.safe_margin(210, 297)           # (200, 287)

# Recover trim size from a 95×57 mm bled-up business card
pkgprint.trim_size(95, 57)               # (89, 51)

✅ check — Print-Readiness File Checker

Inspects an actual image file and reports whether it meets commercial print requirements. Requires Pillow (installed automatically with pip install pkgprint).

Each check returns a CheckResult with .passed, .actual, .expected, and .message. full_report() collects all three checks without raising on individual failures.

Function Checks
check_dpi(path, w_mm, h_mm, min_dpi=300) Effective DPI at the target print size
check_color_mode(path, required_mode="CMYK") Colour mode (CMYK, RGB, Grayscale…)
check_dimensions(path, w_mm, h_mm, tolerance_mm=1) Physical size at native DPI vs target
full_report(path, w_mm, h_mm, min_dpi=300, required_color_mode="CMYK") All three checks combined
import pkgprint

report = pkgprint.full_report("artwork.tif", 210, 297)

print(report.summary)
# DPI check:        PASS — Effective DPI 304.8 ≥ 300 ...
# Colour mode:      FAIL — Colour mode is 'RGB' but 'CMYK' is required ...
# Dimensions check: PASS — Dimensions 210.0×297.0 mm match target ...
# Overall:          NOT PRINT-READY

report.passed          # False
report.dpi.passed      # True
report.color_mode.passed  # False
report.dimensions.actual  # (210.0, 297.0)

# Individual checks
result = pkgprint.check_dpi("artwork.tif", 210, 297, min_dpi=300)
result.passed    # True / False
result.actual    # effective DPI on the worst axis
result.message   # human-readable diagnostic

Result types: CheckResult(passed, actual, expected, message) and PrintReport(dpi, color_mode, dimensions, passed, summary).


♿ accessibility — WCAG Colour Contrast Checker

Checks foreground/background colour pairs for legibility using the WCAG 2.1 contrast formulas — useful for packaging with text, label design, or any print piece with brand colour over a background.

WCAG thresholds: AA normal text = 4.5:1, AA large text = 3.0:1, AAA normal = 7.0:1, AAA large = 4.5:1.

Function Purpose
relative_luminance(r, g, b) WCAG sRGB relative luminance (0.0–1.0)
contrast_ratio(rgb1, rgb2) WCAG contrast ratio (1.0–21.0)
check_wcag_compliance(rgb1, rgb2, level="AA", text_size="normal") Pass/fail + ratio vs WCAG threshold
suggest_darker_or_lighter(rgb_text, rgb_bg, target_ratio=4.5) Adjusted text colour that meets the target ratio
import pkgprint

# Pure black on white: maximum contrast
pkgprint.contrast_ratio((0, 0, 0), (255, 255, 255))    # 21.0

# Mid-grey on white: fails AA normal text
result = pkgprint.check_wcag_compliance((140, 140, 140), (255, 255, 255))
result.passed          # False
result.ratio           # 3.36
result.required_ratio  # 4.5
result.message         # 'Contrast ratio 3.36:1 does NOT meet WCAG AA ...'

# Get an adjusted colour that passes
adjusted = pkgprint.suggest_darker_or_lighter(
    (140, 140, 140), (255, 255, 255), target_ratio=4.5
)
adjusted                                               # (118, 118, 118)
pkgprint.contrast_ratio(adjusted, (255, 255, 255))    # 4.54

Result type: ContrastResult(passed, ratio, required_ratio, level, text_size, message).


📦 dieline — Flat Panel Layout Calculator

Calculates the flat sheet dimensions and named panel sizes for common box styles, so designers know how large their artwork canvas needs to be before structural work starts.

Planning formulas only. These are standard industry approximations. They do not account for material thickness, flute direction, or supplier-specific tuck geometry. Confirm with your structural engineer or printer's dieline template before production.

Supported styles in v0.2.0: "RSC" (Regular Slotted Container) and "Mailer" (tuck-end mailer). More styles planned — see Roadmap.

Function Returns
rsc_flat_size(length, width, height) (flat_width_mm, flat_height_mm) for an RSC box
mailer_flat_size(length, width, height) (flat_width_mm, flat_height_mm) for a tuck mailer
panel_layout(length, width, height, style="RSC") List of Panel objects with name, width_mm, height_mm
import pkgprint

# Flat canvas for a 300×200×150 mm RSC shipping box
pkgprint.rsc_flat_size(300, 200, 150)        # (1035.0, 350)
# flat_width  = 2×(300+200) + 35 mm glue flap = 1035 mm
# flat_height = 150 + 200 (top + bottom flaps each = W/2) = 350 mm

# Named panels for the same box
panels = pkgprint.panel_layout(300, 200, 150)
len(panels)       # 13  (4 body + 8 flaps + 1 glue flap)
panels[0]         # Panel(name='front', width_mm=300, height_mm=150)
panels[1]         # Panel(name='right side', width_mm=200, height_mm=150)

# Tuck mailer: 200×100×50 mm
pkgprint.mailer_flat_size(200, 100, 50)      # (635.0, 300.0)
pkgprint.panel_layout(200, 100, 50, style="Mailer")
# 7 panels: front, right side, back, left side,
#           top tuck flap, bottom tuck flap, glue flap

Result type: Panel(name, width_mm, height_mm).


Real-World Use Case

Scenario: Preparing a client's business card artwork for print.

A client uploads a logo file intended for their US business card (89×51 mm). Before sending to print, you need to verify the file meets your printer's spec, add bleed, and check that their brand colour — a warm grey — will actually be legible as text over the card's white background. With pkgprint, you look up the standard size with paper_size("Business Card US"), then run full_report() on the uploaded file: it instantly tells you the effective DPI at that print size, whether the file is CMYK or RGB (most printers require CMYK), and whether the physical dimensions match. You then call add_bleed(89, 51) to get the 95×57 mm canvas size your designer needs. Finally, check_wcag_compliance(brand_grey, (255, 255, 255)) flags that the grey is only 3.36:1 contrast — failing AA — and suggest_darker_or_lighter() proposes an adjusted value that passes, keeping the hue intact. The whole check pipeline runs in under a second, before anything goes to the print queue.


Testing & Quality

pkgprint ships with 220 tests across 7 test files, one per module. The suite covers:

  • Normal operation, edge cases (zero bleed, exact threshold values), and error paths (wrong types, out-of-range inputs, missing files)
  • Both WCAG AA and AAA thresholds for all four normal/large text combinations
  • Programmatically generated image fixtures for check.py — no binary assets committed to the repo

A note on rigor: During development, the test suite caught a subtle real-world edge case. 2480 × 3508 px is widely cited as "A4 at 300 DPI", but 2480 ÷ (210 mm / 25.4) = 299.97 DPI — fractionally below 300 due to mm→inch conversion. The correct pixel count is 2481 × 3508. The test suite uses the accurate value and the check_dpi function enforces the correct threshold.


Roadmap

  • SVG dieline output — generate production-ready flat dieline artwork directly from panel_layout() (v0.3.0)
  • Extended box styles — crash-lock bottom, auto-bottom, five-panel wrap, and more
  • Expanded paper standards — JIS B-series, Japanese Shiroku-ban, additional envelope sizes
  • CLI tool — pkgprint check artwork.tif --size A4 --dpi 300 for quick pre-flight from the terminal

Contributing

Bug reports, feature requests, and pull requests are welcome at github.com/Rishabh55122/pkgprint/issues. Please open an issue before starting significant work so we can align on approach.


License

MIT — see LICENSE. Free to use in commercial and open-source projects.

Metadata

Release files for pkgprint 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pkgprint 0.2.1
File Size Uploaded Provenance
pkgprint-0.2.1.tar.gz 37.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pkgprint 0.2.1
File Interpreter ABI Platform
pkgprint-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 64.8 kB

Release files / pkgprint-0.2.1.tar.gz

Download URL pkgprint-0.2.1.tar.gz
Size 37.8 kB
Tags Source
SHA-256 checksum
How to use checksums
bbd969caa34bf472958f9813f40cff97824047f39493c0f2be3d2c2b530d84f9
BLAKE2b-256 checksum
How to use checksums
fa42bd94bae56bb8cc344512579547c8e9253d9c170341bdf828556b572c0dad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.6

Release files / pkgprint-0.2.1-py3-none-any.whl

Download URL pkgprint-0.2.1-py3-none-any.whl
Size 27.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e5f086c0ef34dc88ad1efc4d7c4d53015eaadccc0e0b48c5c96a2805df47f72a
BLAKE2b-256 checksum
How to use checksums
6c86f707972b62bb054279bbd71cb0796347cd5c5326a04ec3c13fe8818b646f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.6

Security for pkgprint 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page