44import os
55from PyPDF2 import PdfFileReader , PdfFileWriter
66
7+ ## Helper Functions
78
9+ ### Get PDF details in the window
810def extract_information (pdf_path ):
911 new_window = tk .Toplevel (root )
1012 new_window .title (pdf_path )
@@ -27,57 +29,80 @@ def extract_information(pdf_path):
2729 new_label = tk .Label (new_window , text = txt )
2830 new_label .place (x = 10 , y = 10 )
2931
30-
32+ # Read a pdf then create a new pdf with each page rotated
3133def rotate_pages (pdf_path ):
34+
35+ # Output file object
3236 pdf_writer = PdfFileWriter ()
3337 pdf_reader = PdfFileReader (pdf_path )
38+
39+ # Copy each page to the output file object
3440 for i in range (pdf_reader .getNumPages ()):
3541 pdf_writer .addPage (pdf_reader .getPage (i ).rotateClockwise (90 ))
3642
43+ # Export the object in a pdf file
3744 with open ("./rotate_pages.pdf" , "wb" ) as fh :
3845 pdf_writer .write (fh )
3946
40-
47+ # Read two pdfs and merge them into one
4148def merge_pdfs (pdfA , pdfB ):
49+
50+ # Reading file objects of both pdfs
4251 pdfA_obj = PdfFileReader (pdfA , strict = False )
4352 pdfB_obj = PdfFileReader (pdfB , strict = False )
53+
54+ # Object to store merged pdf
4455 pdf_merge = PdfFileWriter ()
4556
57+ # Get all the pages from pdfA to writer object
4658 for pgNum in range (pdfA_obj .numPages ):
4759 pg = pdfA_obj .getPage (pgNum )
4860 pdf_merge .addPage (pg )
4961
62+ # Get all the pages from pdfB to writer object
5063 for pgNum in range (pdfB_obj .numPages ):
5164 pg = pdfB_obj .getPage (pgNum )
5265 pdf_merge .addPage (pg )
5366
5467 # Write out the merged PDF
55-
5668 fileObj = open (".\merged_pdf.pdf" , "wb" )
5769 pdf_merge .write (fileObj )
70+
71+ #Display confirmation message
5872 info_label .configure (text = f"File Saved at : { os .getcwd ()} \merged_pdf.pdf" )
5973
6074
75+ # Split one pdf in two different pdfs
6176def pdf_split (path , ranges ):
77+
78+ # Read original pdf
6279 pdf = PdfFileReader (path , strict = False )
80+
81+ # Writer obeject for pdf
6382 pdf_writer = PdfFileWriter ()
6483
84+ # Get all the pages upto the provided page number
6585 for page in range (int (ranges )):
6686 pdf_writer .addPage (pdf .getPage (page ))
87+
88+ # Export the object to pdf file for the first part of the splitted pdf
6789 with open ("./SplitA.pdf" , "wb" ) as output_pdf :
6890 pdf_writer .write (output_pdf )
6991
92+ # Same steps for the second part of the pdf.
7093 pdf_writer = PdfFileWriter ()
7194 for page in range (int (ranges ), pdf .getNumPages ()):
7295 pdf_writer .addPage (pdf .getPage (page ))
7396 with open ("./SplitB.pdf" , "wb" ) as output_pdf :
7497 pdf_writer .write (output_pdf )
7598
76-
99+ # Overlay water mark on a pdf (watermark should also be a pdf)
77100def create_watermark (input_pdf , watermark ):
101+
102+ # Get watermark page after reading the pdf
78103 watermark_obj = PdfFileReader (watermark , strict = False )
79104 watermark_page = watermark_obj .getPage (0 )
80-
105+
81106 pdf_reader = PdfFileReader (input_pdf , strict = False )
82107 pdf_writer = PdfFileWriter ()
83108
@@ -86,46 +111,59 @@ def create_watermark(input_pdf, watermark):
86111 page = pdf_reader .getPage (page )
87112 page .mergePage (watermark_page )
88113 pdf_writer .addPage (page )
89-
114+
115+ # Export the writer object to a pdf
90116 with open ("./Watermarked.pdf" , "wb" ) as out :
91117 pdf_writer .write (out )
92118 info_label .configure (text = f"Watermark set\n Check : { os .getcwd ()} " )
93119
94-
120+ # Make a pdf password protected
95121def add_encryption (input_pdf , password ):
122+
123+ # Reader and writer objects
96124 pdf_writer = PdfFileWriter ()
97125 pdf_reader = PdfFileReader (input_pdf , strict = False )
98126
127+ # Copy all the pages from the pdf to the writer object
99128 for page in range (pdf_reader .getNumPages ()):
100129 pdf_writer .addPage (pdf_reader .getPage (page ))
101-
130+
131+ # add encryption to a writer object
102132 pdf_writer .encrypt (user_pwd = password , owner_pwd = None , use_128bit = True )
133+
134+ # export the encrypted pdf
103135 f = open ("./Encrypted.pdf" , "wb" )
104136 pdf_writer .write (f )
105137 info_label .configure (text = f"Password Set\n Check : { os .getcwd ()} " )
106138
107139
140+ ## Selection Functions
141+
142+ # Select file and call extract_information()
108143def info ():
109144 path = askopenfilename (title = "Select File" , filetypes = [("PDF Document" , "*pdf" )])
110- extract_information (path )
145+ if path :
146+ extract_information (path )
111147
112148
149+ # Select file and call rotate_pages()
113150def rotate ():
114151 path = askopenfilename (title = "Select File" , filetypes = [("PDF Document" , "*pdf" )])
115- rotate_pages ( path )
116-
152+ if path :
153+ rotate_pages ( path )
117154
155+ # Select two files and call merge_pdfs()
118156def merge ():
119157 path_A = askopenfilename (
120158 title = "Select First File" , filetypes = [("PDF Document" , "*pdf" )]
121159 )
122160 path_B = askopenfilename (
123161 title = "Select Second File" , filetypes = [("PDF Document" , "*pdf" )]
124162 )
163+ if all (path_A , path_B ):
164+ merge_pdfs (path_A , path_B )
125165
126- merge_pdfs (path_A , path_B )
127-
128-
166+ #Select file and get range and then call pdf_split
129167def split ():
130168 path = askopenfilename (title = "Select File" , filetypes = [("PDF Document" , "*pdf" )])
131169
@@ -135,6 +173,8 @@ def assign():
135173 newWindow .destroy ()
136174
137175 if path :
176+ # Small windo basic tkinter setup
177+ # this window is responsible of creating a popup and ask user the required informationn
138178 newWindow = tk .Toplevel (root )
139179 newWindow .title ("Enter Split Ranges" )
140180 newWindow .geometry ("400x200" )
@@ -154,6 +194,7 @@ def assign():
154194 container .grid (row = 2 , column = 0 )
155195
156196
197+ # Select two files and call creat_watermark()
157198def watermark ():
158199 path = askopenfilename (title = "Select File" , filetypes = [("PDF Document" , "*pdf" )])
159200 pathW = askopenfilename (
@@ -172,6 +213,9 @@ def assign():
172213 newWindow .destroy ()
173214
174215 if path :
216+
217+ # Small windo basic tkinter setup
218+ # this window is responsible of creating a popup and ask user the required informationn
175219 newWindow = tk .Toplevel (root )
176220 newWindow .title ("Create Password" )
177221 newWindow .geometry ("400x200" )
@@ -191,32 +235,36 @@ def assign():
191235 container .grid (row = 1 , column = 0 )
192236
193237
238+ # Basic root tkinter setup, geometry, title
194239root = tk .Tk ()
195240root .geometry ("800x600" )
196241root .wm_title ("PDF Utility Tool" )
197242root .resizable (False , False )
198243fontStyle = tkFont .Font (size = 42 )
199244btnText = tkFont .Font (size = 12 )
200245
201-
246+ # Creating two rows and one column in the window
202247root .columnconfigure (0 , minsize = 800 )
203248root .rowconfigure (0 , minsize = 200 )
204249root .rowconfigure (2 , minsize = 400 )
205250
251+ # Title label
206252label1 = tk .Label (
207253 text = "PDF Utility Tool" , font = fontStyle , borderwidth = 2 , relief = "groove"
208254)
209- info_label = tk .Label (text = "" , font = btnText )
210-
211255
256+ # Information label shows the confirmation messages
257+ info_label = tk .Label (text = "" , font = btnText )
212258label1 .grid (row = 0 , column = 0 )
213259info_label .place (x = 200 , y = 150 )
214260
261+ # Container to store all the function buttons
215262container = tk .Frame (root )
216263
217264container .columnconfigure ([0 , 1 ], minsize = 300 )
218265container .rowconfigure ([0 , 1 , 2 ], minsize = 100 )
219266
267+ # Button for evry function and custom command attribute to call the functions
220268btn_merge = tk .Button (
221269 container ,
222270 text = "Merge" ,
@@ -279,6 +327,7 @@ def assign():
279327)
280328
281329
330+ # Placing all the buttons in the grid setup
282331btn_merge .grid (row = 0 , column = 0 )
283332btn_rotate .grid (row = 0 , column = 1 )
284333btn_split .grid (row = 1 , column = 0 )
0 commit comments