File size: 9,142 Bytes
6611cc2
 
 
f43ec75
8859105
 
f43ec75
fe80ca5
100080e
 
 
 
 
 
 
 
 
 
 
 
778f990
100080e
 
 
 
 
 
778f990
100080e
 
 
 
 
 
2f6e1d1
 
e71a0be
2f6e1d1
100080e
 
 
 
17e1ad4
 
 
 
 
 
 
 
 
41f7afb
17e1ad4
 
 
c1eeb32
 
28193e8
d5ddea1
28193e8
9b54af9
55972b1
 
17e1ad4
 
 
 
 
 
b1c4963
17e1ad4
 
d5ddea1
 
9f090db
17e1ad4
 
 
 
 
 
f43ec75
 
 
 
 
 
 
 
a59ce8e
 
 
 
f43ec75
 
 
 
f4d232d
 
9345cb2
3b76354
8939903
f43ec75
 
 
9b54af9
f43ec75
 
8939903
3b76354
f43ec75
 
 
 
 
 
6611cc2
32d411c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6611cc2
32d411c
 
 
 
 
 
 
 
 
 
 
6611cc2
 
 
 
 
 
 
 
 
 
 
a3a2cde
 
 
 
6611cc2
 
 
 
 
 
 
 
 
eddf43d
6611cc2
 
 
 
a3a2cde
6611cc2
 
 
 
 
 
 
3bf683f
2bc58c1
 
3bf683f
2bc58c1
3bf683f
32d411c
3bf683f
32d411c
3bf683f
 
 
6611cc2
 
 
 
 
 
 
 
 
 
 
32d411c
38b27db
 
3bf683f
 
 
6611cc2
 
 
 
 
 
 
 
 
 
 
 
 
 
38b27db
6611cc2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
import streamlit as st
import os
import zipfile
from PIL import Image, ImageDraw, ImageFont
from rembg import remove


