From: Plom Heller Date: Mon, 2 Nov 2026 20:32:56 +0000 (+0100) Subject: Start page counts at 0 rather than 1, avoiding code confusion. X-Git-Url: https://plomlompom.com/repos/%7B%7Bprefix%7D%7D/%22https:/validator.w3.org/process?a=commitdiff_plain;h=8f37061463e6c37c2fab83b9e17b908ecf1d92c0;p=bookmaker Start page counts at 0 rather than 1, avoiding code confusion. --- diff --git a/README.txt b/README.txt index f27bf84..f192528 100644 --- a/README.txt +++ b/README.txt @@ -31,14 +31,14 @@ OVERVIEW OF TARGET USAGE: By cropping with -c and studying the results, define the areas of the input PDF's pages you want visible. Then, with--nup4, map those areas onto 4 input pages per 1 output page, arranged in such a way that double-sided print-out of those output pages can be cut, folded, and bound (helped by addition of stencils for small incisions to carry rubber bands or the like) into a small A6 book. Each unit of 8 pages from the input PDF is mapped by --nup4 onto two pages representing two sides of a (no-tumble-duplex-printed) A4 paper: +-------=-------+ __________________ - (front) (back) | 4 | 1 = 2 | 3 | 4 /=|===|============ + (front) (back) | 3 | 0 = 1 | 2 | 3 /=|===|============ +-------=-------+ ==> +-------=-------+ ===> _/|\_ v >=|===|============ -| 4 | 1 = 2 | 3 | / | \_ \=|===|============ -|-------=-------| +-------=-------+ 1-> | 2 | 3 | | \ / <- cut out! -| 8 | 5 = 6 | 7 | ==> | 8 | 5 = 6 | 7 | | _/ \_ | | \ | -+-------=-------+ +-------=-------+ |/ \| | \| (p. 5) +| 3 | 0 = 1 | 2 | / | \_ \=|===|============ +|-------=-------| +-------=-------+ 0-> | 1 | 2 | | \ / <- cut out! +| 7 | 4 = 5 | 6 | ==> | 7 | 4 = 5 | 6 | | _/ \_ | | \ | ++-------=-------+ +-------=-------+ |/ \| | \| (p. 4) -To turn this paper into a small 8-pages book, first cut it into two A5 papers along its horizontal middle. Fold both A5's by their vertical middles, with pages 2-3 and 7-6 on the folds' insides. You now have two 4-page A6 "books" of pages 1-4 and pages 5-8. Fold both closed and (counter-intuitively) stack the second one on top of the first one (creating a temporary page order of 5,6,7,8,1,2,3,4). This reveals a small stencil on the top left of page 5 – cut it out, with all other pages folded and aligned under it, creating a small notch in the upper "inner" corner of all pages. Turn around the stack to find a mirror stencil on the bottom and repeat the cutting. Each page now has cuts on top and bottom of its inner margins into which a rubber band can be hooked, or through which a string may be looped and tied, to bind the page's inner margins into a kind of book spine. You may now swap the order of the 4-page books back into a proper final page order (of 1,2,3,4,5,6,7,8) and repeat the whole process for each further --nup4 output paper. +To turn this paper into a small 8-pages book, first cut it into two A5 papers along its horizontal middle. Fold both A5's by their vertical middles, with pages 1-2 and 6-5 on the folds' insides. You now have two 4-page A6 "books" of pages 0-3 and pages 4-7. Fold both closed and (counter-intuitively) stack the second one on top of the first one (creating a temporary page order of 4,5,6,7,0,1,2,3). This reveals a small stencil on the top left of page 4 – cut it out, with all other pages folded and aligned under it, creating a small notch in the upper "inner" corner of all pages. Turn around the stack to find a mirror stencil on the bottom and repeat the cutting. Each page now has cuts on top and bottom of its inner margins into which a rubber band can be hooked, or through which a string may be looped and tied, to bind the page's inner margins into a kind of book spine. You may now swap the order of the 4-page books back into a proper final page order (of 0,1,2,3,4,5,6,7) and repeat the whole process for each further --nup4 output paper. COMMAND EXAMPLES: @@ -49,7 +49,7 @@ Produce OUTPUT.pdf containing all pages of (inclusive) page number range 3-7 fro bookmaker.py -i INPUT.pdf --page_range 3-7 -o OUTPUT.pdf Produce COMBINED.pdf from A.pdf's first 7 pages, B.pdf's pages except its first two, and all pages of C.pdf: - bookmaker.py -i A.pdf -p start-7 -i B.pdf -p 3-end -i C.pdf -o COMBINED.pdf + bookmaker.py -i A.pdf -p start-6 -i B.pdf -p 2-end -i C.pdf -o COMBINED.pdf Crop each page 5cm from the left, 10cm from the bottom, 2cm from the right, and 0cm from the top: bookmaker.py -i INPUT.pdf -o OUTPUT.pdf --crops "5,10,2,0" @@ -77,7 +77,7 @@ Same --nup4, but draw lines marking printable-region margins, page quarters, spi FURTHER NOTES: -For arguments like -p, page numbers are assumed to start with 1 (not 0, which is treated as an invalid page number value). +For arguments like -p, page numbers are assumed to start with 0 (i.e. first page at 0, second page at 1 …). If -p defines a page range beyond the source document's last page, the remaining pages will be created blank. diff --git a/src/bookmaker/misc.py b/src/bookmaker/misc.py index 89b1717..a291bf7 100755 --- a/src/bookmaker/misc.py +++ b/src/bookmaker/misc.py @@ -73,13 +73,11 @@ class PageRange: except ValueError: self._fail('carries value neither integer, nor ' f'"{_TOK_RANGE_START}", nor "{_TOK_RANGE_END}"') - if int(token) < 1: - self._fail('carries page number <1') str_start, str_end = self._code.split('-') if str_end not in {'', _TOK_RANGE_END}: self.end = int(str_end) if str_start not in {'', _TOK_RANGE_START}: - self.start = int(str_start) - 1 + self.start = int(str_start) def _fail( self, @@ -533,8 +531,8 @@ def _validate_args_syntax( if args.rotate_page: arg_char = 'r' for r in args.rotate_page: - if r < 1: - raise MsgFail('value must not be <1: {r}') + if r < 0: + raise MsgFail('value must not be <0: {r}') except MsgFail as e: raise ArgFail(arg_char, e.msg) from e try: @@ -584,16 +582,16 @@ class Book: f'cannot interpret {path} as PDF file') from e page_range = (args_page_range[i] if len(args_page_range) > i else PageRange(None)) - page_range.to_max(len(reader.pages)) + page_range.to_max(len(reader.pages)-1) for old_page_num in page_range.ranging(): - new_page_num += 1 page = (Page.new_blank() if old_page_num >= len(reader.pages) else Page(reader.pages[old_page_num])) self.pages += [page] if do_analyze: page.draw_borders((0.75, 0.0, 0.0)) - print(f'-i, -p: read in {path} page number {old_page_num+1} ' + print(f'-i, -p: read in {path} page number {old_page_num} ' f'as new page {new_page_num}') + new_page_num += 1 self._writer = PdfWriter() def __len__( @@ -627,7 +625,7 @@ class Book: ) -> None: 'For .pages numbered in args_rotate_page, rotate by 90°.' for rotate_page in args_rotate_page or []: - page = self.pages[rotate_page - 1] + page = self.pages[rotate_page] page.translate(tx=-A4_WIDTH/2, ty=-A4_HEIGHT/2) page.rotate(-90) page.translate(tx=A4_WIDTH/2, ty=A4_HEIGHT/2) @@ -690,14 +688,14 @@ class Book: for c_string in args_crops: range_code, crops = split_crops_string(c_string) page_range = PageRange(range_code) - page_range.to_max(len(self)) + page_range.to_max(len(self)-1) prefix = '-c, -t' if args_symmetry else '-c' suffix = ((' (but alternating left and right crop ' 'between even and odd pages)') if args_symmetry else '') page_crop = PageCrop(*(float(crop) for crop in crops.split(','))) - print(f'{prefix}: to pages {page_range.start + 1}:' + print(f'{prefix}: to pages {page_range.start}:' f'{page_range.end} applying crop: ' f'{page_crop.format_in_cm}{suffix}') for idx in page_range.ranging(): @@ -727,7 +725,7 @@ class Book: if arg_analyze: page.draw_borders((0.0, 0.0, 0.75)) page.add_to_writer(self._writer) - print(f'built page number {i+1} (of {len(self)})') + print(f'built page number {i} (of {len(self)})') def build_nup4_output( self, @@ -764,8 +762,8 @@ class Book: for page in self.pages: page.nup4_transforms(nup4_geometry, nup4_i) new_page.merge_page(page) - page_count += 1 print(f'merged page number {page_count} (of {len(self)})') + page_count += 1 nup4_i += 1 if nup4_i > 3: new_page.ornate_nup4(is_front_page, nup4_geometry, arg_analyze)