From 9bc4a0d7bfa703fb2ccb67e8290cf517ae72e16b Mon Sep 17 00:00:00 2001 From: Francesco Baldino Date: Fri, 19 May 2023 13:59:03 +0200 Subject: [PATCH 1/8] added bookletify --- README.md | 5 +++ bookletify.py | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100755 bookletify.py diff --git a/README.md b/README.md index dc2cd67..8ce143d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ Questa repository contiene i seguenti script: Consente di impaginare un pdf in modo da poi poterlo stampare "a libretto" +- `bookletify` — [@Fran314](https://git.phc.dm.unipi.it/Fran314) + + Simile a impagina, ma in python. Formatta un pdf in modo da poi poterlo stampare "a libretto" chiudendolo come un libro invece di sovrapporre una metà sull'altra. + Necessita di PyPDF2 installato con pip per funzionare + - `gobbino` — [@BachoSeven](https://git.phc.dm.unipi.it/BachoSeven) + [@Dilillo](http://poisson.phc.dm.unipi.it/~dilillo/Vario/index.html) Permette di scaricare video e/o pdf di qualsiasi corso presente sul sito del professor Gobbino diff --git a/bookletify.py b/bookletify.py new file mode 100755 index 0000000..4739346 --- /dev/null +++ b/bookletify.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 + +import os +import sys +from math import ceil +from PyPDF2 import PdfReader, PdfWriter + +def main(): + def print_help(): + print('bookletify') + print() + print('USAGE') + print(' bookletify [OPTIONS] file') + print() + print('DESCRIPTION') + print(' Rearranges the pages of a pdf in order to print it as is (double') + print(' sided, flipped on the short edge) so that you can take it, cut ') + print(' in half and close it like you would do with a book. The result ') + print(' will be the original pdf in the correct order, with the size of ') + print(' half a page') + print(' Especially useful to print pdfs to A5 size on A4 paper') + print() + print('OPTIONS') + print(' -h print help') + print(' -q do not print anything to stdout') + + def parse_argv(): + opts = { + "h": False, + "q": False, + } + filename = None + + if len(sys.argv) < 2: + opts["h"] = True + + for arg in sys.argv[1:]: + if arg.startswith('-'): + for opt in opts: + if opt in arg: + opts[opt] = True + elif not filename: + filename = arg + + return (opts, filename) + + def info(text = '', end='\n'): + if not opts["q"]: + print(text, end=end) + + def prog(curr, max_val): + # Overrides the current terminal line with a progressbar filled at curr/max_val + perc = float(curr) / float(max_val) + remaining = f'{curr:{len(str(max_val))}d}/{max_val}' + (cols, _) = os.get_terminal_size() + max_width = cols - len(remaining) - 3 + + size = min(max_width, max_val, 80) + bar = int(perc * size) + + end = '\n' if curr == max_val else '' + info("\r|" + ("\u2588" * bar) + "_" * (size - bar) + "| " + remaining, end) + + + (opts, input_name) = parse_argv() + if opts["h"] or not input_name: + print_help() + exit(0) + + if not os.path.isfile(input_name): + print(f'file {input_name} does not exist') + exit(1) + + output_name = f'{input_name}-rearranged' + if (input_name.endswith('.pdf')): + output_name = f'{input_name[0:-4]}-rearranged.pdf' + + + # Read the input + reader = PdfReader(input_name) + + # Write the result to a file + middle = PdfWriter() + info("Loading...") + n = len(reader.pages) + # Set m as the smallest multiple of 4 bigger or equal to n + m = ceil(n / 4) * 4 + + for i in range(n): + prog(i, m) + middle.add_page(reader.pages[i]) + + for i in range(m - n): + prog(n + i, m) + middle.add_blank_page() + + prog(m, m) + + output = PdfWriter() + info() + info("Rearranging...") + for i in range(int(m / 4)): + mod = i * 2 + prog(i * 4, m) + output.add_page(middle.pages[m - 1 - mod]) + prog(i * 4 + 1, m) + output.add_page(middle.pages[mod]) + prog(i * 4 + 2, m) + output.add_page(middle.pages[1 + mod]) + prog(i * 4 + 3, m) + output.add_page(middle.pages[m - 2 - mod]) + prog(m, m) + + info() + info("Saving...") + output.write(output_name) + info("Done!") + info() + +if __name__ == "__main__": + main() From ae15a5443b5999edf4a4f1ef52855d6eec3e89eb Mon Sep 17 00:00:00 2001 From: Francesco Minnocci Date: Fri, 19 May 2023 17:39:44 +0000 Subject: [PATCH 2/8] Update 'README.md' aggiunte le dipendenze di `impagina` --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8ce143d..8e79297 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,13 @@ Questa repository contiene i seguenti script: - `impagina` — [@BachoSeven](https://git.phc.dm.unipi.it/BachoSeven) - Consente di impaginare un pdf in modo da poi poterlo stampare "a libretto" + Impagina un pdf in modo da poi poterlo stampare "a libretto", usando l'opzione fronte-retro (lato corto), per poi tagliare e sovrapporre una metà sull'altra. + Dipendenze: `pdftk`, `pdfjam` (parte di TeXlive), `groff` (non solo `groff-base`) - `bookletify` — [@Fran314](https://git.phc.dm.unipi.it/Fran314) - Simile a impagina, ma in python. Formatta un pdf in modo da poi poterlo stampare "a libretto" chiudendolo come un libro invece di sovrapporre una metà sull'altra. - Necessita di PyPDF2 installato con pip per funzionare + Simile a `impagina`, ma in python. Formatta un pdf in modo da poi poterlo stampare "a libretto" tagliando chiudendolo come un libro. + Necessita di PyPDF2 installato con `pip` per funzionare - `gobbino` — [@BachoSeven](https://git.phc.dm.unipi.it/BachoSeven) + [@Dilillo](http://poisson.phc.dm.unipi.it/~dilillo/Vario/index.html) From 789c9308d42dde478f96a23fa35ca46e37972ee5 Mon Sep 17 00:00:00 2001 From: Francesco Minnocci Date: Fri, 19 May 2023 17:40:05 +0000 Subject: [PATCH 3/8] Update 'README.md' aggiunte le dipendenze di `impagina` --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8e79297..7b32c48 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,13 @@ Questa repository contiene i seguenti script: - `impagina` — [@BachoSeven](https://git.phc.dm.unipi.it/BachoSeven) Impagina un pdf in modo da poi poterlo stampare "a libretto", usando l'opzione fronte-retro (lato corto), per poi tagliare e sovrapporre una metà sull'altra. + Dipendenze: `pdftk`, `pdfjam` (parte di TeXlive), `groff` (non solo `groff-base`) - `bookletify` — [@Fran314](https://git.phc.dm.unipi.it/Fran314) Simile a `impagina`, ma in python. Formatta un pdf in modo da poi poterlo stampare "a libretto" tagliando chiudendolo come un libro. + Necessita di PyPDF2 installato con `pip` per funzionare - `gobbino` — [@BachoSeven](https://git.phc.dm.unipi.it/BachoSeven) + [@Dilillo](http://poisson.phc.dm.unipi.it/~dilillo/Vario/index.html) From 76ceb6dfb82bd9841659a17a5d514ac994461ecf Mon Sep 17 00:00:00 2001 From: Francesco Baldino Date: Wed, 24 May 2023 02:00:50 +0200 Subject: [PATCH 4/8] updated bookletify to automatically merge 2 pages per sheet --- bookletify.py | 181 ++++++++++++++++++++++++-------------------------- 1 file changed, 86 insertions(+), 95 deletions(-) diff --git a/bookletify.py b/bookletify.py index 4739346..9072585 100755 --- a/bookletify.py +++ b/bookletify.py @@ -1,72 +1,50 @@ #!/usr/bin/env python3 import os -import sys -from math import ceil -from PyPDF2 import PdfReader, PdfWriter +import argparse +from PyPDF2 import PageObject, PdfReader, PdfWriter, PaperSize, Transformation def main(): - def print_help(): - print('bookletify') - print() - print('USAGE') - print(' bookletify [OPTIONS] file') - print() - print('DESCRIPTION') - print(' Rearranges the pages of a pdf in order to print it as is (double') - print(' sided, flipped on the short edge) so that you can take it, cut ') - print(' in half and close it like you would do with a book. The result ') - print(' will be the original pdf in the correct order, with the size of ') - print(' half a page') - print(' Especially useful to print pdfs to A5 size on A4 paper') - print() - print('OPTIONS') - print(' -h print help') - print(' -q do not print anything to stdout') - - def parse_argv(): - opts = { - "h": False, - "q": False, - } - filename = None - - if len(sys.argv) < 2: - opts["h"] = True - - for arg in sys.argv[1:]: - if arg.startswith('-'): - for opt in opts: - if opt in arg: - opts[opt] = True - elif not filename: - filename = arg - - return (opts, filename) - - def info(text = '', end='\n'): - if not opts["q"]: - print(text, end=end) - - def prog(curr, max_val): - # Overrides the current terminal line with a progressbar filled at curr/max_val - perc = float(curr) / float(max_val) - remaining = f'{curr:{len(str(max_val))}d}/{max_val}' - (cols, _) = os.get_terminal_size() - max_width = cols - len(remaining) - 3 - - size = min(max_width, max_val, 80) - bar = int(perc * size) - - end = '\n' if curr == max_val else '' - info("\r|" + ("\u2588" * bar) + "_" * (size - bar) + "| " + remaining, end) - - - (opts, input_name) = parse_argv() - if opts["h"] or not input_name: - print_help() - exit(0) + PROGRAM_NAME="bookletify" + DESCRIPTION = """Rearranges the pages of a pdf in order to print it as is, + so that you can take it, cut it in half and close it like you would + with a book. The result will be the original pdf in the correct order, + with the size of half a page. Especially useful to print pdfs to A5 + size on A4 paper""" + + parser = argparse.ArgumentParser( + prog=PROGRAM_NAME, + description=DESCRIPTION + ) + + parser.add_argument('filename') + parser.add_argument('-q', '--quiet', + action='store_true', + help='suppress stdout') + parser.add_argument('-s', '--size', + action='store', + choices=['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'C4'], + default='A4', + metavar='SIZE', + help="""set final paper size. Possible values: 'A0', + ..., 'A8' or 'C4'. Default value is 'A4'""") + + parser.add_argument('-b', '--binding-margin', + default=10, + type=float, + metavar='MARGIN', + help="""internal margin for the binding, expressed in + millimeters. Default value is 10""") + + args = parser.parse_args() + + info = lambda text='', end='\n': print(text, end=end) + if args.quiet: + info = lambda text='', end='\n': None + prog = lambda curr, max: info(f"\r{curr} / {max}", '\n' if curr == max else '') + + input_name = args.filename if not os.path.isfile(input_name): print(f'file {input_name} does not exist') exit(1) @@ -75,47 +53,60 @@ def main(): if (input_name.endswith('.pdf')): output_name = f'{input_name[0:-4]}-rearranged.pdf' + + fullwidth = getattr(PaperSize, args.size).width + fullheight = getattr(PaperSize, args.size).height + smallwidth = fullheight / 2 + smallheight = fullwidth + # Convert mm to pixels at 72 dpi + bindingwidth = args.binding_margin * 72 / float(25.4) + smallblank = PageObject.create_blank_page(width=smallwidth - bindingwidth, height=smallheight) # Read the input reader = PdfReader(input_name) - - # Write the result to a file - middle = PdfWriter() - info("Loading...") n = len(reader.pages) - # Set m as the smallest multiple of 4 bigger or equal to n - m = ceil(n / 4) * 4 + pages = [] + info("Reading...") for i in range(n): - prog(i, m) - middle.add_page(reader.pages[i]) - - for i in range(m - n): - prog(n + i, m) - middle.add_blank_page() - - prog(m, m) + prog(i, n) + pages.append(reader.pages[i]) + prog(n,n) + + while(len(pages) % 4 != 0): + pages.append(smallblank) + output = PdfWriter() - info() - info("Rearranging...") - for i in range(int(m / 4)): - mod = i * 2 - prog(i * 4, m) - output.add_page(middle.pages[m - 1 - mod]) - prog(i * 4 + 1, m) - output.add_page(middle.pages[mod]) - prog(i * 4 + 2, m) - output.add_page(middle.pages[1 + mod]) - prog(i * 4 + 3, m) - output.add_page(middle.pages[m - 2 - mod]) - prog(m, m) - - info() - info("Saving...") + info("\nRearranging...") + + def merge_srt_page(base, over, angle, tx, ty): + sx = float(smallwidth - bindingwidth) / float(over.mediabox.width) + sy = float(smallheight) / float(over.mediabox.height) + t = Transformation().scale(sx, sy).rotate(angle). translate(tx, ty) + over.add_transformation(t) + base.merge_page(over) + + m = len(pages) + for i in range(int(m / 2)): + prog(i, int(m / 2)) + new_page = PageObject.create_blank_page(width=fullwidth, height=fullheight) + if i % 2 == 0: + merge_srt_page(new_page, pages[m - 1 - i], -90, 0, fullheight) + merge_srt_page(new_page, pages[i], - 90, 0, smallwidth - bindingwidth) + pass + else: + merge_srt_page(new_page, pages[m - 1 - i], 90, smallheight, smallwidth + bindingwidth) + merge_srt_page(new_page, pages[i], 90, smallheight, 0) + + output.add_page(new_page) + prog(int(m/2), int(m/2)) + + info("\nSaving...") output.write(output_name) - info("Done!") - info() + info("\nDone!") if __name__ == "__main__": main() + + From 9f784976762a1a1d240ff67cd6426934ffd5d189 Mon Sep 17 00:00:00 2001 From: Francesco Baldino Date: Wed, 24 May 2023 11:31:56 +0200 Subject: [PATCH 5/8] bookletify now supports trimming borders --- bookletify.py | 78 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/bookletify.py b/bookletify.py index 9072585..6953485 100755 --- a/bookletify.py +++ b/bookletify.py @@ -12,11 +12,7 @@ def main(): with the size of half a page. Especially useful to print pdfs to A5 size on A4 paper""" - parser = argparse.ArgumentParser( - prog=PROGRAM_NAME, - description=DESCRIPTION - ) - + parser = argparse.ArgumentParser(prog=PROGRAM_NAME, description=DESCRIPTION) parser.add_argument('filename') parser.add_argument('-q', '--quiet', action='store_true', @@ -28,13 +24,33 @@ def main(): metavar='SIZE', help="""set final paper size. Possible values: 'A0', ..., 'A8' or 'C4'. Default value is 'A4'""") - parser.add_argument('-b', '--binding-margin', default=10, type=float, metavar='MARGIN', help="""internal margin for the binding, expressed in - millimeters. Default value is 10""") + millimeters relative to the final paper size (ie: + half of the height of the paper size specified by + --size). Set to 0 to disable. This setting is + independent to the trim setting, ie: increasing or + decreasing this margin does not trim any content on + the final pdf, the content gets scaled down (or up) + to fit to the final width minus the binding margin. + Default value is 10""") + parser.add_argument('-t', '--trim', + default=[0,0,0,0], + type=float, + nargs=4, + metavar='T', + help="""margins to trim, expressed in millimeters + relative to the original page size, as: top right + bottom left. This setting is independent to the + binding margin, ie: first the trim is applied, then + the trimmed content gets scaled up (or down) to the + full height and width, minus the binding margin. + Changing the trim does not increase or decrease the + final binding margin. A negative trim adds an empty + border on that side. Default value is 0 0 0 0""") args = parser.parse_args() @@ -59,8 +75,13 @@ def main(): smallwidth = fullheight / 2 smallheight = fullwidth # Convert mm to pixels at 72 dpi - bindingwidth = args.binding_margin * 72 / float(25.4) + bindingwidth = args.binding_margin * 72.0 / 25.4 smallblank = PageObject.create_blank_page(width=smallwidth - bindingwidth, height=smallheight) + + tt = args.trim[0] * 72.0 / 25.4 + tr = args.trim[1] * 72.0 / 25.4 + tb = args.trim[2] * 72.0 / 25.4 + tl = args.trim[3] * 72.0 / 25.4 # Read the input reader = PdfReader(input_name) @@ -80,24 +101,43 @@ def main(): output = PdfWriter() info("\nRearranging...") - def merge_srt_page(base, over, angle, tx, ty): - sx = float(smallwidth - bindingwidth) / float(over.mediabox.width) - sy = float(smallheight) / float(over.mediabox.height) - t = Transformation().scale(sx, sy).rotate(angle). translate(tx, ty) - over.add_transformation(t) - base.merge_page(over) + def get_scaling(page): + sx = float(smallwidth - bindingwidth) / (float(page.mediabox.width) - tr - tl) + sy = float(smallheight) / (float(page.mediabox.height) - tt - tb) + return (sx, sy) m = len(pages) for i in range(int(m / 2)): prog(i, int(m / 2)) new_page = PageObject.create_blank_page(width=fullwidth, height=fullheight) if i % 2 == 0: - merge_srt_page(new_page, pages[m - 1 - i], -90, 0, fullheight) - merge_srt_page(new_page, pages[i], - 90, 0, smallwidth - bindingwidth) - pass + (sx, sy) = get_scaling(pages[m-1-i]) + t = Transformation().scale(sx, sy).rotate(-90).translate(-tb * sy, fullheight + tl * sx) + pages[m-1-i].add_transformation(t) + pages[m-1-i].cropbox.upper_right = (smallheight, fullheight) + pages[m-1-i].cropbox.lower_left = (0, smallwidth + bindingwidth) + new_page.merge_page(pages[m-1-i]) + + (sx, sy) = get_scaling(pages[i]) + t = Transformation().scale(sx, sy).rotate(-90).translate(-tb * sy, smallwidth - bindingwidth + tl * sx) + pages[i].add_transformation(t) + pages[i].cropbox.upper_right = (smallheight, smallwidth - bindingwidth) + pages[i].cropbox.lower_left = (0, 0) + new_page.merge_page(pages[i]) else: - merge_srt_page(new_page, pages[m - 1 - i], 90, smallheight, smallwidth + bindingwidth) - merge_srt_page(new_page, pages[i], 90, smallheight, 0) + (sx, sy) = get_scaling(pages[m-1-i]) + t = Transformation().scale(sx, sy).rotate(90).translate(smallheight + tb * sy, smallwidth + bindingwidth - tl * sx) + pages[m-1-i].add_transformation(t) + pages[m-1-i].cropbox.upper_right = (smallheight, fullheight) + pages[m-1-i].cropbox.lower_left = (0, smallwidth + bindingwidth) + new_page.merge_page(pages[m-1-i]) + + (sx, sy) = get_scaling(pages[i]) + t = Transformation().scale(sx, sy).rotate(90).translate(smallheight + tb * sy, 0 - tl * sx) + pages[i].add_transformation(t) + pages[i].cropbox.upper_right = (smallheight, smallwidth - bindingwidth) + pages[i].cropbox.lower_left = (0, 0) + new_page.merge_page(pages[i]) output.add_page(new_page) prog(int(m/2), int(m/2)) From b54b8c78fc0355c384cf0ff31a72416fc8451943 Mon Sep 17 00:00:00 2001 From: Francesco Baldino Date: Wed, 24 May 2023 11:36:36 +0200 Subject: [PATCH 6/8] Update 'README.md' --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b32c48..238f76f 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,13 @@ Questa repository contiene i seguenti script: - `bookletify` — [@Fran314](https://git.phc.dm.unipi.it/Fran314) Simile a `impagina`, ma in python. Formatta un pdf in modo da poi poterlo stampare "a libretto" tagliando chiudendolo come un libro. + + Supporta: + - trim + - diversi tipi di paper size (A4 di default, per poter mandare in stampa senza dover mettere "fit-to-page") + - aggiunta di un bordo interno (a sinistra per le pagine dispari, a destra per le pagine pari) per la rilegatura - Necessita di PyPDF2 installato con `pip` per funzionare + Dipendenze: `PyPDF2` - `gobbino` — [@BachoSeven](https://git.phc.dm.unipi.it/BachoSeven) + [@Dilillo](http://poisson.phc.dm.unipi.it/~dilillo/Vario/index.html) From 0222758546af9adc0f37c18729405a38ba96b9d4 Mon Sep 17 00:00:00 2001 From: Fran314 Date: Wed, 24 May 2023 09:38:34 +0000 Subject: [PATCH 7/8] Update 'README.md' --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 238f76f..9e9c9c5 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ Questa repository contiene i seguenti script: Simile a `impagina`, ma in python. Formatta un pdf in modo da poi poterlo stampare "a libretto" tagliando chiudendolo come un libro. Supporta: - - trim - - diversi tipi di paper size (A4 di default, per poter mandare in stampa senza dover mettere "fit-to-page") - - aggiunta di un bordo interno (a sinistra per le pagine dispari, a destra per le pagine pari) per la rilegatura + - trim + - diversi tipi di paper size (A4 di default, per poter mandare in stampa senza dover mettere "fit-to-page") + - aggiunta di un bordo interno (a sinistra per le pagine dispari, a destra per le pagine pari) per la rilegatura Dipendenze: `PyPDF2` From 3885127c419509b406bf1d4cd0b4498d967fa9e9 Mon Sep 17 00:00:00 2001 From: Francesco Baldino Date: Wed, 24 May 2023 14:25:00 +0200 Subject: [PATCH 8/8] bookletify now supports piping --- README.md | 1 + bookletify.py | 60 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 9e9c9c5..c2d5a34 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Questa repository contiene i seguenti script: - trim - diversi tipi di paper size (A4 di default, per poter mandare in stampa senza dover mettere "fit-to-page") - aggiunta di un bordo interno (a sinistra per le pagine dispari, a destra per le pagine pari) per la rilegatura + - pipe da stdin / a stdout Dipendenze: `PyPDF2` diff --git a/bookletify.py b/bookletify.py index 6953485..d063621 100755 --- a/bookletify.py +++ b/bookletify.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import os +import sys +import io import argparse from PyPDF2 import PageObject, PdfReader, PdfWriter, PaperSize, Transformation @@ -13,19 +15,28 @@ def main(): size on A4 paper""" parser = argparse.ArgumentParser(prog=PROGRAM_NAME, description=DESCRIPTION) - parser.add_argument('filename') + parser.add_argument('input', + help="""name of the input file to bookletify. Use '-' + to read file from stdin""") + parser.add_argument('output', + help="""name of the output file to write to. Use '-' to + write to stdout""") parser.add_argument('-q', '--quiet', action='store_true', - help='suppress stdout') + help="""suppress stdout. Not suppressed if the flag + this flag is absent. Automatically suppressed if + output is '-' (see output), to avoid broken + pdfs""") parser.add_argument('-s', '--size', action='store', - choices=['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'C4'], + choices=['A0', 'A1', 'A2', 'A3', 'A4', 'A5', + 'A6', 'A7', 'A8', 'C4'], default='A4', metavar='SIZE', help="""set final paper size. Possible values: 'A0', ..., 'A8' or 'C4'. Default value is 'A4'""") parser.add_argument('-b', '--binding-margin', - default=10, + default=8.0, type=float, metavar='MARGIN', help="""internal margin for the binding, expressed in @@ -36,7 +47,7 @@ def main(): decreasing this margin does not trim any content on the final pdf, the content gets scaled down (or up) to fit to the final width minus the binding margin. - Default value is 10""") + Default value is 8""") parser.add_argument('-t', '--trim', default=[0,0,0,0], type=float, @@ -54,21 +65,25 @@ def main(): args = parser.parse_args() + if args.output == '-': + # If output is written to stdout, suppress other stdout output such as + # current state of the program and progress bars + args.quiet = True + info = lambda text='', end='\n': print(text, end=end) if args.quiet: info = lambda text='', end='\n': None prog = lambda curr, max: info(f"\r{curr} / {max}", '\n' if curr == max else '') - input_name = args.filename - if not os.path.isfile(input_name): - print(f'file {input_name} does not exist') - exit(1) - - output_name = f'{input_name}-rearranged' - if (input_name.endswith('.pdf')): - output_name = f'{input_name[0:-4]}-rearranged.pdf' - + reader = None + if args.input == '-': + reader = PdfReader(sys.stdin.buffer) + else: + if not os.path.isfile(args.input): + print(f'file {args.input} does not exist') + exit(1) + reader = PdfReader(args.input) fullwidth = getattr(PaperSize, args.size).width fullheight = getattr(PaperSize, args.size).height @@ -76,7 +91,10 @@ def main(): smallheight = fullwidth # Convert mm to pixels at 72 dpi bindingwidth = args.binding_margin * 72.0 / 25.4 - smallblank = PageObject.create_blank_page(width=smallwidth - bindingwidth, height=smallheight) + smallblank = PageObject.create_blank_page( + width=smallwidth - bindingwidth, + height=smallheight + ) tt = args.trim[0] * 72.0 / 25.4 tr = args.trim[1] * 72.0 / 25.4 @@ -84,11 +102,9 @@ def main(): tl = args.trim[3] * 72.0 / 25.4 # Read the input - reader = PdfReader(input_name) + info("Reading...") n = len(reader.pages) pages = [] - - info("Reading...") for i in range(n): prog(i, n) pages.append(reader.pages[i]) @@ -143,7 +159,13 @@ def main(): prog(int(m/2), int(m/2)) info("\nSaving...") - output.write(output_name) + if args.output == '-': + data = io.BytesIO() + output.write(data) + sys.stdout.buffer.write(data.getvalue()) + else: + output.write(args.output) + info("\nDone!") if __name__ == "__main__":