cr8 commited on
Commit
e227540
·
verified ·
1 Parent(s): 5e8d556

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -68
app.py CHANGED
@@ -1,59 +1,19 @@
1
  import gradio as gr
2
- from PIL import Image, ImageOps
3
  import rembg
4
  import io
5
- import numpy as np
 
6
 
7
- def remove_background_add_outline(image, outline_size=5, outline_color=(255, 255, 255)):
8
  if image is None:
9
  return None, None
10
 
11
- # Convert image to bytes for rembg
12
- img_byte_arr = io.BytesIO()
13
- image.save(img_byte_arr, format='PNG')
14
- img_byte_arr.seek(0)
15
-
16
- # Remove background
17
- processed_bytes = rembg.remove(img_byte_arr.getvalue())
18
- processed_img = Image.open(io.BytesIO(processed_bytes)).convert("RGBA")
19
-
20
- # Add outline
21
- if outline_size > 0:
22
- # Create a mask from the alpha channel
23
- alpha = processed_img.split()[3]
24
-
25
- # Create a slightly larger mask by dilating
26
- larger_mask = ImageOps.expand(alpha, outline_size, fill=255)
27
-
28
- # Create an outline image
29
- outline_img = Image.new('RGBA', larger_mask.size, (0, 0, 0, 0))
30
- outline_color_with_alpha = outline_color + (255,) # Add alpha to color
31
-
32
- # Draw the outline
33
- for x in range(larger_mask.width):
34
- for y in range(larger_mask.height):
35
- if larger_mask.getpixel((x, y)) == 255 and (x < outline_size or y < outline_size or
36
- x >= processed_img.width or y >= processed_img.height or
37
- processed_img.getpixel((x-outline_size, y-outline_size))[3] == 0):
38
- outline_img.putpixel((x, y), outline_color_with_alpha)
39
-
40
- # Combine the outline with the original image
41
- final_img = Image.new('RGBA', larger_mask.size, (0, 0, 0, 0))
42
- final_img.paste(outline_img, (0, 0), outline_img)
43
- final_img.paste(processed_img, (outline_size, outline_size), processed_img)
44
- else:
45
- final_img = processed_img
46
-
47
- # Prepare file for download
48
- download_path = "sticker.png"
49
- final_img.save(download_path, format="PNG")
50
-
51
- return final_img, download_path
52
-
53
- # Faster but simpler method for adding outline
54
- def add_outline_simple(image, outline_size=5, outline_color=(255, 255, 255)):
55
- if image is None:
56
- return None, None
57
 
58
  # Convert image to bytes for rembg
59
  img_byte_arr = io.BytesIO()
@@ -64,54 +24,115 @@ def add_outline_simple(image, outline_size=5, outline_color=(255, 255, 255)):
64
  processed_bytes = rembg.remove(img_byte_arr.getvalue())
65
  processed_img = Image.open(io.BytesIO(processed_bytes)).convert("RGBA")
66
 
67
- # Create a larger background image with the outline color
68
- if outline_size > 0:
 
69
  background = Image.new('RGBA',
70
  (processed_img.width + 2*outline_size,
71
  processed_img.height + 2*outline_size),
72
- outline_color + (255,))
 
 
 
73
 
74
  # Paste the processed image onto the background
 
75
  background.paste(processed_img, (outline_size, outline_size), processed_img)
76
  final_img = background
77
  else:
78
  final_img = processed_img
79
 
80
- # Prepare file for download
81
- download_path = "sticker.png"
82
- final_img.save(download_path, format="PNG")
 
 
 
 
 
 
 
83
 
84
  return final_img, download_path
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  # Gradio Interface
87
  with gr.Blocks(title="Sticker Maker") as interface:
88
  gr.Markdown("# Sticker Maker")
89
- gr.Markdown("Remove background, add white outline, and download as transparent PNG")
90
 
91
  with gr.Row():
92
  with gr.Column():
93
  image_upload = gr.Image(label="Upload Image", type="pil")
 
94
  outline_size = gr.Slider(label="Outline Thickness", minimum=0, maximum=20, value=5, step=1)
95
  outline_color = gr.ColorPicker(label="Outline Color", value="#FFFFFF")
96
- create_btn = gr.Button("Create Sticker")
97
 
98
  with gr.Column():
99
- output_preview = gr.Image(label="Preview", type="pil")
100
  output_file = gr.File(label="Download PNG")
101
 
102
- def process_image(image, outline_size, outline_color):
103
- # Convert hex color to RGB
104
- r = int(outline_color[1:3], 16)
105
- g = int(outline_color[3:5], 16)
106
- b = int(outline_color[5:7], 16)
107
- rgb_color = (r, g, b)
108
-
109
- # Use the simpler method for better performance
110
- return add_outline_simple(image, int(outline_size), rgb_color)
111
 
112
  create_btn.click(
113
  fn=process_image,
114
- inputs=[image_upload, outline_size, outline_color],
115
  outputs=[output_preview, output_file]
116
  )
117
 
 
1
  import gradio as gr
2
+ from PIL import Image
3
  import rembg
4
  import io
5
+ import os
6
+ import shutil
7
 
8
+ def process_image(image, outline_size, outline_color, add_outline):
9
  if image is None:
10
  return None, None
11
 
