File size: 4,226 Bytes
4b7c9ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import cv2
import re
import os
import glob
import sys
from fpdf import FPDF
from pdf2image import convert_from_path
from PIL import Image as PILImage

class Converter:
    def __init__(self):
        self.a4_w_mm = 210
        self.a4_h_mm = 297
        self.dpi = 200.0

    def invert_image(self, i_input, i_output):
        """Inverts a given image."""
        image = cv2.imread(i_input)
        print("Inverting image: {}".format(i_input))
        if image is None:
            print("Error reading image: {}".format(i_input))
            return
        image = ~image
        cv2.imwrite(i_output, image)

    def pdf_to_img_all(self, file_path, o_dir):
        """Converts all PDF pages to JPEG images."""
        if not os.path.exists(o_dir):
            os.makedirs(o_dir)
        pages = convert_from_path(file_path, dpi=self.dpi)
        for i, image in enumerate(pages):
            output_path = os.path.join(o_dir, f"{i+1}.jpeg")
            image.save(output_path, 'JPEG', quality=95)
            print("Saved image: {}".format(output_path))

    def get_scaled_dimensions(self, width_pixels, height_pixels):
        """Calculate scaled dimensions maintaining aspect ratio."""
        width_ratio = width_pixels / height_pixels
        
        if width_ratio > 1:  # Landscape
            w = self.a4_h_mm
            h = self.a4_h_mm / width_ratio
            return 'L', w, h
        else:  # Portrait
            h = self.a4_h_mm
            w = self.a4_h_mm * width_ratio
            return 'P', w, h

    def img_to_pdf(self, i_dir, o_dir, filename, invert_pages):
        """Combines images into PDF, inverting specified pages."""
        pdf = FPDF(unit="mm", format='A4')
        pdf.set_auto_page_break(auto=False, margin=0)
        pdf.set_margins(0, 0, 0)

        # Collect and sort image files
        filepaths = []
        for filepath in glob.iglob(os.path.join(i_dir, '*.jpeg')):
            filepaths.append(filepath)

        pages = []
        for path in filepaths:
            base = os.path.basename(path)
            match = re.search(r'(\d+)\.jpeg', base)
            if match:
                pages.append((int(match.group(1)), path))
        pages.sort(key=lambda x: x[0])

        # Process each page
        for page_num, img_path in pages:
            if page_num in invert_pages:
                self.invert_image(img_path, img_path)
            else:
                print("Keeping original image: {}".format(img_path))
            
            with PILImage.open(img_path) as img:
                width_pixels, height_pixels = img.size

            # Get scaled dimensions and orientation
            orientation, w, h = self.get_scaled_dimensions(width_pixels, height_pixels)
            
            # Add page with proper orientation
            pdf.add_page(orientation=orientation)
            
            # Center image on page
            x = (self.a4_w_mm if orientation == 'P' else self.a4_h_mm - w) / 2
            y = (self.a4_h_mm if orientation == 'P' else self.a4_w_mm - h) / 2
            
            # Place image
            pdf.image(img_path, x=x, y=y, w=w, h=h)
            print(f"Added {img_path} to PDF ({orientation})")

        # Save output
        if not os.path.exists(o_dir):
            os.makedirs(o_dir)
        output_pdf = os.path.join(o_dir, filename)
        pdf.output(output_pdf, "F")
        print("Generated PDF: {}".format(output_pdf))


def parse_page_ranges(range_str):
    """Converts range string to list of page numbers."""
    pages = set()
    parts = range_str.split(',')
    for part in parts:
        part = part.strip()
        if '-' in part:
            start, end = part.split('-')
            pages.update(range(int(start), int(end) + 1))
        else:
            pages.add(int(part))
    return sorted(pages)


if __name__ == "__main__":
    converter = Converter()
    pdf_file = 'input.pdf'
    img_dir = 'images'
    output_dir = 'output'
    output_pdf_name = 'result.pdf'

    page_range_str = "1-12,14-20,22-32,56,66-78,82-97"
    pages_to_invert = parse_page_ranges(page_range_str)

    converter.pdf_to_img_all(pdf_file, img_dir)
    converter.img_to_pdf(img_dir, output_dir, output_pdf_name, pages_to_invert)