framing-space / app.py
kodey175's picture
Create app.py
cac299e verified
Raw
History Blame Contribute Delete
3.2 kB
import gradio as gr
from PIL import Image, ImageOps
import numpy as np
def process_image(image, target_aspect="9:16", fit_mode="crop"):
"""
Frames an image to a target aspect ratio.
fit_mode: 'crop' (center crop) or 'pad' (add borders)
"""
if image is None:
return None
# Convert to PIL if needed (Gradio passes numpy arrays sometimes)
if isinstance(image, np.ndarray):
img = Image.fromarray(image)
else:
img = image
w, h = img.size
current_ratio = w / h
# Parse target aspect
if target_aspect == "9:16":
target_ratio = 9 / 16
elif target_aspect == "16:9":
target_ratio = 16 / 9
elif target_aspect == "1:1":
target_ratio = 1.0
elif target_aspect == "4:5":
target_ratio = 4 / 5
else:
target_ratio = 9 / 16 # Default
if fit_mode == "pad":
# Calculate new size to fit inside target ratio
if current_ratio > target_ratio:
# Image is wider than target -> fit width, pad height
new_w = w
new_h = int(w / target_ratio)
else:
# Image is taller than target -> fit height, pad width
new_h = h
new_w = int(h * target_ratio)
# Create background (black or blurred version could be added, using black for now)
new_img = Image.new('RGB', (new_w, new_h), (0, 0, 0))
# Paste original in center
x_offset = (new_w - w) // 2
y_offset = (new_h - h) // 2
new_img.paste(img, (x_offset, y_offset))
return new_img
else: # Crop mode (Center Crop)
# Calculate crop box
if current_ratio > target_ratio:
# Image is wider -> crop width
new_w = int(h * target_ratio)
new_h = h
x_offset = (w - new_w) // 2
y_offset = 0
else:
# Image is taller -> crop height
new_w = w
new_h = int(w / target_ratio)
x_offset = 0
y_offset = (h - new_h) // 2
left = x_offset
top = y_offset
right = left + new_w
bottom = top + new_h
return img.crop((left, top, right, bottom))
with gr.Blocks(title="MMahBot Framing Studio") as demo:
gr.Markdown("## 🖼️ AI Image Framer & Cropper")
gr.Markdown("Prepare images for Watermarking and Video Generation by enforcing aspect ratios.")
with gr.Row():
with gr.Column():
input_img = gr.Image(label="Upload Image", type="pil")
aspect_radio = gr.Radio(
["9:16", "16:9", "1:1", "4:5"],
value="9:16",
label="Target Aspect Ratio"
)
mode_radio = gr.Radio(
["crop", "pad"],
value="crop",
label="Fitting Mode (Crop removes edges, Pad adds borders)"
)
btn = gr.Button("Process Frame", variant="primary")
with gr.Column():
output_img = gr.Image(label="Framed Result", type="pil")
btn.click(fn=process_image, inputs=[input_img, aspect_radio, mode_radio], outputs=output_img)
if __name__ == "__main__":
demo.launch()