pkgprint
Print and packaging math — straight to your Python project.
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, orcheck_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.pkgprintships the correct2481 pxthreshold. - 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 300for 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.
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 pkgprint-0.2.1.tar.gz.
File metadata
- Download URL: pkgprint-0.2.1.tar.gz
- Upload date:
- Size: 37.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbd969caa34bf472958f9813f40cff97824047f39493c0f2be3d2c2b530d84f9
|
|
| MD5 |
f3b32c89cb234a81e2b710cd8211d148
|
|
| BLAKE2b-256 |
fa42bd94bae56bb8cc344512579547c8e9253d9c170341bdf828556b572c0dad
|
File details
Details for the file pkgprint-0.2.1-py3-none-any.whl.
File metadata
- Download URL: pkgprint-0.2.1-py3-none-any.whl
- Upload date:
- Size: 27.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5f086c0ef34dc88ad1efc4d7c4d53015eaadccc0e0b48c5c96a2805df47f72a
|
|
| MD5 |
e1c066235b13d551c2702b8f4ce3d15f
|
|
| BLAKE2b-256 |
6c86f707972b62bb054279bbd71cb0796347cd5c5326a04ec3c13fe8818b646f
|