#!/home/user/.pypdf/bin/python3 import sys import pypdf from pypdf.generic import create_string_object,Destination,FloatObject,NameObject,RectangleObject,DictionaryObject,TreeObject,ArrayObject from typing import cast fn = sys.argv[1] scale = float(sys.argv[2]) moveleft = float(sys.argv[3]) movedown = float(sys.argv[4]) # ----- transformation M = [scale,0,0,scale,-moveleft,-movedown] def transformpoint(x,y): x,y = x.as_numeric(),y.as_numeric() x,y = M[0]*x+M[2]*y+M[4],M[1]*x+M[3]*y+M[5] x,y = FloatObject(x),FloatObject(y) return x,y def transformrectangle(r): xLL,yLL,xUR,yUR = r xLL,yLL = transformpoint(xLL,yLL) xUR,yUR = transformpoint(xUR,yUR) return xLL,yLL,xUR,yUR # ----- initial copy output = pypdf.PdfWriter(clone_from=fn) # ----- transform page contents for page in output.pages: page.add_transformation(M) page.compress_content_streams() # ----- transform destinations def dest_transform(key,value): if value[1] != '/XYZ': return x,y = value[2:4] x,y = transformpoint(x,y) value[2:4] = x,y def dest_walk(tree): tree = cast(TreeObject,tree) if '/Kids' in tree: for kid in tree['/Kids']: dest_walk(kid.get_object()) elif '/Names' in tree: names = tree['/Names'] i = 0 while i+2 <= len(names): key = cast(str,names[i].get_object()) i += 1 if not isinstance(key,str): continue value = names[i].get_object() if isinstance(value,DictionaryObject) and '/D' in value: value = value['/D'] dest_transform(key,value) else: for key,value in tree.items(): value = value.get_object() if isinstance(value,DictionaryObject): value = value['/D'] dest_transform(key,value) catalog = output._root_object if '/Dests' in catalog: dest_walk(catalog['/Dests']) elif '/Names' in catalog: names = cast(ArrayObject,catalog['/Names']) if '/Dests' in names: dest_walk(names['/Dests']) # ----- transform links scaledannots = set() for page in output.pages: if '/Annots' in page: for a in page['/Annots']: if a.idnum in scaledannots: continue scaledannots.add(a.idnum) r = a.get_object()['/Rect'] a.get_object().update({NameObject('/Rect'):RectangleObject(transformrectangle(r))}) # ----- ship it output.write(sys.stdout.buffer)