zinegen 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zinegen-0.1.0/.claude-plugin/marketplace.json +13 -0
- zinegen-0.1.0/.claude-plugin/plugin.json +11 -0
- zinegen-0.1.0/.github/workflows/ci.yml +24 -0
- zinegen-0.1.0/.github/workflows/publish.yml +18 -0
- zinegen-0.1.0/.gitignore +11 -0
- zinegen-0.1.0/.mcp.json +8 -0
- zinegen-0.1.0/AGENTS.md +93 -0
- zinegen-0.1.0/CHANGELOG.md +13 -0
- zinegen-0.1.0/LICENSE +21 -0
- zinegen-0.1.0/PKG-INFO +149 -0
- zinegen-0.1.0/README.md +118 -0
- zinegen-0.1.0/THIRD_PARTY_NOTICES.md +35 -0
- zinegen-0.1.0/docs/00-research.md +67 -0
- zinegen-0.1.0/docs/01-probe-results.md +58 -0
- zinegen-0.1.0/docs/02-design.md +54 -0
- zinegen-0.1.0/docs/03-schemas.md +121 -0
- zinegen-0.1.0/docs/getting-started.md +171 -0
- zinegen-0.1.0/examples/book.example.yaml +25 -0
- zinegen-0.1.0/probe/cmyk_probe.py +35 -0
- zinegen-0.1.0/probe/page.html +13 -0
- zinegen-0.1.0/pyproject.toml +59 -0
- zinegen-0.1.0/skills/zinegen/SKILL.md +56 -0
- zinegen-0.1.0/src/zinegen/__init__.py +1 -0
- zinegen-0.1.0/src/zinegen/check.py +87 -0
- zinegen-0.1.0/src/zinegen/cli.py +201 -0
- zinegen-0.1.0/src/zinegen/color.py +108 -0
- zinegen-0.1.0/src/zinegen/issues.py +54 -0
- zinegen-0.1.0/src/zinegen/layout.py +194 -0
- zinegen-0.1.0/src/zinegen/lr/__init__.py +0 -0
- zinegen-0.1.0/src/zinegen/lr/compat.py +156 -0
- zinegen-0.1.0/src/zinegen/presets.py +64 -0
- zinegen-0.1.0/src/zinegen/proof.py +60 -0
- zinegen-0.1.0/src/zinegen/render.py +164 -0
- zinegen-0.1.0/src/zinegen/schema/book.schema.json +98 -0
- zinegen-0.1.0/src/zinegen/server.py +154 -0
- zinegen-0.1.0/src/zinegen/spec.py +220 -0
- zinegen-0.1.0/src/zinegen/templates/book.html.j2 +41 -0
- zinegen-0.1.0/src/zinegen/templates/sRGB2014.icc +0 -0
- zinegen-0.1.0/tests/test_release.py +42 -0
- zinegen-0.1.0/tests/test_render.py +83 -0
- zinegen-0.1.0/tests/test_spec_layout.py +104 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "longfin",
|
|
3
|
+
"description": "Plugins by longfin",
|
|
4
|
+
"owner": { "name": "Swen Mun", "url": "https://github.com/longfin" },
|
|
5
|
+
"plugins": [
|
|
6
|
+
{
|
|
7
|
+
"name": "zinegen",
|
|
8
|
+
"source": "./",
|
|
9
|
+
"description": "Typeset a photobook or zine from a Lightroom album into a print-ready PDF/X (skill + MCP server)",
|
|
10
|
+
"category": "productivity"
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zinegen",
|
|
3
|
+
"displayName": "zinegen",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Typeset a photobook or zine from a Lightroom album into a print-ready PDF/X (skill + MCP server)",
|
|
6
|
+
"author": { "name": "Swen Mun", "url": "https://github.com/longfin" },
|
|
7
|
+
"homepage": "https://github.com/longfin/zinegen#readme",
|
|
8
|
+
"repository": "https://github.com/longfin/zinegen",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": ["lightroom", "photobook", "zine", "pdf/x", "prepress", "typesetting", "mcp"]
|
|
11
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- name: System libraries (pango for WeasyPrint, ghostscript for proofs, fonts)
|
|
14
|
+
run: |
|
|
15
|
+
sudo apt-get update
|
|
16
|
+
sudo apt-get install -y --no-install-recommends libpango-1.0-0 libpangoft2-1.0-0 ghostscript fontconfig fonts-dejavu-core fonts-nanum
|
|
17
|
+
- uses: astral-sh/setup-uv@v5
|
|
18
|
+
- run: uv venv && uv pip install -e ".[dev]" ruff
|
|
19
|
+
- run: .venv/bin/ruff check .
|
|
20
|
+
- run: .venv/bin/python -m pytest -q
|
|
21
|
+
- name: Package builds and ships its data files
|
|
22
|
+
run: |
|
|
23
|
+
uv build
|
|
24
|
+
unzip -l dist/*.whl | grep -E "schema/book.schema.json|templates/book.html.j2|templates/sRGB2014.icc"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pypi:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # PyPI trusted publishing, no token stored anywhere
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: astral-sh/setup-uv@v6
|
|
17
|
+
- run: uv build
|
|
18
|
+
- run: uv publish
|
zinegen-0.1.0/.gitignore
ADDED
zinegen-0.1.0/.mcp.json
ADDED
zinegen-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI agents working in this repository (Claude Code, Codex and others).
|
|
4
|
+
|
|
5
|
+
## What this project is
|
|
6
|
+
|
|
7
|
+
`zinegen` turns a Lightroom (cloud) album into a print-ready PDF/X. The agent is the typesetter: it edits
|
|
8
|
+
`books/<name>/book.yaml`, renders, looks at the spread proofs, and iterates. The human curates photos in
|
|
9
|
+
Lightroom and reviews proofs. See `README.md` for the pipeline and `skills/zinegen/SKILL.md` for the
|
|
10
|
+
typesetting workflow and taste rules.
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
src/zinegen/
|
|
16
|
+
lr/compat.py Lightroom helpers missing from lr-mcp (album order, captions, cached renditions)
|
|
17
|
+
presets.py trim presets, binding rules, spine width
|
|
18
|
+
spec.py book.yaml loading, JSON Schema validation, skeleton drafting
|
|
19
|
+
schema/ book.schema.json (book.yaml format, version 1)
|
|
20
|
+
issues.py issue codes shared by report.json and check.json
|
|
21
|
+
layout.py page geometry in mm, dpi/gutter report
|
|
22
|
+
render.py HTML -> WeasyPrint PDF/X, pikepdf post-processing
|
|
23
|
+
color.py ICC conversion (Pillow + LittleCMS), gamut check
|
|
24
|
+
proof.py Ghostscript page PNGs -> spread PNGs
|
|
25
|
+
check.py structural PDF/X self-check
|
|
26
|
+
cli.py `zinegen` subcommands
|
|
27
|
+
server.py MCP server (`zinegen mcp`), tools prefixed `zg_`
|
|
28
|
+
templates/ book.html.j2, fallback sRGB2014.icc
|
|
29
|
+
skills/zinegen/ agent skill
|
|
30
|
+
docs/ research, probe results, design (Korean)
|
|
31
|
+
probe/ reproducible experiments (not part of the package)
|
|
32
|
+
examples/ annotated book.example.yaml
|
|
33
|
+
books/ your books (git-ignored: they reference a private catalog)
|
|
34
|
+
tests/ pytest (no network)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Setup and commands
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv venv && . .venv/bin/activate && uv pip install -e ".[dev]"
|
|
41
|
+
zinegen doctor # pango, ghostscript, ICC profiles, Lightroom sign-in
|
|
42
|
+
python -m pytest -q # unit tests (spec, layout, presets)
|
|
43
|
+
zinegen build books/<name> # end-to-end on a real album (needs Lightroom sign-in); books/ is git-ignored
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
macOS: WeasyPrint needs `brew install pango`; `render.py` sets `DYLD_FALLBACK_LIBRARY_PATH` to the Homebrew
|
|
47
|
+
lib dir automatically. Ghostscript (`gs`) is required for proofs.
|
|
48
|
+
|
|
49
|
+
## Rules
|
|
50
|
+
|
|
51
|
+
- **Frozen formats** (see `docs/03-schemas.md`): `book.yaml` (`version: 1`, `schema/book.schema.json`),
|
|
52
|
+
`photos.json`, `out/report.json`, `out/check.json`. Add fields freely; renaming or removing one, or changing
|
|
53
|
+
a meaning, bumps that format's version and needs a migration note in the doc. New issue codes go in `issues.py`.
|
|
54
|
+
|
|
55
|
+
- **`book.yaml` is the only editable artefact of a book.** Never patch `out/interior.pdf` or `interior.html`.
|
|
56
|
+
If the renderer cannot express something, extend `layout.py`/`spec.py` and add a template.
|
|
57
|
+
- **Keep geometry explicit.** All image placement is computed in `layout.py` in millimetres so that dpi and
|
|
58
|
+
gutter crossing can be reported. Do not move placement into CSS (`object-fit` etc.).
|
|
59
|
+
- **PDF/X invariants** (checked by `check.py`): an output intent with an embedded profile, TrimBox and BleedBox
|
|
60
|
+
on every page, CMYK/Gray images only for X-1a, ICC-tagged RGB for X-4, no transparency on X-1a, all fonts
|
|
61
|
+
embedded. Any change to `render.py` or the template must keep `zinegen check` green on both standards.
|
|
62
|
+
- **Never recompress a source JPEG twice.** X-1a converts P3 -> CMYK once (cached in `cache/cmyk/`); X-4 embeds
|
|
63
|
+
the original bytes. Keep `optimize_images=False` and the DCT passthrough.
|
|
64
|
+
- **Lightroom access is read-only** and goes through `lr_mcp.client`. Do not add write calls. Do not print or
|
|
65
|
+
commit anything from `~/.config/lr-mcp/` (tokens, client secret).
|
|
66
|
+
- **ICC profiles and Apple/Adobe fonts are not redistributable.** Only `sRGB2014.icc` (from WeasyPrint) is bundled.
|
|
67
|
+
Resolve press profiles at run time (`color.find_profile`) and prefer OFL fonts (Nanum, Noto, Pretendard) as defaults.
|
|
68
|
+
- Functions that lr-mcp may adopt later live in `lr/compat.py` and must stay importable with only `lr_mcp.client`
|
|
69
|
+
as a dependency, so they can be upstreamed unchanged (lr-mcp issues #9, #10, #11).
|
|
70
|
+
- Tests must not touch the network. `tests/test_render.py` renders synthetic JPEGs through the real pipeline
|
|
71
|
+
(PDF/X-4 with an RGB output intent); anything that needs Lightroom or a CMYK profile is a manual `build` run.
|
|
72
|
+
- **One version, three places.** `pyproject.toml`, `.claude-plugin/plugin.json` and `metadata.version` in
|
|
73
|
+
`skills/zinegen/SKILL.md` must agree (`tests/test_release.py` checks). To release: bump all three, date the
|
|
74
|
+
CHANGELOG entry, commit, `git tag vX.Y.Z && git push --tags`, then `uv build` and `gh release create vX.Y.Z dist/*`. Publishing the GitHub release triggers
|
|
75
|
+
`publish.yml`, which uploads to PyPI through trusted publishing (no token in the repo or on any machine).
|
|
76
|
+
The repo root is both the plugin and a one-entry marketplace (`.claude-plugin/marketplace.json`, `.mcp.json`);
|
|
77
|
+
`claude plugin validate .` must pass.
|
|
78
|
+
- Lint with `ruff check .` (config in pyproject); CI runs ruff, pytest and a wheel build on Ubuntu.
|
|
79
|
+
- Commit messages: short imperative subject, body explaining why. Do not commit `books/*/cache`, `out`, `proof`,
|
|
80
|
+
PDFs or PNGs (see `.gitignore`).
|
|
81
|
+
|
|
82
|
+
## When typesetting a book (not developing the tool)
|
|
83
|
+
|
|
84
|
+
Load the skill in `skills/zinegen/SKILL.md` and follow it. In short: pick the album, draft with `zg_init_book`,
|
|
85
|
+
edit `book.yaml`, `zg_fetch` → `zg_render` → `zg_proof`, critique every spread, iterate two or three times,
|
|
86
|
+
finish with `zg_check` green and report warnings (low dpi, gutter crossing, padded pages) to the user.
|
|
87
|
+
|
|
88
|
+
## Open work
|
|
89
|
+
|
|
90
|
+
- Cover PDF (spine from `zinegen spine`, wrap-around layout, separate PDF/X).
|
|
91
|
+
- Local review GUI: spread viewer with comments the agent can read; no editing.
|
|
92
|
+
- Upstream `lr/compat.py` to lr-mcp.
|
|
93
|
+
- Real preflight comparison (Acrobat Pro / callas) and fixes for anything it flags.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-11-08
|
|
4
|
+
|
|
5
|
+
First public version.
|
|
6
|
+
|
|
7
|
+
- `book.yaml` spec (format version 1, JSON Schema) with trim presets, four bindings and nine page templates.
|
|
8
|
+
- Lightroom album import through lr-mcp: album order, captions, cropped size, cached full-size renditions.
|
|
9
|
+
- PDF/X-1a (CMYK via LittleCMS) and PDF/X-4 (ICC-tagged RGB passthrough) output with WeasyPrint.
|
|
10
|
+
- Spread proofs (Ghostscript) and a structural PDF/X self-check (pikepdf) with coded issues.
|
|
11
|
+
- CLI, MCP server (`zg_*` tools) and an agent skill for Claude Code / Codex.
|
|
12
|
+
- Installable as a Claude Code plugin (`/plugin install zinegen --marketplace longfin/zinegen`) and through
|
|
13
|
+
`npx skills add longfin/zinegen`.
|
zinegen-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Swen Mun
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
zinegen-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: zinegen
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent-driven photobook typesetting: Lightroom album -> print-ready PDF/X
|
|
5
|
+
Project-URL: Homepage, https://github.com/longfin/zinegen
|
|
6
|
+
Project-URL: Issues, https://github.com/longfin/zinegen/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/longfin/zinegen/blob/main/CHANGELOG.md
|
|
8
|
+
Author: Swen Mun
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent,lightroom,mcp,pdf/x,photobook,prepress,weasyprint
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
18
|
+
Classifier: Topic :: Printing
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Requires-Dist: jinja2>=3.1
|
|
21
|
+
Requires-Dist: jsonschema>=4.20
|
|
22
|
+
Requires-Dist: lr-mcp>=0.2
|
|
23
|
+
Requires-Dist: mcp<3,>=2.3
|
|
24
|
+
Requires-Dist: pikepdf>=9
|
|
25
|
+
Requires-Dist: pillow>=11
|
|
26
|
+
Requires-Dist: pyyaml>=6
|
|
27
|
+
Requires-Dist: weasyprint>=66
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# zinegen
|
|
33
|
+
|
|
34
|
+
[](https://github.com/longfin/zinegen/actions/workflows/ci.yml)
|
|
35
|
+
|
|
36
|
+
Agent-driven photobook typesetting: a Lightroom (cloud) album goes in, a print-ready **PDF/X** comes out.
|
|
37
|
+
One Python package provides a CLI, an MCP server and an agent skill, so Claude Code, Codex or any other
|
|
38
|
+
MCP-capable agent can act as the typesetter while you curate in Lightroom and review proofs.
|
|
39
|
+
|
|
40
|
+
No Adobe desktop app is required. Photos come from the Lightroom Partner API through
|
|
41
|
+
[lr-mcp](https://github.com/longfin/lr-mcp) as full-size JPEG renditions (Display P3, quality 92, 4:4:4),
|
|
42
|
+
which is enough for offset printing; see `docs/01-probe-results.md` for the measurements.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Lightroom album ──fetch──▶ cache/<asset>.jpg ──┐
|
|
46
|
+
book.yaml (edited by the agent / you) ─────────┴──render──▶ out/interior.pdf (PDF/X-1a or PDF/X-4)
|
|
47
|
+
──proof───▶ proof/spread-NN.png
|
|
48
|
+
──check───▶ out/check.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## What it does
|
|
52
|
+
|
|
53
|
+
- `book.yaml` is the single source of truth: trim size (presets or custom mm), bleed, binding, margins, fonts,
|
|
54
|
+
output standard, ICC profile and the page sequence with one of nine templates per page
|
|
55
|
+
(`title`, `blank`, `text`, `colophon`, `full-bleed`, `margin`, `pair`, `spread-full`, `spread-margin`).
|
|
56
|
+
- Page geometry is computed in millimetres, not left to CSS: every image placement reports its effective dpi
|
|
57
|
+
and whether it crosses the gutter. Spreads are forced to start on a left-hand page; the page count is padded
|
|
58
|
+
to the binding's multiple.
|
|
59
|
+
- **PDF/X-1a** (offset, 국내 인쇄소): images are converted to CMYK with LittleCMS (perceptual intent, black point
|
|
60
|
+
compensation) and embedded without a second JPEG generation; text and rules are DeviceCMYK.
|
|
61
|
+
- **PDF/X-4** (POD, Blurb-style services): the original P3 JPEGs are embedded losslessly and tagged with their ICC
|
|
62
|
+
profile; the output intent is still a CMYK press profile.
|
|
63
|
+
- Proof PNGs are composed as spreads so an agent can look at them (`zg_proof` returns images over MCP).
|
|
64
|
+
- A structural self-check (output intent, trim/bleed boxes, colour spaces, transparency, font embedding,
|
|
65
|
+
resolution) runs with pikepdf. It is not a replacement for Acrobat/callas preflight.
|
|
66
|
+
|
|
67
|
+
**New here?** Follow [docs/getting-started.md](docs/getting-started.md): it takes a Claude Code or Codex
|
|
68
|
+
subscriber from zero to a first PDF, and the agent can run it for you.
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
brew install pango ghostscript # WeasyPrint runtime, proof rendering (macOS; apt equivalents on Linux)
|
|
74
|
+
uv tool install lr-mcp && lr-mcp doctor # Lightroom credentials and sign-in: follow the lr-mcp README
|
|
75
|
+
uv tool install zinegen # from PyPI; for development: git clone, uv venv && uv pip install -e ".[dev]"
|
|
76
|
+
zinegen doctor
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
CMYK ICC profiles cannot be redistributed, so zinegen looks for the usual ones on the machine
|
|
80
|
+
(Adobe installs, ColorSync) and otherwise takes a path in `output.icc`. ISO Coated v2 / PSO Coated v3
|
|
81
|
+
can be downloaded free from [ECI](https://www.eci.org/).
|
|
82
|
+
|
|
83
|
+
## Register with an agent
|
|
84
|
+
|
|
85
|
+
`zinegen` must be on `PATH` first (`uv tool install`, above). Then pick one:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Claude Code: plugin install adds the skill and registers the `zinegen` MCP server in one step
|
|
89
|
+
/plugin install zinegen --marketplace longfin/zinegen
|
|
90
|
+
|
|
91
|
+
# Any agent that reads SKILL.md folders (Claude Code, Codex, Cursor, ...): skill only
|
|
92
|
+
npx skills add longfin/zinegen
|
|
93
|
+
codex mcp add zinegen -- "$(which zinegen)" mcp # Codex still needs the MCP server registered
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Without either tool, clone the repo and copy `skills/zinegen` into `~/.claude/skills/` or `~/.codex/skills/` and register the server
|
|
97
|
+
with `claude mcp add zinegen -s user -- "$(which zinegen)" mcp`.
|
|
98
|
+
|
|
99
|
+
Both agents also need the `lightroom` MCP server from lr-mcp for browsing and rating photos.
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
zinegen albums autumn # find the album id
|
|
105
|
+
zinegen init --album <album id> --dir books/autumn # draft book.yaml + photos.json
|
|
106
|
+
$EDITOR books/autumn/book.yaml # sequence, templates, captions
|
|
107
|
+
zinegen build books/autumn # fetch + render + proof + check
|
|
108
|
+
zinegen spine --pages 48 --caliper 110 # spine width from page count and paper caliper (µm)
|
|
109
|
+
zinegen presets # trim presets and binding rules
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
A complete annotated spec is in [`examples/book.example.yaml`](examples/book.example.yaml).
|
|
113
|
+
|
|
114
|
+
MCP tools: `zg_spec_help`, `zg_list_albums`, `zg_album_photos`, `zg_init_book`, `zg_fetch`, `zg_render`,
|
|
115
|
+
`zg_proof`, `zg_check`, `zg_spine`.
|
|
116
|
+
|
|
117
|
+
## Book directory
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
books/<name>/
|
|
121
|
+
book.yaml the spec (the only thing to edit)
|
|
122
|
+
photos.json photo metadata from Lightroom
|
|
123
|
+
cache/ renditions, index.json, cmyk/ conversions (ignored by git)
|
|
124
|
+
out/ interior.pdf, interior.html, report.json, check.json
|
|
125
|
+
proof/ page-NNN.png, spread-NN.png
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Docs
|
|
129
|
+
|
|
130
|
+
- `docs/getting-started.md` — zero-to-first-book guide for Claude Code / Codex users
|
|
131
|
+
- `AGENTS.md` — how an agent should work in this repo and with the tool
|
|
132
|
+
- `docs/00-research.md` — initial research (Korean)
|
|
133
|
+
- `docs/01-probe-results.md` — measured rendition quality and WeasyPrint PDF/X results (Korean)
|
|
134
|
+
- `docs/02-design.md` — design notes (Korean)
|
|
135
|
+
- `skills/zinegen/SKILL.md` — the agent skill
|
|
136
|
+
|
|
137
|
+
## Status
|
|
138
|
+
|
|
139
|
+
Alpha (0.1.0). Interior PDF for a single album, A5 perfect binding verified end to end against a real album;
|
|
140
|
+
the PDF/X output passes the built-in structural check but has not yet been through Acrobat/callas preflight.
|
|
141
|
+
Not yet: cover PDF with spine, review GUI, upstreaming the Lightroom helpers to lr-mcp (issues #9–#11 there).
|
|
142
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT. Third-party material and external tools are listed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
147
|
+
|
|
148
|
+
This project is not affiliated with, endorsed by, or sponsored by Adobe. Adobe, Lightroom and InDesign are
|
|
149
|
+
either registered trademarks or trademarks of Adobe in the United States and/or other countries.
|
zinegen-0.1.0/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# zinegen
|
|
2
|
+
|
|
3
|
+
[](https://github.com/longfin/zinegen/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Agent-driven photobook typesetting: a Lightroom (cloud) album goes in, a print-ready **PDF/X** comes out.
|
|
6
|
+
One Python package provides a CLI, an MCP server and an agent skill, so Claude Code, Codex or any other
|
|
7
|
+
MCP-capable agent can act as the typesetter while you curate in Lightroom and review proofs.
|
|
8
|
+
|
|
9
|
+
No Adobe desktop app is required. Photos come from the Lightroom Partner API through
|
|
10
|
+
[lr-mcp](https://github.com/longfin/lr-mcp) as full-size JPEG renditions (Display P3, quality 92, 4:4:4),
|
|
11
|
+
which is enough for offset printing; see `docs/01-probe-results.md` for the measurements.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Lightroom album ──fetch──▶ cache/<asset>.jpg ──┐
|
|
15
|
+
book.yaml (edited by the agent / you) ─────────┴──render──▶ out/interior.pdf (PDF/X-1a or PDF/X-4)
|
|
16
|
+
──proof───▶ proof/spread-NN.png
|
|
17
|
+
──check───▶ out/check.json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What it does
|
|
21
|
+
|
|
22
|
+
- `book.yaml` is the single source of truth: trim size (presets or custom mm), bleed, binding, margins, fonts,
|
|
23
|
+
output standard, ICC profile and the page sequence with one of nine templates per page
|
|
24
|
+
(`title`, `blank`, `text`, `colophon`, `full-bleed`, `margin`, `pair`, `spread-full`, `spread-margin`).
|
|
25
|
+
- Page geometry is computed in millimetres, not left to CSS: every image placement reports its effective dpi
|
|
26
|
+
and whether it crosses the gutter. Spreads are forced to start on a left-hand page; the page count is padded
|
|
27
|
+
to the binding's multiple.
|
|
28
|
+
- **PDF/X-1a** (offset, 국내 인쇄소): images are converted to CMYK with LittleCMS (perceptual intent, black point
|
|
29
|
+
compensation) and embedded without a second JPEG generation; text and rules are DeviceCMYK.
|
|
30
|
+
- **PDF/X-4** (POD, Blurb-style services): the original P3 JPEGs are embedded losslessly and tagged with their ICC
|
|
31
|
+
profile; the output intent is still a CMYK press profile.
|
|
32
|
+
- Proof PNGs are composed as spreads so an agent can look at them (`zg_proof` returns images over MCP).
|
|
33
|
+
- A structural self-check (output intent, trim/bleed boxes, colour spaces, transparency, font embedding,
|
|
34
|
+
resolution) runs with pikepdf. It is not a replacement for Acrobat/callas preflight.
|
|
35
|
+
|
|
36
|
+
**New here?** Follow [docs/getting-started.md](docs/getting-started.md): it takes a Claude Code or Codex
|
|
37
|
+
subscriber from zero to a first PDF, and the agent can run it for you.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
brew install pango ghostscript # WeasyPrint runtime, proof rendering (macOS; apt equivalents on Linux)
|
|
43
|
+
uv tool install lr-mcp && lr-mcp doctor # Lightroom credentials and sign-in: follow the lr-mcp README
|
|
44
|
+
uv tool install zinegen # from PyPI; for development: git clone, uv venv && uv pip install -e ".[dev]"
|
|
45
|
+
zinegen doctor
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
CMYK ICC profiles cannot be redistributed, so zinegen looks for the usual ones on the machine
|
|
49
|
+
(Adobe installs, ColorSync) and otherwise takes a path in `output.icc`. ISO Coated v2 / PSO Coated v3
|
|
50
|
+
can be downloaded free from [ECI](https://www.eci.org/).
|
|
51
|
+
|
|
52
|
+
## Register with an agent
|
|
53
|
+
|
|
54
|
+
`zinegen` must be on `PATH` first (`uv tool install`, above). Then pick one:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Claude Code: plugin install adds the skill and registers the `zinegen` MCP server in one step
|
|
58
|
+
/plugin install zinegen --marketplace longfin/zinegen
|
|
59
|
+
|
|
60
|
+
# Any agent that reads SKILL.md folders (Claude Code, Codex, Cursor, ...): skill only
|
|
61
|
+
npx skills add longfin/zinegen
|
|
62
|
+
codex mcp add zinegen -- "$(which zinegen)" mcp # Codex still needs the MCP server registered
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Without either tool, clone the repo and copy `skills/zinegen` into `~/.claude/skills/` or `~/.codex/skills/` and register the server
|
|
66
|
+
with `claude mcp add zinegen -s user -- "$(which zinegen)" mcp`.
|
|
67
|
+
|
|
68
|
+
Both agents also need the `lightroom` MCP server from lr-mcp for browsing and rating photos.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
zinegen albums autumn # find the album id
|
|
74
|
+
zinegen init --album <album id> --dir books/autumn # draft book.yaml + photos.json
|
|
75
|
+
$EDITOR books/autumn/book.yaml # sequence, templates, captions
|
|
76
|
+
zinegen build books/autumn # fetch + render + proof + check
|
|
77
|
+
zinegen spine --pages 48 --caliper 110 # spine width from page count and paper caliper (µm)
|
|
78
|
+
zinegen presets # trim presets and binding rules
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
A complete annotated spec is in [`examples/book.example.yaml`](examples/book.example.yaml).
|
|
82
|
+
|
|
83
|
+
MCP tools: `zg_spec_help`, `zg_list_albums`, `zg_album_photos`, `zg_init_book`, `zg_fetch`, `zg_render`,
|
|
84
|
+
`zg_proof`, `zg_check`, `zg_spine`.
|
|
85
|
+
|
|
86
|
+
## Book directory
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
books/<name>/
|
|
90
|
+
book.yaml the spec (the only thing to edit)
|
|
91
|
+
photos.json photo metadata from Lightroom
|
|
92
|
+
cache/ renditions, index.json, cmyk/ conversions (ignored by git)
|
|
93
|
+
out/ interior.pdf, interior.html, report.json, check.json
|
|
94
|
+
proof/ page-NNN.png, spread-NN.png
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Docs
|
|
98
|
+
|
|
99
|
+
- `docs/getting-started.md` — zero-to-first-book guide for Claude Code / Codex users
|
|
100
|
+
- `AGENTS.md` — how an agent should work in this repo and with the tool
|
|
101
|
+
- `docs/00-research.md` — initial research (Korean)
|
|
102
|
+
- `docs/01-probe-results.md` — measured rendition quality and WeasyPrint PDF/X results (Korean)
|
|
103
|
+
- `docs/02-design.md` — design notes (Korean)
|
|
104
|
+
- `skills/zinegen/SKILL.md` — the agent skill
|
|
105
|
+
|
|
106
|
+
## Status
|
|
107
|
+
|
|
108
|
+
Alpha (0.1.0). Interior PDF for a single album, A5 perfect binding verified end to end against a real album;
|
|
109
|
+
the PDF/X output passes the built-in structural check but has not yet been through Acrobat/callas preflight.
|
|
110
|
+
Not yet: cover PDF with spine, review GUI, upstreaming the Lightroom helpers to lr-mcp (issues #9–#11 there).
|
|
111
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT. Third-party material and external tools are listed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
116
|
+
|
|
117
|
+
This project is not affiliated with, endorsed by, or sponsored by Adobe. Adobe, Lightroom and InDesign are
|
|
118
|
+
either registered trademarks or trademarks of Adobe in the United States and/or other countries.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## Bundled
|
|
4
|
+
|
|
5
|
+
**`src/zinegen/templates/sRGB2014.icc`** — Copyright International Color Consortium, 2015.
|
|
6
|
+
Obtained from the WeasyPrint distribution (BSD-3-Clause), which bundles the ICC's reference sRGB profile.
|
|
7
|
+
The ICC makes this profile available under its standard terms: it may be copied, distributed, embedded, made,
|
|
8
|
+
used and sold without restriction; altered versions must have the original identification and copyright
|
|
9
|
+
information removed and must not be misrepresented as the original profile. zinegen ships it unaltered and
|
|
10
|
+
uses it only as a fallback RGB tag for untagged images and as an RGB output intent in tests.
|
|
11
|
+
|
|
12
|
+
## Not bundled, resolved on the user's machine
|
|
13
|
+
|
|
14
|
+
- **CMYK press profiles** (Japan Color 2001 Coated, Coated FOGRA39, U.S. Web Coated (SWOP) and others) are
|
|
15
|
+
looked up in Adobe/ColorSync/`/usr/share/color/icc` directories or taken from `output.icc`. They are never
|
|
16
|
+
copied into this repository or the package; their own licenses apply. ECI profiles (eci.org) are a free
|
|
17
|
+
alternative.
|
|
18
|
+
- **Fonts** are resolved through fontconfig and subset-embedded into the PDF. Default families (Nanum, Noto)
|
|
19
|
+
are SIL Open Font License fonts that permit embedding. If you configure a proprietary font in `fonts:`,
|
|
20
|
+
make sure its license allows embedding in documents.
|
|
21
|
+
- **Ghostscript** (AGPL-3.0) is invoked as a separate `gs` process for proof images only; it is not linked or
|
|
22
|
+
redistributed. Anyone who bundles Ghostscript together with zinegen (containers, installers) takes on the
|
|
23
|
+
AGPL obligations for that bundle.
|
|
24
|
+
- **Pango / Cairo / GLib** (LGPL-2.1+) are loaded by WeasyPrint as shared libraries.
|
|
25
|
+
|
|
26
|
+
## Python dependencies
|
|
27
|
+
|
|
28
|
+
| Package | License |
|
|
29
|
+
|---|---|
|
|
30
|
+
| lr-mcp | MIT |
|
|
31
|
+
| mcp | MIT |
|
|
32
|
+
| WeasyPrint, pydyf, tinycss2, Jinja2 | BSD-3-Clause |
|
|
33
|
+
| pikepdf | MPL-2.0 |
|
|
34
|
+
| Pillow (with LittleCMS) | MIT-CMU (LittleCMS: MIT) |
|
|
35
|
+
| jsonschema, PyYAML, fonttools | MIT |
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# zinegen 사전 조사 (2026-11-08)
|
|
2
|
+
|
|
3
|
+
lr-mcp로 가져온 Lightroom 앨범을 바탕으로, AI 에이전트가 조판하고 출판용(인쇄 입고 가능) PDF를 만드는 앱의 사전 조사 메모.
|
|
4
|
+
|
|
5
|
+
## 1. lr-mcp가 지금 주는 것 / 못 주는 것
|
|
6
|
+
|
|
7
|
+
소스: github.com/longfin/lr-mcp `src/lr_mcp/server.py`, `client.py` (2026-11-08 기준 main)
|
|
8
|
+
|
|
9
|
+
제공:
|
|
10
|
+
- 앨범 목록/검색, 앨범 내 사진 필터(날짜, 시간대, 별점, 플래그, 카메라/렌즈/조리개/ISO/파일명)
|
|
11
|
+
- 사진 요약: id, 파일명, 촬영시각, 별점, 플래그, 카메라, 렌즈, 노출값, 원본 픽셀 크기(`importSource.originalWidth/Height`)
|
|
12
|
+
- 현상 설정 요약(XMP develop의 주요 crs:* 키, `HasCrop`, `CropAngle` 포함)
|
|
13
|
+
- 렌디션 JPEG: thumbnail2x / 640 / 1280 / 2048 / 2560 / fullsize. 2560·fullsize는 `X-Generate-Renditions`로 생성 요청 후 2초 간격 폴링(최대 60초)
|
|
14
|
+
- 프로젝트 앨범 생성/추가/삭제(서버가 만든 앨범만)
|
|
15
|
+
|
|
16
|
+
미제공(확장 후보):
|
|
17
|
+
- 앨범의 사용자 정렬 순서(custom order). 현재 `lr_list_photos`는 촬영시각 순으로 정렬
|
|
18
|
+
- 제목/캡션(xmp dc:title, dc:description), 키워드, 색 라벨, GPS/위치
|
|
19
|
+
- 크롭 적용 후 실제 가로세로비(원본 크기만 노출. 렌디션 JPEG 픽셀 크기를 직접 읽어야 함)
|
|
20
|
+
- 원본(RAW/마스터) 다운로드. Partner API에 원본 다운로드 엔드포인트가 없다는 Adobe 측 답변(2024-07)이 커뮤니티에 인용됨. PUT /master(업로드)만 존재
|
|
21
|
+
- 렌디션 색공간/ICC. 문서에서 확인 못 함. 실측 필요(exiftool로 ICC 확인)
|
|
22
|
+
|
|
23
|
+
운영 제약:
|
|
24
|
+
- 생성된 2560/fullsize 렌디션은 1일 후 자동 삭제 → 로컬 캐시 필수
|
|
25
|
+
- 2560/fullsize는 "basic API access에서는 불가"라는 문구가 검색 결과에 인용됨(lr-mcp는 이미 사용 중이므로 현재 자격으로 되는지 확인)
|
|
26
|
+
- 크레덴셜당 베타 사용자 25명 제한 → 타인에게 배포하는 제품이면 Adobe 심사 필요
|
|
27
|
+
|
|
28
|
+
## 2. 인쇄 입고 사양(일반)
|
|
29
|
+
|
|
30
|
+
- 재단 여백(도련) 사방 3mm. A4 완성 210×297 → 작업 216×303mm
|
|
31
|
+
- 이미지 300dpi(최종 인쇄 크기 기준)
|
|
32
|
+
- 국내 인쇄소 대부분 CMYK 요구. RGB 입고 시 색 변환은 인쇄소가 임의로 함
|
|
33
|
+
- PDF/X-1a: CMYK/별색만, 투명도 불가. PDF/X-4: ICC 태그된 RGB·투명도 허용. 해외 POD(Blurb 등)와 디지털 인쇄는 X-4 또는 일반 PDF 수용이 많음
|
|
34
|
+
- 무선제본 책등 = (총 페이지 ÷ 2) × 종이 1장 두께(mm). 평량(g)이 아닌 두께(㎛)가 필요. 인쇄소/제지사 자료 필요
|
|
35
|
+
- 표지는 보통 내지와 별도 PDF(펼침: 뒷표지+책등+앞표지+도련)
|
|
36
|
+
- 검증: PDF/X 프리플라이트는 Acrobat Pro 또는 callas pdfToolbox. veraPDF는 PDF/A·UA만
|
|
37
|
+
|
|
38
|
+
해상도 환산(300dpi):
|
|
39
|
+
| 렌디션 | 긴 변 최대 인쇄 길이 |
|
|
40
|
+
|---|---|
|
|
41
|
+
| 2048px | 173mm |
|
|
42
|
+
| 2560px | 217mm (A5 세로 216mm 도련 포함 딱 맞음) |
|
|
43
|
+
| 24MP 6000px | 508mm (A4 펼침 426mm 가능) |
|
|
44
|
+
| 12MP 4000px | 339mm (A4 펼침은 240dpi) |
|
|
45
|
+
|
|
46
|
+
## 3. 렌더링 엔진 후보 (PDF/X 지원 관점)
|
|
47
|
+
|
|
48
|
+
| 엔진 | PDF/X | 이미지 RGB→CMYK | 도련/재단선 | 비고 |
|
|
49
|
+
|---|---|---|---|---|
|
|
50
|
+
| Typst | 없음(PDF/A, PDF/UA만) | 없음 | 수동 | 빠름, 텍스트 DSL이라 에이전트 친화적. PDF/X는 Ghostscript 후처리 필요 |
|
|
51
|
+
| WeasyPrint | pdf/x-1a, x-3, x-4, x-5g + output intent | 불명확 | @page bleed/marks | Python(lr-mcp와 동일). "유효성 보장 안 함" 명시 |
|
|
52
|
+
| Prince | X-1a/X-3/X-4 공식, 오류 보고 | 자동 변환, 이미지 ICC 존중 | @page bleed/marks | 상용. 가장 확실 |
|
|
53
|
+
| Chromium/Paged.js | 없음 | 없음 | Paged.js로 marks/bleed | 미리보기용으로는 최적(HTML 그대로 GUI) |
|
|
54
|
+
| 직접 생성(pikepdf/pdf-lib) | 직접 구현 | Pillow+LittleCMS | 직접 | 자유도 최대, 공수 최대 |
|
|
55
|
+
| InDesign(설치됨, MCP 있음) | 네이티브 | 네이티브 | 네이티브 | Adobe 라이선스 의존 |
|
|
56
|
+
| Ghostscript 후처리 | -dPDFX + PDFX_def.ps | -sColorConversionStrategy=CMYK | - | 버전별 동작 차이·버그 보고 있음 |
|
|
57
|
+
|
|
58
|
+
로컬 확인: gs 10.05, ImageMagick 7.1, exiftool, uv, node 24, InDesign 2026, Lightroom(Classic 포함) 설치됨.
|
|
59
|
+
|
|
60
|
+
## 4. 아키텍처 초안(에이전트 중심)
|
|
61
|
+
|
|
62
|
+
1. 수집: lr-mcp로 선별 → 로컬 캐시(렌디션 + 메타 JSON)
|
|
63
|
+
2. 북 스펙(선언적 파일, git 친화): 판형/도련/그리드/서체/시퀀스/스프레드별 템플릿/이미지 배치(초점·크롭)/캡션
|
|
64
|
+
3. 결정적 렌더러: 스펙 → PDF(인쇄용) + 저해상 PNG 프루프(스프레드 단위)
|
|
65
|
+
4. 에이전트 루프: 프루프 이미지를 보고 비평 → 스펙 수정 → 재렌더
|
|
66
|
+
5. GUI: 스프레드 뷰어 + 코멘트/승인만. 편집 기능 없음(또는 최소)
|
|
67
|
+
6. 출고: 내지 PDF/X + 표지 PDF/X + 프리플라이트 리포트
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# 실측 결과: Lightroom 렌디션 JPEG 적합성과 WeasyPrint PDF/X (2026-11-08)
|
|
2
|
+
|
|
3
|
+
## 1. Lightroom Partner API 렌디션 실측
|
|
4
|
+
|
|
5
|
+
대상: Ricoh GR IV DNG(25MP) 2장, 앨범 "20261107 단풍을찌것습니다", lr-mcp `lr_download_photos`로 수신.
|
|
6
|
+
|
|
7
|
+
| 항목 | fullsize | 2560 | 2048 |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| 픽셀 | 6192×4128 (원본 동일) | 2560×1706 | 2048×1365 |
|
|
10
|
+
| 용량 | 5.0MB | 0.8MB | 0.6MB |
|
|
11
|
+
| 비트 | 8bit | 8bit | 8bit |
|
|
12
|
+
| ICC | Display P3 임베드 | Display P3 | Display P3 |
|
|
13
|
+
| JPEG 품질 | 92 | 92 | 92 |
|
|
14
|
+
| 크로마 서브샘플링 | 없음(4:4:4) | 없음 | 없음 |
|
|
15
|
+
| 해상도 태그 | 300dpi | - | - |
|
|
16
|
+
| 생성 엔진 | Adobe Imagecore (Linux) | | |
|
|
17
|
+
| 메타데이터 | 제목/캡션/저작자 없음. EXIF 대부분 제거 | | |
|
|
18
|
+
|
|
19
|
+
판정: 출판 입고용으로 충분하다.
|
|
20
|
+
- 8bit/채널은 인쇄 RIP 입력의 업계 표준. 16bit 이점은 추가 보정 여지뿐이며, 보정은 Lightroom에서 끝내고 다시 받으면 된다.
|
|
21
|
+
- 품질 92 + 4:4:4는 시각적으로 무손실 수준. 재압축만 피하면 된다.
|
|
22
|
+
- Display P3는 sRGB보다 넓어 코티드 CMYK 색역 대부분을 담는다. 변환 시 임베드 ICC를 LittleCMS가 그대로 사용했다.
|
|
23
|
+
- 단점: 캡션·제목 메타데이터 없음(API로 따로 받아야 함), 출력 샤프닝 제어 불가, 생성 렌디션 1일 후 만료.
|
|
24
|
+
|
|
25
|
+
## 2. CMYK 변환 실측 (Pillow + LittleCMS)
|
|
26
|
+
|
|
27
|
+
Display P3 → 각 프로파일, 지각적 의도 + 흑점 보정. 풀해상도 변환 0.5초.
|
|
28
|
+
|
|
29
|
+
| 목적 프로파일 | 색역 밖 픽셀(상대색도 기준, 1/8 축소 샘플) |
|
|
30
|
+
|---|---|
|
|
31
|
+
| Japan Color 2001 Coated | 약 28% |
|
|
32
|
+
| Coated FOGRA39 | 약 25% |
|
|
33
|
+
| US Web Coated SWOP | 약 31% |
|
|
34
|
+
|
|
35
|
+
이 사진은 채도 +28, 포지티브 필름 프로파일의 단풍 사진이라 색역 밖 비율이 높다. JPEG 문제가 아니라 CMYK 색역의 한계이므로 소프트프루프(CMYK→sRGB 시뮬레이션)를 에이전트가 만들어 보여주고 Lightroom에서 조정하는 루프가 필요하다.
|
|
36
|
+
|
|
37
|
+
산출 CMYK JPEG(품질 95, 4:4:4): 약 22MB/장. CMYK TIFF LZW: 85~92MB/장.
|
|
38
|
+
|
|
39
|
+
## 3. WeasyPrint PDF/X 실측
|
|
40
|
+
|
|
41
|
+
환경: WeasyPrint 최신(uv), macOS에서 `brew install pango` 필요, `DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib`.
|
|
42
|
+
입력: A5(148×210) 2페이지 HTML, `@page { bleed: 3mm; marks: crop cross }`, `@color-profile --press { src: url(JapanColor2001Coated.icc); components: c,m,y,k }`, `output_intent="--press"`, CMYK JPEG 전면 배치 + 한글 캡션.
|
|
43
|
+
|
|
44
|
+
| 검사 항목 | PDF/X-1a | PDF/X-4 |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| PDF 버전 | 1.4 | 1.6 |
|
|
47
|
+
| OutputIntent GTS_PDFX + DestOutputProfile | ✓ Japan Color 2001 Coated | ✓ |
|
|
48
|
+
| GTS_PDFXVersion | PDF/X-1a:2003 (Info + XMP) | PDF/X-4 (XMP) |
|
|
49
|
+
| TrimBox / BleedBox | 419.5×595.3pt / +8.5pt(3mm) | 동일 |
|
|
50
|
+
| 이미지 | DCTDecode, DeviceCMYK, 6192×4128 재압축 없음 | 동일 |
|
|
51
|
+
| 서체 | Apple SD Gothic Neo 서브셋 임베드 | 동일 |
|
|
52
|
+
| 투명도/ExtGState alpha | 없음 | 없음 |
|
|
53
|
+
| 텍스트·괘선 색 | device-cmyk → DeviceCMYK 연산자 | 동일 |
|
|
54
|
+
| 재단선 | 렌더 확인됨 | 동일 |
|
|
55
|
+
|
|
56
|
+
주의: 미사용 `/Lab`, `/ICCBased` ColorSpace 리소스가 페이지 리소스에 남는다. 엄격한 X-1a 프리플라이트에서 걸릴 수 있으니 pikepdf 후처리로 제거하거나 Acrobat 프리플라이트로 확인 필요. 공식 PDF/X 검증 도구(Acrobat Pro Preflight, callas)로의 최종 검증은 아직 안 했다.
|
|
57
|
+
|
|
58
|
+
재현: `probe/cmyk_probe.py`, `probe/page.html`.
|