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()
|