Salman Alfarisi commited on
Commit
5a9e63f
·
1 Parent(s): a40f5dd

Initial: commit change background color

Browse files
Files changed (5) hide show
  1. .gitignore +65 -0
  2. LICENSE +21 -0
  3. README.md +11 -0
  4. app.py +99 -0
  5. requirements.txt +5 -0
.gitignore ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+
26
+ # Virtual environment
27
+ venv/
28
+ env/
29
+ .env/
30
+ ENV/
31
+
32
+ # Editor directories and files
33
+ .vscode/
34
+ .idea/
35
+ *.sublime-project
36
+ *.sublime-workspace
37
+
38
+ # Jupyter Notebook checkpoints
39
+ .ipynb_checkpoints
40
+
41
+ # OS files
42
+ .DS_Store
43
+ Thumbs.db
44
+
45
+ # Logs and databases
46
+ *.log
47
+ *.sqlite3
48
+
49
+ # Temporary files
50
+ tmp/
51
+ temp/
52
+ *.tmp
53
+ *.bak
54
+ *.swp
55
+
56
+ # Gradio uploads/cache
57
+ gradio_data/
58
+
59
+ # Python packaging
60
+ pip-wheel-metadata/
61
+ *.dist-info/
62
+
63
+ # Test outputs
64
+ .coverage
65
+ htmlcov/
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Salman Alfarisi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -11,3 +11,14 @@ license: mit
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
14
+
15
+ ---
16
+
17
+
18
+ # 🖼️ Change Background Color App
19
+
20
+ A lightweight Gradio web app to remove the background of any image and replace it with a user-chosen solid color. Simply upload your photo, pick from default swatches, use the color picker or enter a HEX code, then download your finalized PNG.
21
+
22
+ ---
23
+
24
+
app.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, tempfile, re
2
+ import gradio as gr
3
+ from rembg import remove
4
+ from PIL import Image, ImageColor
5
+
6
+ # CPU only
7
+ os.environ["ORT_PROVIDERS"] = "CPUExecutionProvider"
8
+
9
+ def normalize_color(c: str) -> str:
10
+ """Convert 'rgba(r,g,b,a)' to '#rrggbb', or pass through hex."""
11
+ c = c.strip()
12
+ if c.startswith("rgba"):
13
+ nums = [float(x) for x in re.findall(r"[\d\.]+", c)]
14
+ r, g, b = map(int, nums[:3])
15
+ return f"#{r:02x}{g:02x}{b:02x}"
16
+ return c
17
+
18
+ def change_background_and_save(img: Image.Image, color: str):
19
+ """Remove bg, composite over colored background, save PNG."""
20
+ fg = remove(img).convert("RGBA")
21
+ hexcol = normalize_color(color)
22
+ rgb = ImageColor.getrgb(hexcol)
23
+ bg = Image.new("RGBA", fg.size, rgb + (255,))
24
+ out = Image.alpha_composite(bg, fg)
25
+
26
+ tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
27
+ out.save(tmp.name, "PNG")
28
+ tmp.close()
29
+ return out, tmp.name
30
+
31
+ css = """
32
+ h2, p { text-align:center; }
33
+ #controls-row { margin-top:1rem; margin-bottom:1rem; }
34
+ #swatch-red,#swatch-blue,#swatch-white {
35
+ width:24px; height:24px; border:none; margin-right:8px; cursor:pointer;
36
+ }
37
+ #swatch-red { background:#DB1514; }
38
+ #swatch-blue{ background:#0090FF; }
39
+ #swatch-white{ background:#FFFFFF; border:1px solid #ccc; }
40
+ #change-btn { width:100%; }
41
+ .footer { text-align:center; margin-top:2rem; color:#666; font-size:0.9rem; }
42
+ .social-icons a { margin:0 .5rem; text-decoration:none; color:inherit; }
43
+ """
44
+
45
+ with gr.Blocks(css=css, title="Change Background Color") as demo:
46
+ gr.Markdown("## CHANGE BACKGROUND COLOR")
47
+ gr.Markdown("Upload a photo, pick a background color, then download the result.")
48
+
49
+ with gr.Row():
50
+ inp = gr.Image(label="Upload Photo", type="pil")
51
+ out = gr.Image(label="Result", interactive=False)
52
+
53
+ with gr.Row(elem_id="controls-row"):
54
+ with gr.Column(scale=1):
55
+ gr.Markdown("**Default Colors**")
56
+ red_btn = gr.Button("", elem_id="swatch-red")
57
+ blue_btn = gr.Button("", elem_id="swatch-blue")
58
+ white_btn = gr.Button("", elem_id="swatch-white")
59
+ with gr.Column(scale=1):
60
+ gr.Markdown("**Pick a Color**")
61
+ picker = gr.ColorPicker(value="#DB1514")
62
+ with gr.Column(scale=1):
63
+ gr.Markdown("**Or enter hex**")
64
+ manual = gr.Textbox(value="#DB1514", placeholder="#RRGGBB")
65
+
66
+ change_btn = gr.Button("✏️ Change Background", elem_id="change-btn", interactive=False)
67
+ download_btn = gr.DownloadButton("⬇️ Download PNG", visible=True)
68
+
69
+ # Enable the Change button once an image is uploaded
70
+ inp.change(lambda _: gr.update(interactive=True), inp, change_btn)
71
+
72
+ # swatches set the picker
73
+ red_btn.click(lambda: "#DB1514", None, picker)
74
+ blue_btn.click(lambda: "#0090FF", None, picker)
75
+ white_btn.click(lambda: "#FFFFFF", None, picker)
76
+
77
+ # manual textbox drives the picker too
78
+ manual.change(lambda h: h or "#DB1514", manual, picker)
79
+
80
+ # perform the work and hook up output & download
81
+ change_btn.click(
82
+ fn=change_background_and_save,
83
+ inputs=[inp, picker],
84
+ outputs=[out, download_btn],
85
+ )
86
+
87
+ gr.HTML("""
88
+ <div class="footer">
89
+ Made by Salman Alfarisi • 2025<br>
90
+ <span class="social-icons">
91
+ <a href="https://github.com/salmanalfarisi11" target="_blank">GitHub</a> |
92
+ <a href="https://www.instagram.com/faris.salman111/" target="_blank">Instagram</a> |
93
+ <a href="https://id.linkedin.com/in/salmanalfarisi11" target="_blank">LinkedIn</a>
94
+ </span>
95
+ </div>
96
+ """)
97
+
98
+ if __name__ == "__main__":
99
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio>=3.20
2
+ rembg>=2.0.30
3
+ Pillow>=9.0.0
4
+ onnxruntime>=1.13.1
5
+