import gradio as gr from PIL import Image, ImageDraw def halftone_effect(img, dot_size=10): """ Apply a halftone effect to the input image. Parameters: - img: PIL.Image object (input image) - dot_size: int, spacing and maximum cell size for dot placement Returns: - PIL.Image object with halftone effect """ # Convert to grayscale grayscale = img.convert('L') width, height = grayscale.size # Create a new white image for the halftone effect halftone_image = Image.new('L', (width, height), color=255) draw = ImageDraw.Draw(halftone_image) # Loop through the image in steps of dot_size for x in range(0, width, dot_size): for y in range(0, height, dot_size): # Determine the size of the current block (to handle image edges) block_width = min(dot_size, width - x) block_height = min(dot_size, height - y) # Extract the region of interest and calculate its average brightness region = grayscale.crop((x, y, x + block_width, y + block_height)) avg_brightness = sum(region.getdata()) / (block_width * block_height) # Calculate radius based on brightness (brighter = smaller dot) max_radius = dot_size // 2 radius = int((255 - avg_brightness) / 255 * max_radius) radius = max(0, min(radius, max_radius)) # Clamp radius between 0 and max_radius # Draw the circle at the center of the current cell center_x = x + dot_size // 2 center_y = y + dot_size // 2 draw.ellipse( ( center_x - radius, center_y - radius, center_x + radius, center_y + radius ), fill=0 # Black dot ) return halftone_image # Gradio Interface interface = gr.Interface( fn=halftone_effect, inputs=[ gr.Image(type="pil", label="Upload an Image"), gr.Slider(minimum=5, maximum=20, step=1, value=10, label="Dot Size") ], outputs=gr.Image(label="Halftone Image"), title="Halftone Image Generator", description="Convert any image into a stylized halftone effect using black dots.", allow_flagging="never" ) if __name__ == "__main__": interface.launch()