watermark-space / app.py
kodey175's picture
Create app.py
f021b59 verified
Raw
History Blame Contribute Delete
3.97 kB
"""
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()