def draw_ruler(image, dpi=300, unit="in", color="white"):
    """
    Draws a ruler on the top and left edges of an image.

    Args:
        image: The PIL Image object to draw on.
        dpi: The DPI of the image (default 300).
        unit: The unit of measurement (default "in").
        color: The color of the ruler (default "black").
    """

    draw = ImageDraw.Draw(image)
    width, height = image.size
    font = ImageFont.load_default(size=100)

    # Draw top ruler
    for i in range(0, width, int(dpi)):
        x = i
        draw.line((x, 0, x, 10), fill=color)
        if i % int(dpi) == 0:
            draw.text((x, 12), str(i // dpi), fill=color, font=font)

    # Draw left ruler
    for i in range(0, height, int(dpi)):
        y = i
        draw.line((0, y, 10, y), fill=color)
        if i % int(dpi) == 0:
            if i != 0:
                 draw.text((12, y), str(i // dpi), fill=color, font=font)
            
    draw.text((100, y-30), "inch", fill=color, font=font)

    return image
    
def draw_ruler1(image, dpi=72, font_size=144):
    """
    Draw a virtual ruler 10 cm from the bottom of the image.
    Args:
        image (PIL.Image.Image): The input image.
        dpi (int): The DPI (dots per inch) of the image. Default is 72.
    Returns:
        PIL.Image.Image: The image with the ruler drawn on it.
    """
    dpi = image.info.get("dpi", (72, 72))
    print("dpi:",image.info.get("dpi",(300,300)))
    dpi = dpi[0] if isinstance(dpi, tuple) else dpi
    # Create a drawing context
    draw = ImageDraw.Draw(image)

    # Load a font
    #try:   
        #font = ImageFont.truetype("arial.ttf", font_size)
    #except IOError:
    font = ImageFont.load_default(size=100)

    print("font:",font)
    
    # Define the ruler dimensions
    ruler_height = int(1 * dpi / 2.54)  # 1 cm in pixels
    ruler_y_position = image.height - int(10 * dpi / 2.54)  # 10 cm from the bottom
    
    # Draw horizontal ruler
    for i in range(0, image.width, int(10 * dpi / 2.54)):  # 10 cm intervals
        if i % int(dpi * 10 / 2.54) == 0:  # 10 cm intervals
            draw.line([(i, ruler_y_position), (i, ruler_y_position + ruler_height)], fill="black", width=2)
            draw.text((i + 2, ruler_y_position + 2), str(i // int(dpi / 2.54)), fill="black", font=font)
            #draw.text((i + 2, ruler_y_position + 2), "8", fill="black", font=font)

        else:
            draw.line([(i, ruler_y_position), (i, ruler_y_position + ruler_height // 2)], fill="black", width=1)
    
    return image
    
def draw_ruler0(image, dpi=72):
    """
    Draw a virtual ruler 1 cm from the bottom of the image.
    Args:
        image (PIL.Image.Image): The input image.
        dpi (int): The DPI (dots per inch) of the image. Default is 72.
    Returns:
        PIL.Image.Image: The image with the ruler drawn on it.
    """
    # Get the DPI value as a single number
    dpi = image.info.get("dpi", (72, 72))
    dpi = dpi[0] if isinstance(dpi, tuple) else dpi

    # Create a drawing context
    draw = ImageDraw.Draw(image)
    
    # Define the ruler dimensions
    ruler_height = int(10 * dpi / 2.54)  # 10 cm in pixels
    ruler_y_position = image.height - ruler_height  # 10 cm from the bottom

    print("ruler_y_position",ruler_y_position)
    print("image.height",image.height)
    # Draw horizontal ruler
    for i in range(0, image.width, int(dpi / 2.54)):  # 1 cm intervals
        if i % int(dpi * 10 / 2.54) == 0:  # 10 cm intervals
            draw.line([(i, ruler_y_position), (i, image.height)], fill="black", width=5)
            draw.text((i + 2, ruler_y_position + 2), str(i // int(dpi / 2.54)), fill="black")
        else:
            draw.line([(i, ruler_y_position), (i, ruler_y_position + ruler_height // 2)], fill="black", width=5)
            
    return image

# Example usage
#image = Image.open("path_to_your_image.jpg")
#image_with_ruler = draw_ruler(image)
#image_with_ruler.show()

def crop_image(image, left_mm, right_mm, top_mm, bottom_mm):
    """
    Crop the image from the left, right, top, and bottom sides.
    Args:
        image (PIL.Image.Image): The input image.
        left_mm (float): The amount to crop from the left side in millimeters.
        right_mm (float): The amount to crop from the right side in millimeters.
        top_mm (float): The amount to crop from the top side in millimeters.
        bottom_mm (float): The amount to crop from the bottom side in millimeters.
    Returns:
        PIL.Image.Image: The cropped image.
    """
    # Get the DPI value as a single number
    dpi = image.info.get("dpi", (72, 72))
    dpi = dpi[0] if isinstance(dpi, tuple) else dpi

    # Calculate the cropping width and height in pixels based on image DPI
    width_mm = image.width * 25.4 / dpi
    height_mm = image.height * 25.4 / dpi

    left_crop = int(left_mm * image.width / width_mm)
    right_crop = image.width - int(right_mm * image.width / width_mm)
    top_crop = int(top_mm * image.height / height_mm)
    bottom_crop = image.height - int(bottom_mm * image.height / height_mm)

    # Crop the image
    cropped_image = image.crop((left_crop, top_crop, right_crop, bottom_crop))

    return cropped_image
    
def crop_image1(image, left_mm, right_mm):
    """
    Crop the image from both the left and right sides.

    Args:
        image (PIL.Image.Image): The input image.
        left_mm (float): The amount to crop from the left side in millimeters.
        right_mm (float): The amount to crop from the right side in millimeters.

    Returns:
        PIL.Image.Image: The cropped image.
    """
    # Get the DPI value as a single number
    dpi = image.info.get("dpi", (72, 72))
    dpi = dpi[0] if isinstance(dpi, tuple) else dpi

    # Calculate the cropping width in pixels based on image DPI
    width_mm = image.width * 25.4 / dpi
    cropping_width = int((left_mm + right_mm) * image.width / width_mm)

    # Calculate the left and right cropping boundaries
    left_crop = int(left_mm * image.width / width_mm)
    right_crop = image.width - int(right_mm * image.width / width_mm)

    # Crop the image
    cropped_image = image.crop((left_crop, left_crop, right_crop, image.height))

    return cropped_image



def main():
    st.title("Batch Image Cropper")

    # Upload multiple image files
    uploaded_files = st.file_uploader("Upload image files", type=["jpg", "jpeg", "png"], accept_multiple_files=True)

    if uploaded_files is not None:
        col1, col2, col3, col4, col5 = st.columns(5)

        with col1:
            left_mm = st.number_input("Crop left (mm)", min_value=0.0, value=0.0, step=0.1)
        with col2:
            right_mm = st.number_input("Crop right (mm)", min_value=0.0, value=0.0, step=0.1)
        with col3:
            top_mm = st.number_input("Crop top (mm)", min_value=0.0, value=0.0, step=0.1)
        with col4:
            bottom_mm = st.number_input("Crop bottom (mm)", min_value=0.0, value=0.0, step=0.1)
        with col5:
            ruler_chk = st.checkbox("Ruler?")

        # Create a container to hold the cropped images
        images_container = st.empty()

        # Process each uploaded image file
        cropped_images = []
        for uploaded_file in uploaded_files:
            # Open the image file
            image = Image.open(uploaded_file)

            # Crop the image
            cropped_image = crop_image(image, left_mm, right_mm, top_mm, bottom_mm)
            #remove background
            cropped_image=remove(cropped_image)
            #do we draw a ruler
            if ruler_chk:
                cropped_image= draw_ruler(cropped_image)
            cropped_images.append(cropped_image)

        # Display the original and cropped images side by side
        col_width = 300
        num_images = len(uploaded_files)
        num_columns = 2
        num_rows = (num_images + 1) // num_columns
        for row in range(num_rows):
            cols = st.columns(num_columns)
            for col in range(num_columns):
                index = row * num_columns + col
                if index < num_images:
                    cols[col].subheader(f"Image {index+1}")
                    cols[col].image(uploaded_files[index], caption="Original Image", width=col_width)
                    cols[col].image(cropped_images[index], caption="Cropped Image", width=col_width)

        # Save all cropped images
        if st.button("Save All"):
            zip_filename = "cropped_images.zip"
            with zipfile.ZipFile(zip_filename, "w") as zipf:
                for i, cropped_image in enumerate(cropped_images):
                    filename, ext = os.path.splitext(uploaded_files[i].name)
                    cropped_filename = f"cropped_{filename}.png"
                    cropped_image.save(cropped_filename)
                    zipf.write(cropped_filename)
                    os.remove(cropped_filename)
            st.success(f"All cropped images saved successfully as {zip_filename}")


if __name__ == "__main__":
    main()