""" Hugging Face Space: Image Watermarker Processes images to add subtle, non-removable watermarks. Requirements: pillow, requests """ import gradio as gr from PIL import Image, ImageDraw, ImageFont import io import os def apply_watermark(image, watermark_text, position="bottom-right", opacity=0.7): """ Apply a text watermark to an image. Args: image: PIL Image object watermark_text: Text to overlay position: One of 'top-left', 'top-right', 'bottom-left', 'bottom-right', 'center' opacity: Float 0.0-1.0 Returns: PIL Image with watermark """ if image.mode != 'RGBA': image = image.convert('RGBA') # Create watermark layer watermark_layer = Image.new('RGBA', image.size, (255, 255, 255, 0)) draw = ImageDraw.Draw(watermark_layer) # Try to load a font, fall back to default try: # Try common font paths font_paths = [ "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf", "C:\\Windows\\Fonts\\arial.ttf", "/System/Library/Fonts/Helvetica.ttc" ] font = None for path in font_paths: if os.path.exists(path): font = ImageFont.truetype(path, 36) break if font is None: font = ImageFont.load_default() except Exception: font = ImageFont.load_default() # Get text bounding box bbox = draw.textbbox((0, 0), watermark_text, font=font) text_width = bbox[2] - bbox[0] text_height = bbox[3] - bbox[1] # Calculate position padding = 20 img_width, img_height = image.size if position == "top-left": x, y = padding, padding elif position == "top-right": x, y = img_width - text_width - padding, padding elif position == "bottom-left": x, y = padding, img_height - text_height - padding elif position == "bottom-right": x, y = img_width - text_width - padding, img_height - text_height - padding elif position == "center": x, y = (img_width - text_width) // 2, (img_height - text_height) // 2 else: x, y = img_width - text_width - padding, img_height - text_height - padding # Draw text with opacity alpha = int(255 * opacity) draw.text((x, y), watermark_text, font=font, fill=(255, 255, 255, alpha)) # Composite watermarked = Image.alpha_composite(image, watermark_layer) return watermarked.convert('RGB') def process_image(input_image, watermark_text, position, opacity): if input_image is None: return None result = apply_watermark(input_image, watermark_text, position, float(opacity)) return result # Gradio Interface with gr.Blocks(title="MMahBot Watermarker") as demo: gr.Markdown("# 🛡️ MMahBot Smart Watermarker") gr.Markdown("Upload an image and add a subtle, professional watermark.") with gr.Row(): with gr.Column(): input_img = gr.Image(type="pil", label="Upload Image") watermark_text = gr.Textbox( label="Watermark Text", value="@mmahbot", placeholder="Enter watermark text" ) position = gr.Dropdown( choices=["bottom-right", "bottom-left", "top-right", "top-left", "center"], value="bottom-right", label="Position" ) opacity = gr.Slider( minimum=0.1, maximum=1.0, value=0.7, step=0.1, label="Opacity" ) submit_btn = gr.Button("Apply Watermark", variant="primary") with gr.Column(): output_img = gr.Image(type="pil", label="Watermarked Image") submit_btn.click( fn=process_image, inputs=[input_img, watermark_text, position, opacity], outputs=output_img ) if __name__ == "__main__": demo.launch()