Skip to content

file: Unfold scanned booklets into sequential pages - #87

Open
sjg20 wants to merge 1 commit into
masterfrom
booklet-unfold
Open

file: Unfold scanned booklets into sequential pages#87
sjg20 wants to merge 1 commit into
masterfrom
booklet-unfold

Conversation

@sjg20

@sjg20 sjg20 commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Unfold scanned booklets into sequential pages

When a saddle-stitched booklet is taken apart (e.g. by pulling the
staples) and fed through a scanner, each scanned page holds two booklet
pages side by side, and the sheets only come out in reading order on the
outermost sheet. This adds an Unfold booklet operation that recovers
normal sequential pages automatically.

What it does

  • Splits each scanned page down the vertical middle into a left and a
    right half (no trimming — the full halves are kept, no page dropped).
  • Reorders the halves into reading order using the standard saddle-stitch
    imposition. For an 8-page booklet (4 scanned pages) the scans hold
    [8|1] [2|7] [6|3] [4|5] and unfold to 1 2 3 4 5 6 7 8.
  • Creates a new max stack and supports undo, mirroring the existing
    duplicate operation.
  • Available from the Duplicate… context submenu (and as an action).

Structure

  • File::bookletOrder() — pure helper computing the reading order;
    covered by a unit test (testBookletOrder).
  • File::addImageAsPage() — the page-writing logic factored out of
    copyTo() so the new path reuses it (no behaviour change to copyTo).
  • File::unfoldBooklet()Desktopmodel::opUnfoldBooklets() /
    unfoldBooklet()UCUnfoldBooklet undo → desktop action/slot/menu.

Tests

  • testBookletOrder — verifies the imposition for a 4-sheet booklet and
    that every source page contributes exactly one left and one right half.
  • testUnfoldBooklet — unfolds the test stack, checks the new stack is
    named testfile_unfold, is a Max, has twice the page count, and that
    undo removes it.

Note: the full GUI build could not be exercised locally (the sandbox
lacks the QtStateMachine dev headers used by desktopwidget.cpp); the
core objects and the test were compiled individually and the full
build/tests rely on CI.

When a saddle-stitched booklet is taken apart and scanned, each scanned
page holds two booklet pages side by side and the sheets come out in
reading order only on the outermost sheet. Recovering normal sequential
pages by hand is tedious, so add an 'Unfold booklet' operation that does
it automatically.

Each scanned page is split down the middle into a left and a right half
and the halves are reordered into reading order in a new stack. The
imposition is the standard saddle stitch: the outer sheet carries the
last and first pages, the next sheet the second and second-to-last, and
so on, alternating which half is the lower page number as the scan moves
from the outer to the inner sheets. The full halves are kept, so no page
is trimmed or dropped.

The reading order is worked out by bookletOrder(), a pure helper that is
covered by a unit test, and the page-writing logic in copyTo() is
factored into addImageAsPage() so the new path can reuse it. The
operation creates a new max stack and supports undo, mirroring the
existing duplicate operation.

Co-developed-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant