Advertisement
Guest User

PDF imposer 4123

a guest
Dec 19th, 2024
1,291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.74 KB | Source Code | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, filedialog, messagebox
  3. from PyPDF2 import PdfReader, PdfWriter
  4. import os
  5. import traceback
  6. import sys
  7.  
  8. class PDFImposerApp:
  9.     PAGES_PER_SHEET = 4  # Constant for pages per sheet
  10.  
  11.     def __init__(self, root):
  12.         self.root = root
  13.         self.root.title("PDF Imposer")
  14.         self.root.geometry("600x450")  # Adjusted height for LabelFrames
  15.  
  16.         main_frame = ttk.Frame(root, padding="10")  # Reduced padding
  17.         main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
  18.         root.columnconfigure(0, weight=1)
  19.         root.rowconfigure(0, weight=1)
  20.  
  21.         # Input File Section
  22.         input_frame = ttk.LabelFrame(main_frame, text="Input PDF", padding=10)
  23.         input_frame.grid(row=0, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5, padx=5)
  24.         input_frame.columnconfigure(1, weight=1)
  25.  
  26.         ttk.Label(input_frame, text="Input PDF:").grid(row=0, column=0, sticky=tk.W, pady=5, padx=5)
  27.         self.input_path = tk.StringVar()
  28.         ttk.Entry(input_frame, textvariable=self.input_path, width=50).grid(row=0, column=1, padx=5, sticky=(tk.W, tk.E))
  29.         ttk.Button(input_frame, text="Browse", command=self.browse_input).grid(row=0, column=2, padx=5)
  30.  
  31.         # Output File Section
  32.         output_frame = ttk.LabelFrame(main_frame, text="Output PDF", padding=10)
  33.         output_frame.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5, padx=5)
  34.         output_frame.columnconfigure(1, weight=1)
  35.  
  36.         ttk.Label(output_frame, text="Output PDF:").grid(row=0, column=0, sticky=tk.W, pady=5, padx=5)
  37.         self.output_path = tk.StringVar()
  38.         ttk.Entry(output_frame, textvariable=self.output_path, width=50).grid(row=0, column=1, padx=5, sticky=(tk.W, tk.E))
  39.         ttk.Button(output_frame, text="Browse", command=self.browse_output).grid(row=0, column=2, padx=5)
  40.  
  41.         # Blank Pages Control
  42.         blank_frame = ttk.LabelFrame(main_frame, text="Blank Pages", padding=10)
  43.         blank_frame.grid(row=2, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10, padx=5)
  44.         blank_frame.columnconfigure(1, weight=1)
  45.  
  46.         ttk.Label(blank_frame, text="Additional Blank Pages:").grid(row=0, column=0, sticky=tk.W, pady=5, padx=5)
  47.         self.blank_pages = tk.IntVar(value=0)
  48.         blank_controls_frame = ttk.Frame(blank_frame)
  49.         blank_controls_frame.grid(row=0, column=1, sticky=tk.E, padx=5)
  50.  
  51.         ttk.Button(blank_controls_frame, text="-", width=3, command=self.decrease_blank).pack(side=tk.LEFT, padx=2)
  52.         ttk.Label(blank_controls_frame, textvariable=self.blank_pages, width=5, anchor="center").pack(side=tk.LEFT, padx=2)
  53.         ttk.Button(blank_controls_frame, text="+", width=3, command=self.increase_blank).pack(side=tk.LEFT, padx=2)
  54.  
  55.         # Impose button
  56.         ttk.Button(main_frame, text="Rearrange that SHEET!", command=self.impose_pdf).grid(row=3, column=0, columnspan=3, pady=15)
  57.  
  58.         # Status message
  59.         self.status_var = tk.StringVar()
  60.         ttk.Label(main_frame, textvariable=self.status_var, wraplength=580).grid(row=4, column=0, columnspan=3, sticky=(tk.W, tk.E), padx=5)
  61.  
  62.     def browse_input(self):
  63.         filename = filedialog.askopenfilename(filetypes=[("PDF files", "*.pdf")])
  64.         if filename:
  65.             self.input_path.set(filename)
  66.             output_dir = os.path.dirname(filename)
  67.             input_name = os.path.splitext(os.path.basename(filename))[0]  # Get name without extension
  68.             output_name = f"imposed_{input_name}.pdf"
  69.             self.output_path.set(os.path.join(output_dir, output_name))
  70.  
  71.     def browse_output(self):
  72.         filename = filedialog.asksaveasfilename(
  73.             defaultextension=".pdf",
  74.             filetypes=[("PDF files", "*.pdf")]
  75.         )
  76.         if filename:
  77.             self.output_path.set(filename)
  78.  
  79.     def decrease_blank(self):
  80.         if self.blank_pages.get() > 0:
  81.             self.blank_pages.set(self.blank_pages.get() - 1)
  82.  
  83.     def increase_blank(self):
  84.         self.blank_pages.set(self.blank_pages.get() + 1)
  85.  
  86.     def create_blank_page(self, template_page):
  87.         """Creates a blank page with the same size as the template page."""
  88.         try:
  89.             media_box = template_page.mediabox
  90.             writer = PdfWriter()
  91.             writer.add_blank_page(width=float(media_box.width), height=float(media_box.height))
  92.             return writer.pages[0]
  93.         except Exception as e:
  94.             raise Exception(f"Error creating blank page: {str(e)}")
  95.  
  96.     def impose_pdf(self):
  97.         try:
  98.             input_path = self.input_path.get()
  99.             output_path = self.output_path.get()
  100.  
  101.             if not input_path or not output_path:
  102.                 messagebox.showerror("Error", "Please select both input and output files.")
  103.                 return
  104.  
  105.             if not os.path.exists(input_path):
  106.                 messagebox.showerror("Error", "Input file not found.")
  107.                 return
  108.  
  109.             self.status_var.set("Processing PDF...")
  110.             self.root.update()
  111.  
  112.             pdf_reader = PdfReader(input_path)
  113.             pdf_writer = PdfWriter()
  114.  
  115.             num_pages = len(pdf_reader.pages)
  116.             if not pdf_reader.pages:
  117.                 messagebox.showerror("Error", "Input PDF has no pages.")
  118.                 return
  119.  
  120.             template_page = pdf_reader.pages[0]
  121.  
  122.             # Calculate required blank pages directly
  123.             blanks_needed = (self.PAGES_PER_SHEET - (num_pages % self.PAGES_PER_SHEET)) % self.PAGES_PER_SHEET
  124.             total_pages = num_pages + blanks_needed
  125.  
  126.             all_pages = list(pdf_reader.pages)  # Create a copy
  127.             for _ in range(blanks_needed):
  128.                 all_pages.append(self.create_blank_page(template_page))
  129.  
  130.             for i in range(0, total_pages, self.PAGES_PER_SHEET):
  131.                 page_indices = [i + 3, i, i + 1, i + 2]
  132.                 for idx in page_indices:
  133.                     if idx < total_pages:
  134.                         pdf_writer.add_page(all_pages[idx])
  135.  
  136.             with open(output_path, "wb") as output_file:
  137.                 pdf_writer.write(output_file)
  138.  
  139.             self.status_var.set(f"Success! Imposed PDF saved to: {output_path}")
  140.             messagebox.showinfo("Success", "PDF imposition completed successfully!")
  141.  
  142.         except FileNotFoundError:
  143.             self.status_var.set("Error: Input file not found.")
  144.             messagebox.showerror("Error", "Input file not found.")
  145.         except Exception as e:
  146.             error_msg = f"Error: {str(e)}\n\nFull traceback:\n{traceback.format_exc()}"
  147.             self.status_var.set(error_msg)
  148.             messagebox.showerror("Error", error_msg)
  149.  
  150. if __name__ == "__main__":
  151.     root = tk.Tk()
  152.     app = PDFImposerApp(root)
  153.     root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement