Add project --refit to re-propose the content rectangle

Saved state always wins over a fresh proposal, which is what the
project file is for — but it also means a project made before detection
proposed a content rectangle keeps the old whole-page one forever, and
reopening or re-exporting changes nothing.

--refit re-runs the proposal over every page while leaving cuts,
discards, stepped cuts and metadata untouched. Verified on the real
Engel project: rectangles updated on all 6 pages, all 4 cuts per page
kept including both stepped ones, metadata intact, and exported slices
scale larger now that the margin shadow no longer pads the width.

--force remains the destructive option that re-detects everything.
This commit is contained in:
Esa Kataja
2026-07-28 23:35:10 +03:00
parent c00a00bb2a
commit 54b8e37657
+13
View File
@@ -61,6 +61,14 @@ def _project(args: argparse.Namespace) -> int:
print(f"{path.name}: loaded") print(f"{path.name}: loaded")
if project.source_changed(): if project.source_changed():
print(" WARNING: the PDF has changed since these cuts were made") print(" WARNING: the PDF has changed since these cuts were made")
if args.refit:
# Re-propose the content rectangle without disturbing cuts,
# discards or metadata — for projects made before detection
# proposed one, or whose rectangle was dragged wrong.
for i in range(len(project.pages)):
gray = page_raster(source, i)
project.pages[i].content_rect = detect_page(gray).content
print(f" content rectangle re-fitted on {len(project.pages)} pages")
else: else:
detections, heights = [], [] detections, heights = [], []
for i in range(len(source)): for i in range(len(source)):
@@ -145,6 +153,11 @@ def main(argv: list[str] | None = None) -> int:
proj.add_argument("pdf") proj.add_argument("pdf")
proj.add_argument("--save", action="store_true", help="write the project file") proj.add_argument("--save", action="store_true", help="write the project file")
proj.add_argument("--force", action="store_true", help="re-detect, discarding existing state") proj.add_argument("--force", action="store_true", help="re-detect, discarding existing state")
proj.add_argument(
"--refit",
action="store_true",
help="re-propose the content rectangle, keeping cuts and metadata",
)
proj.add_argument("--type", choices=[t.value for t in SourceType]) proj.add_argument("--type", choices=[t.value for t in SourceType])
proj.set_defaults(func=_project) proj.set_defaults(func=_project)