#!/usr/bin/env python3 from pypdf import PaperSize, PdfReader, PdfWriter, Transformation from pypdf.generic import RectangleObject import argparse parser = argparse.ArgumentParser( prog='pdf2zine', description='pdf2zine rearranges pages for signature printing ', epilog='onipa') parser.add_argument('pdf_file') # positional argument #parser.add_argument('pages', type=int) # positional argument #parser.add_argument('-s', '--signature') # option that takes a value parser.add_argument('-v', '--verbose', action='store_true') # on/off flag parser.add_argument('-z', '--zine', action='store_true', help='Input pdf needs to be 16 pages') parser.add_argument('-s', '--signature', dest='signature', type=int, action='store', default=0, help='') args = parser.parse_args() signature_size=args.signature if signature_size < 0 : # print("signature size must be greater than 0!") print("signature size must be non-negative integer!") exit(1) reader = PdfReader(args.pdf_file) number_of_pages = len(reader.pages) #page = reader.pages[0] #text = page.extract_text() pages=number_of_pages #print(pages) lst=[] def get_reorder(number_of_pages: int, signature_size: int): panu=number_of_pages sisi=signature_size #p\s| 1 | 2 | 3 | 4 | #----------------------- # 1 | 4 | 8 | 12 | 16 | # 2 | 4 | 8 | 12 | 16 | # 3 | 4 | 8 | 12 | 16 | # 4 | 4 | 8 | 12 | 16 | # 5 | 8 | 8 | 12 | 16 | # 6 | 8 | 8 | 12 | 16 | # 7 | 8 | 8 | 12 | 16 | # 8 | 8 | 8 | 12 | 16 | # 9 | 12 | 16 | 12 | 16 | #10 | 12 | 16 | 12 | 16 | #11 | 12 | 16 | 12 | 16 | #12 | 12 | 16 | 12 | 16 | #13 | 16 | 16 | 24 | 16 | p=number_of_pages s=signature_size if signature_size == 0: signature_size=1 pages_filled= ( int((number_of_pages-1)/(4*signature_size)) +1 )*4*signature_size signature_size=int(pages_filled/4) pages_filled= ( int((number_of_pages-1)/(4*signature_size)) +1 )*4*signature_size signature_count=int( pages_filled/signature_size/4 ) #print(signature_count) for i in range(signature_count): # print("i=",i) down=(i+1)*4*signature_size # print("down=",down) up= (i*4*signature_size)+1 # print("up",up) for count in range(signature_size): # print("count=",count) lst.append(down); down -= 1 lst.append(up); up += 1 lst.append(up); up += 1 lst.append(down); down -= 1 # print(lst) #print(lst) #print(len(lst)) return lst def print_signatures(lst: list,signature_size: int): if signature_size==0: signature_size=1 for i in range( len( lst ) ): if ( (i+1) % (4*signature_size) == 0 ): print(lst[i]) elif ( (i+1) % (4) == 0 ): print(lst[i], end=' ') else: print(lst[i],end='.') # REARRANGING OF PAGES def rearrange_pages(reader, lst): writer = PdfWriter() for page in lst: # print(page) if page > len(reader.pages): writer.add_blank_page(width=reader.pages[0].mediabox.width,height=reader.pages[0].mediabox.height) else: writer.add_page(reader.pages[page-1]) return writer def make_zine(reader, lst): # _____________________ # | 1r | 8r | 7r | 6r | # --------------------- # | 2 | 3 | 4 | 5 | # --------------------- # # _________________________ # | 9r | 16r | 15r | 14r | # ------------------------- # | 10 | 11 | 12 | 13 | # ------------------------- # # todo # - [ ] alternative folding 1 for zine # _____________________ # | 3r | 2r | 1r | 8r | # --------------------- # | 4 | 5 | 6 | 7 | # --------------------- # _________________________ # | 11r | 10r | 9r | 16r | # ------------------------- # | 12 | 13 | 14 | 15 | # ------------------------- # page_order=[ 2, 3, 4, 5, 1, 8, 7, 6, 10,11,12,13, 9,16,15,14 ] print("zine") # Create a destination file, and add a blank page to it writer = PdfWriter() # Copy source page to destination page, several times for i in range(2): destpage = writer.add_blank_page( width=PaperSize.A4.height, height=PaperSize.A4.width ) for y in range(2): for x in range(4): pageposition=8*i+4*y+x sourcepage=reader.pages[page_order[pageposition]-1] mb=sourcepage.mediabox sourcepage.cropbox = RectangleObject(( -2*mb.right, -4*mb.top, 2*mb.right, 2*mb.top )) if y == 1: transformation = Transformation().rotate(180) r="r" sourcepage.add_transformation(transformation) tx_val=(1*x+1) * sourcepage.mediabox.width ty_val=2*y * sourcepage.mediabox.height else: tx_val=x * sourcepage.mediabox.width ty_val=2*y * sourcepage.mediabox.height r=" " if x==3: print(page_order[pageposition],r) else: print(page_order[pageposition],r,end=' ') destpage.merge_transformed_page( sourcepage, Transformation( ).translate( tx=tx_val, ty=ty_val, ).scale( sx=0.5, sy=0.5 ) , expand=True ) # destpage. destpage.mediabox = RectangleObject(( 0, 0, 2*mb.right, 1*mb.top )) #writer.add_page(destpage) # destpage = writer.add_blank_page( # width=PaperSize.A4.height, # height=PaperSize.A4.width # ) return writer lst=get_reorder(number_of_pages, signature_size) if args.zine : if number_of_pages != 16: #TODO: if number of pages%16 != 0 : fill up with blank pages # in loop: # if i > len(pages): insert blank? or terminate orderly print("Error... when using '--zine' the input pdf must have 16 pages!") exit(1) writer=make_zine(reader, lst) # signature_size=zine outfile=args.pdf_file.split(".pdf")[0]+"_zine.pdf" else: print_signatures(lst,signature_size) writer=rearrange_pages(reader,lst) outfile=args.pdf_file.split(".pdf")[0]+"_book_s"+str(signature_size)+".pdf" # SAVE FILE TO DISK with open(outfile, "wb") as fp: writer.write(fp)