12
+ # Convert hex color to RGB
13
+ r = int(outline_color[1:3], 16)
14
+ g = int(outline_color[3:5], 16)
15
+ b = int(outline_color[5:7], 16)
16
+ rgb_color = (r, g, b)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  # Convert image to bytes for rembg
19
  img_byte_arr = io.BytesIO()
 
24
  processed_bytes = rembg.remove(img_byte_arr.getvalue())
25
  processed_img = Image.open(io.BytesIO(processed_bytes)).convert("RGBA")
26
 
27
+ # Add outline if selected
28
+ if add_outline and outline_size > 0:
29
+ # Create a larger background image with the outline color
30
  background = Image.new('RGBA',
31
  (processed_img.width + 2*outline_size,
32
  processed_img.height + 2*outline_size),
33
+ (0, 0, 0, 0)) # Start with transparent background
34
+
35
+ # Create outline mask
36
+ outline_img = Image.new('RGBA', background.size, rgb_color + (255,))
37
 
38
  # Paste the processed image onto the background
39
+ background.paste(outline_img, (0, 0), create_outline_mask(processed_img, outline_size))
40
  background.paste(processed_img, (outline_size, outline_size), processed_img)
41
  final_img = background
42
  else:
43
  final_img = processed_img
44
 
45
+ # Create output directory if it doesn't exist
46
+ os.makedirs("outputs", exist_ok=True)
47
+
48
+ # Save as PNG with transparency preserved
49
+ output_path = "outputs/sticker.png"
50
+ final_img.save(output_path, format="PNG")
51
+
52
+ # Create a copy for gradio to return (workaround for download issues)
53
+ download_path = "outputs/download_sticker.png"
54
+ shutil.copy2(output_path, download_path)
55
 
56
  return final_img, download_path
57
 
58
+ def create_outline_mask(image, thickness):
59
+ """Create a mask for the outline based on the image alpha channel"""
60
+ # Get mask from alpha channel
61
+ mask = image.split()[3]
62
+ w, h = image.size
63
+
64
+ expanded = Image.new('L', (w + 2*thickness, h + 2*thickness), 0)
65
+ expanded.paste(mask, (thickness, thickness))
66
+
67
+ # Create outline mask
68
+ result = Image.new('L', expanded.size, 0)
69
+ for i in range(thickness):
70
+ # Expand the mask in all 8 directions for each thickness level
71
+ temp = Image.new('L', expanded.size, 0)
72
+ # Expand right
73
+ temp.paste(expanded, (-1, 0))
74
+ result = Image.composite(temp, result, temp)
75
+ # Expand left
76
+ temp = Image.new('L', expanded.size, 0)
77
+ temp.paste(expanded, (1, 0))
78
+ result = Image.composite(temp, result, temp)
79
+ # Expand up
80
+ temp = Image.new('L', expanded.size, 0)
81
+ temp.paste(expanded, (0, 1))
82
+ result = Image.composite(temp, result, temp)
83
+ # Expand down
84
+ temp = Image.new('L', expanded.size, 0)
85
+ temp.paste(expanded, (0, -1))
86
+ result = Image.composite(temp, result, temp)
87
+ # Expand diagonal directions
88
+ temp = Image.new('L', expanded.size, 0)
89
+ temp.paste(expanded, (-1, -1))
90
+ result = Image.composite(temp, result, temp)
91
+ temp = Image.new('L', expanded.size, 0)
92
+ temp.paste(expanded, (-1, 1))
93
+ result = Image.composite(temp, result, temp)
94
+ temp = Image.new('L', expanded.size, 0)
95
+ temp.paste(expanded, (1, -1))
96
+ result = Image.composite(temp, result, temp)
97
+ temp = Image.new('L', expanded.size, 0)
98
+ temp.paste(expanded, (1, 1))
99
+ result = Image.composite(temp, result, temp)
100
+
101
+ # Subtract the original mask to get just the outline
102
+ for y in range(expanded.height):
103
+ for x in range(expanded.width):
104
+ if expanded.getpixel((x, y)) > 0:
105
+ result.putpixel((x, y), 0)
106
+
107
+ return result
108
+
109
  # Gradio Interface
110
  with gr.Blocks(title="Sticker Maker") as interface:
111
  gr.Markdown("# Sticker Maker")
112
+ gr.Markdown("Remove background, add optional outline, and download as transparent PNG")
113
 
114
  with gr.Row():
115
  with gr.Column():
116
  image_upload = gr.Image(label="Upload Image", type="pil")
117
+ add_outline = gr.Checkbox(label="Add Outline", value=True)
118
  outline_size = gr.Slider(label="Outline Thickness", minimum=0, maximum=20, value=5, step=1)
119
  outline_color = gr.ColorPicker(label="Outline Color", value="#FFFFFF")
120
+ create_btn = gr.Button("Create Sticker", variant="primary")
121
 
122
  with gr.Column():
123
+ output_preview = gr.Image(label="Preview (Transparent Background)", type="pil")
124
  output_file = gr.File(label="Download PNG")
125
 
126
+ # Make outline options visible only when add_outline is checked
127
+ add_outline.change(
128
+ fn=lambda x: gr.update(visible=x),
129
+ inputs=add_outline,
130
+ outputs=[outline_size, outline_color]
131
+ )
 
 
 
132
 
133
  create_btn.click(
134
  fn=process_image,
135
+ inputs=[image_upload, outline_size, outline_color, add_outline],
136
  outputs=[output_preview, output_file]
137
  )
138