99from PyQt6 .QtCore import Qt
1010from PyQt6 .QtGui import QFont
1111from PyPDF2 import PdfReader , PdfWriter
12+ from pdf2image import convert_from_path
1213
1314
1415class Mode :
@@ -130,6 +131,61 @@ def split_pdf(input_path, chunk_size, output_path):
130131 return message
131132
132133
134+ def convert_to_images (input_path , page_numbers , output_path ):
135+ """Convert specified PDF pages to images."""
136+ reader = PdfReader (input_path )
137+ total_pages = len (reader .pages )
138+
139+ valid_pages = []
140+ invalid_pages = []
141+
142+ # Validate page numbers
143+ for page_num in page_numbers :
144+ if 1 <= page_num <= total_pages :
145+ valid_pages .append (page_num )
146+ else :
147+ invalid_pages .append (page_num )
148+
149+ if not valid_pages :
150+ raise ValueError ("No valid pages to convert to images." )
151+
152+ # Determine output naming
153+ output_file = Path (output_path )
154+ base_name = output_file .stem
155+ output_dir = output_file .parent
156+
157+ # Ensure output directory exists
158+ output_dir .mkdir (parents = True , exist_ok = True )
159+
160+ created_files = []
161+
162+ # Convert pages to images
163+ # pdf2image uses 1-based indexing, matching our page_numbers
164+ images = convert_from_path (input_path , first_page = min (valid_pages ),
165+ last_page = max (valid_pages ))
166+
167+ for page_num in valid_pages :
168+ # Get the corresponding image from the converted range
169+ image_index = page_num - min (valid_pages )
170+ if image_index < len (images ):
171+ image = images [image_index ]
172+
173+ # Generate output filename
174+ output_filename = output_dir / f"{ base_name } _page{ page_num } .png"
175+ image .save (str (output_filename ), "PNG" )
176+ created_files .append (str (output_filename ))
177+
178+ num_images = len (created_files )
179+ message = f"Successfully converted { num_images } page{ 's' if num_images > 1 else '' } to image{ 's' if num_images > 1 else '' } "
180+
181+ if invalid_pages :
182+ message += f"\n \n Skipped invalid pages: { invalid_pages } (PDF has { total_pages } pages)"
183+
184+ message += f"\n \n Created { num_images } PNG image{ 's' if num_images > 1 else '' } in:\n { output_dir } "
185+
186+ return message
187+
188+
133189class PDFPageSelectorApp (QMainWindow ):
134190 def __init__ (self ):
135191 super ().__init__ ()
@@ -155,6 +211,15 @@ def __init__(self):
155211 help_text = "Number of pages per file (greater than 0)" ,
156212 process_func = self ._process_split ,
157213 output_suffix = "_split"
214+ ),
215+ Mode (
216+ name = "image" ,
217+ display_name = "Image" ,
218+ section_title = "Page Ranges" ,
219+ placeholder = "e.g., 1-3,5,6-9,11" ,
220+ help_text = "Examples: 1-3,5,6-9,11 or 1,3,5 or 10-20" ,
221+ process_func = self ._process_image ,
222+ output_suffix = "_images"
158223 )
159224 ]
160225
@@ -196,7 +261,7 @@ def init_ui(self):
196261 layout .addWidget (self ._create_output_section ())
197262
198263 # Process button
199- self .process_button = QPushButton ("Create Trimmed PDF " )
264+ self .process_button = QPushButton ("Execute " )
200265 self .process_button .setMinimumHeight (40 )
201266 self .process_button .setFont (QFont ("" , 11 , QFont .Weight .Bold ))
202267 self .process_button .clicked .connect (self .process_pdf )
@@ -421,6 +486,35 @@ def _process_split(self, chunk_input):
421486 message = split_pdf (self .input_path , chunk_size , self .output_path )
422487 self ._show_success (message )
423488
489+ def _process_image (self , page_input ):
490+ """Process PDF in image mode."""
491+ self ._ensure_output_path ()
492+ try :
493+ page_numbers = parse_page_ranges (page_input )
494+ except (ValueError , AttributeError ) as e :
495+ raise ValueError (f"Invalid page format:\n { str (e )} " )
496+
497+ # Check if any output files would be overwritten
498+ if self .output_path :
499+ output_file = Path (self .output_path )
500+ base_name = output_file .stem
501+ output_dir = output_file .parent
502+
503+ # Check if any of the image files exist
504+ files_exist = False
505+ for page_num in page_numbers :
506+ image_file = output_dir / f"{ base_name } _page{ page_num } .png"
507+ if image_file .exists ():
508+ files_exist = True
509+ break
510+
511+ if files_exist :
512+ if not self ._confirm_overwrite ():
513+ return
514+
515+ message = convert_to_images (self .input_path , page_numbers , self .output_path )
516+ self ._show_success (message )
517+
424518 def _confirm_overwrite (self ):
425519 """Ask user to confirm file overwrite."""
426520 reply = QMessageBox .question (
0 commit comments