Spaces:
Running
Running
| 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() |