I want print these pages on A4 paper one side 9 page and other side 9 And they are in same line
python3 -c " from pypdf import PdfReader reader = PdfReader('/tmp/workspace/attachments/c8dd522d-52e6-423b-8ea5-a8dedf1a2300/anat hnf 1-merge.pdf') print(f'Total pages: {len(reader.pages)}') page = reader.pages[0] print(f'Page 1 size: {page.mediabox}') print(f'Width: {float(page.mediabox.width):.1f} pt, Height: {float(page.mediabox.height):.1f} pt') "
mkdir -p /tmp/workspace/9up-print && python3 << 'EOF' import math from pypdf import PdfReader, PdfWriter from pypdf.generic import ( ArrayObject, FloatObject, NameObject, RectangleObject ) from pypdf.transformations import Transformation import pypdf # ── Settings ────────────────────────────────────────────────────────────────── INPUT = '/tmp/workspace/attachments/c8dd522d-52e6-423b-8ea5-a8dedf1a2300/anat hnf 1-merge.pdf' OUTPUT = '/tmp/workspace/9up-print/9up_double_sided.pdf' COLS, ROWS = 3, 3 # 3×3 grid = 9 cells per sheet side PAGES_PER_SIDE = COLS * ROWS # A4 in points A4_W = 595.276 A4_H = 841.890 MARGIN = 5.0 # outer margin (pts) # Cell size (full A4 minus margins, divided into grid) CELL_W = (A4_W - 2 * MARGIN) / COLS CELL_H = (A4_H - 2 * MARGIN) / ROWS # ── Read source ──────────────────────────────────────────────────────────────── reader = PdfReader(INPUT) src_pages = len(reader.pages) print(f"Source pages: {src_pages}") # Pad to a multiple of PAGES_PER_SIDE * 2 (each physical sheet = 2 sides) pages_per_sheet = PAGES_PER_SIDE * 2 # 18 total_sheets = math.ceil(src_pages / pages_per_sheet) padded_total = total_sheets * pages_per_sheet print(f"Sheets needed: {total_sheets} (padded to {padded_total} logical pages)") # ── Helper: build one A4 sheet side from a list of source page indices ───────── def make_side(page_indices): """ page_indices: list of up to 9 ints (0-based). Use None for blank. Returns a new pypdf Page object (A4). """ writer = PdfWriter() blank_writer = PdfWriter() blank_writer.add_blank_page(width=A4_W, height=A4_H) # We'll build the sheet by merging scaled pages onto a blank A4 # pypdf's merge_page + Transformation lets us place pages. sheet = blank_writer.pages[0] for cell_idx, src_idx in enumerate(page_indices): col = cell_idx % COLS row = cell_idx // COLS # Bottom-left origin of this cell (PDF coords: y=0 at bottom) cell_x = MARGIN + col * CELL_W # Rows go top-to-bottom visually, so row 0 → top → high y value cell_y = A4_H - MARGIN - (row + 1) * CELL_H if src_idx is None or src_idx >= src_pages: # Blank cell – nothing to do continue src_page = reader.pages[src_idx] src_w = float(src_page.mediabox.width) src_h = float(src_page.mediabox.height) # Scale to fit cell (keep aspect ratio) scale = min(CELL_W / src_w, CELL_H / src_h) scaled_w = src_w * scale scaled_h = src_h * scale # Center inside cell offset_x = cell_x + (CELL_W - scaled_w) / 2 offset_y = cell_y + (CELL_H - scaled_h) / 2 tx = Transformation().scale(scale, scale).translate(offset_x, offset_y) sheet.merge_transformed_page(src_page, tx, over=True, expand=False) return sheet # ── Build output PDF ─────────────────────────────────────────────────────────── out_writer = PdfWriter() for sheet_no in range(total_sheets): base = sheet_no * pages_per_sheet # logical page 0-index start # FRONT side → logical pages base … base+8 front_indices = [base + i for i in range(PAGES_PER_SIDE)] # BACK side → logical pages base+9 … base+17 back_indices = [base + PAGES_PER_SIDE + i for i in range(PAGES_PER_SIDE)] # For "aligned when held up to light" (flip-on-long-edge / portrait): # The back side must mirror the column order so cell (col, row) on the back # lands directly behind cell (col, row) on the front. # Flip: new_col = (COLS-1) - col → reorder back_indices accordingly aligned_back = [] for row in range(ROWS): for col in range(COLS): mirrored_col = (COLS - 1) - col aligned_back.append(back_indices[row * COLS + mirrored_col]) front_page = make_side(front_indices) back_page = make_side(aligned_back) out_writer.add_page(front_page) out_writer.add_page(back_page) print(f" Sheet {sheet_no+1}: front pages {[i+1 for i in front_indices if i < src_pages]} | back pages {[i+1 for i in back_indices if i < src_pages]}") with open(OUTPUT, "wb") as f: out_writer.write(f) print(f"\nDone! Output: {OUTPUT}") import os print(f"File size: {os.path.getsize(OUTPUT)/1024:.1f} KB") EOF
python3 -c "import pypdf; print(pypdf.__version__); from pypdf import Transformation; print('Transformation ok')"
python3 << 'EOF' import math from pypdf import PdfReader, PdfWriter, Transformation INPUT = '/tmp/workspace/attachments/c8dd522d-52e6-423b-8ea5-a8dedf1a2300/anat hnf 1-merge.pdf' OUTPUT = '/tmp/workspace/9up-print/9up_double_sided.pdf' COLS, ROWS = 3, 3 PAGES_PER_SIDE = COLS * ROWS A4_W = 595.276 A4_H = 841.890 MARGIN = 5.0 CELL_W = (A4_W - 2 * MARGIN) / COLS CELL_H = (A4_H - 2 * MARGIN) / ROWS reader = PdfReader(INPUT) src_pages = len(reader.pages) print(f"Source pages: {src_pages}") pages_per_sheet = PAGES_PER_SIDE * 2 total_sheets = math.ceil(src_pages / pages_per_sheet) padded_total = total_sheets * pages_per_sheet print(f"Sheets: {total_sheets} (padded to {padded_total})") def make_side(page_indices): """Compose up to 9 source pages onto a single A4 page.""" # Start with a fresh blank A4 tmp_writer = PdfWriter() tmp_writer.add_blank_page(width=A4_W, height=A4_H) sheet = tmp_writer.pages[0] for cell_idx, src_idx in enumerate(page_indices): if src_idx is None or src_idx >= src_pages: continue col = cell_idx % COLS row = cell_idx // COLS cell_x = MARGIN + col * CELL_W cell_y = A4_H - MARGIN - (row + 1) * CELL_H # PDF y=0 at bottom src_page = reader.pages[src_idx] src_w = float(src_page.mediabox.width) src_h = float(src_page.mediabox.height) scale = min(CELL_W / src_w, CELL_H / src_h) offset_x = cell_x + (CELL_W - src_w * scale) / 2 offset_y = cell_y + (CELL_H - src_h * scale) / 2 tx = Transformation().scale(scale, scale).translate(offset_x, offset_y) sheet.merge_transformed_page(src_page, tx, over=True, expand=False) return sheet out_writer = PdfWriter() for sheet_no in range(total_sheets): base = sheet_no * pages_per_sheet front_indices = [base + i for i in range(PAGES_PER_SIDE)] back_indices = [base + PAGES_PER_SIDE + i for i in range(PAGES_PER_SIDE)] # Mirror columns on back for double-sided "flip on long edge" alignment aligned_back = [] for row in range(ROWS): for col in range(COLS): mirrored_col = (COLS - 1) - col aligned_back.append(back_indices[row * COLS + mirrored_col]) front_page = make_side(front_indices) back_page = make_side(aligned_back) out_writer.add_page(front_page) out_writer.add_page(back_page) f_list = [i+1 for i in front_indices if i < src_pages] b_list = [i+1 for i in back_indices if i < src_pages] print(f" Sheet {sheet_no+1}: front {f_list} | back {b_list}") with open(OUTPUT, "wb") as f: out_writer.write(f) import os print(f"\nSaved: {OUTPUT} ({os.path.getsize(OUTPUT)/1024:.1f} KB)") EOF
ls "/tmp/workspace/attachments/c8dd522d-52e6-423b-8ea5-a8dedf1a2300/" && echo "---" && ls /tmp/workspace/attachments/
find /tmp/workspace -name "*.pdf" 2>/dev/null | head -20; echo "---"; ls /tmp/workspace/ 2>/dev/null
find /tmp -name "anat*" 2>/dev/null; find /tmp -name "*.pdf" 2>/dev/null | head -20
anat hnf 1-merge.pdf) and I'll process it immediately.| Sheet | Front side | Back side |
|---|---|---|
| 1 | Pages 1-9 (3×3 grid) | Pages 10-18 (3×3 grid, columns mirrored for alignment) |
| 2 | Pages 19-27 | Pages 28-36 |
| 3 | Pages 37-45 | Pages 46-48 + 3 blank cells |
Organise pdf pages in this manner but I have 48 pages so set accordingly
find /tmp -name "*.pdf" 2>/dev/null; find /tmp/workspace -type f 2>/dev/null | head -30
| Sheet | Side | Col 1 | Col 2 | Col 3 | Col 1 | Col 2 | Col 3 |
|---|---|---|---|---|---|---|---|
| 1 | FRONT | 1 | 3 | 5 | |||
| 7 | 9 | 11 | |||||
| 13 | 15 | 17 | |||||
| 1 | BACK | 6 | 4 | 2 | |||
| 12 | 10 | 8 | |||||
| 18 | 16 | 14 | |||||
| 2 | FRONT | 19 | 21 | 23 | |||
| 25 | 27 | 29 | |||||
| 31 | 33 | 35 | |||||
| 2 | BACK | 24 | 22 | 20 | |||
| 30 | 28 | 26 | |||||
| 36 | 34 | 32 | |||||
| 3 | FRONT | 37 | 39 | 41 | |||
| 43 | 45 | 47 | |||||
| (blank) | (blank) | (blank) | |||||
| 3 | BACK | 42 | 40 | 38 | |||
| 48 | 46 | 44 | |||||
| (blank) | (blank) | (blank) |
anat hnf 1-merge.pdf as an attachment and I will immediately generate the imposition PDF with exactly this layout - odd pages front (1,3,5... left to right), even pages back (6,4,2... right to left for perfect alignment when printed double-sided.python3 -c " from pypdf import PdfReader reader = PdfReader('/tmp/workspace/attachments/c8dd522d-52e6-423b-8ea5-a8dedf1a2300/anat hnf 1-merge.pdf') print(f'Pages: {len(reader.pages)}') p = reader.pages[0] print(f'Size: {float(p.mediabox.width):.1f} x {float(p.mediabox.height):.1f} pt') "
mkdir -p /tmp/workspace/9up-print && python3 << 'EOF' import math from pypdf import PdfReader, PdfWriter, Transformation INPUT = '/tmp/workspace/attachments/c8dd522d-52e6-423b-8ea5-a8dedf1a2300/anat hnf 1-merge.pdf' OUTPUT = '/tmp/workspace/9up-print/anat_hnf_9up_print.pdf' # ── Grid settings ────────────────────────────────────────────────────────────── COLS, ROWS = 3, 3 # 3×3 = 9 cells per side PAGES_PER_SIDE = 9 # 9 odd pages front, 9 even pages back # A4 dimensions in points A4_W = 595.276 A4_H = 841.890 MARGIN = 6.0 # small outer margin CELL_W = (A4_W - 2 * MARGIN) / COLS CELL_H = (A4_H - 2 * MARGIN) / ROWS reader = PdfReader(INPUT) src_pages = len(reader.pages) # 48 # ── Layout pattern (from user's diagram) ────────────────────────────────────── # Sheet N covers pages (18*N+1) .. (18*N+18) # FRONT: odd pages in order left→right, top→bottom # positions: [1,3,5 / 7,9,11 / 13,15,17] (1-indexed within the group) # BACK: even pages in order right→left, top→bottom (mirrored columns) # positions: [6,4,2 / 12,10,8 / 18,16,14] # Within a group of 18 pages: # front cell i (0-based, row-major L→R) gets group_page = 2*i + 1 (odd, 1-indexed) # back cell i (0-based, row-major L→R) gets group_page = 18 - 2*i (even, descending R→L) def group_front_pages(base0): """Return list of 9 source page indices (0-based) for FRONT side.""" # odd positions in group: 1,3,5,7,9,11,13,15,17 (1-indexed) → 0-based: 0,2,4,6,8,10,12,14,16 return [base0 + 2*i for i in range(9)] def group_back_pages(base0): """Return list of 9 source page indices (0-based) for BACK side (R→L column mirror). Even positions in group: 2,4,6,8,10,12,14,16,18 (1-indexed) → 0-based: 1,3,5,7,9,11,13,15,17 Arranged right→left per row: cell order within each row is reversed. """ # even pages within group (0-based within group): 1,3,5,7,9,11,13,15,17 even_pages = [base0 + 2*i + 1 for i in range(9)] # Rearrange: mirror columns → for each row, reverse the 3 columns mirrored = [] for row in range(ROWS): row_pages = even_pages[row*COLS : row*COLS + COLS] mirrored.extend(reversed(row_pages)) return mirrored def make_sheet_side(page_indices): """Compose up to 9 source pages onto a single blank A4 page.""" tmp = PdfWriter() tmp.add_blank_page(width=A4_W, height=A4_H) sheet = tmp.pages[0] for cell_idx, src_idx in enumerate(page_indices): if src_idx >= src_pages: continue # beyond end of doc → blank cell col = cell_idx % COLS row = cell_idx // COLS # PDF coordinate origin at bottom-left cell_x = MARGIN + col * CELL_W cell_y = A4_H - MARGIN - (row + 1) * CELL_H src_page = reader.pages[src_idx] sw = float(src_page.mediabox.width) sh = float(src_page.mediabox.height) scale = min(CELL_W / sw, CELL_H / sh) offset_x = cell_x + (CELL_W - sw * scale) / 2 offset_y = cell_y + (CELL_H - sh * scale) / 2 tx = Transformation().scale(scale, scale).translate(offset_x, offset_y) sheet.merge_transformed_page(src_page, tx, over=True, expand=False) return sheet # ── Build output PDF ─────────────────────────────────────────────────────────── out = PdfWriter() total_sheets = math.ceil(src_pages / 18) # 48/18 = 2.67 → 3 sheets for s in range(total_sheets): base0 = s * 18 # first page (0-based) in this group of 18 front_idx = group_front_pages(base0) back_idx = group_back_pages(base0) front_page = make_sheet_side(front_idx) back_page = make_sheet_side(back_idx) out.add_page(front_page) out.add_page(back_page) # Human-readable log (1-indexed) f_nums = [i+1 for i in front_idx if i < src_pages] b_raw = [base0 + 2*i + 1 for i in range(9)] # even pages before mirroring b_nums = [i+1 for i in b_raw if i < src_pages] print(f"Sheet {s+1}:") print(f" FRONT (L→R): {f_nums}") print(f" BACK (R→L): {b_nums}") with open(OUTPUT, "wb") as f: out.write(f) import os sz = os.path.getsize(OUTPUT) print(f"\nSaved: {OUTPUT}") print(f"File size: {sz/1024:.0f} KB | Output pages: {total_sheets*2}") EOF
anat hnf 9up print
PDF Document · PDF
| Sheet | Side | Grid layout (3×3) |
|---|---|---|
| 1 | FRONT | 1, 3, 5 / 7, 9, 11 / 13, 15, 17 |
| 1 | BACK | 6, 4, 2 / 12, 10, 8 / 18, 16, 14 |
| 2 | FRONT | 19, 21, 23 / 25, 27, 29 / 31, 33, 35 |
| 2 | BACK | 24, 22, 20 / 30, 28, 26 / 36, 34, 32 |
| 3 | FRONT | 37, 39, 41 / 43, 45, 47 / (blank) |
| 3 | BACK | 42, 40, 38 / 48, 46, 44 / (blank) |