40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
|
|
import sys
|
||
|
|
from PIL import Image
|
||
|
|
|
||
|
|
def remove_white_bg(input_path, output_path, threshold=235):
|
||
|
|
img = Image.open(input_path).convert("RGBA")
|
||
|
|
data = img.getdata()
|
||
|
|
new_data = []
|
||
|
|
|
||
|
|
for item in data:
|
||
|
|
r, g, b, a = item
|
||
|
|
avg = (r + g + b) / 3.0
|
||
|
|
|
||
|
|
# If it's very close to white, make it transparent
|
||
|
|
if avg > threshold and min(r,g,b) > threshold - 10:
|
||
|
|
# Feathering the alpha channel
|
||
|
|
# 255 = fully transparent
|
||
|
|
# threshold = fully opaque
|
||
|
|
factor = (avg - threshold) / (255 - threshold)
|
||
|
|
alpha = int(255 * (1 - factor))
|
||
|
|
|
||
|
|
# Clamp alpha
|
||
|
|
alpha = max(0, min(255, alpha))
|
||
|
|
|
||
|
|
# We keep the pixel white to avoid dark fringes, but lower its opacity
|
||
|
|
new_data.append((255, 255, 255, alpha))
|
||
|
|
else:
|
||
|
|
new_data.append(item)
|
||
|
|
|
||
|
|
img.putdata(new_data)
|
||
|
|
|
||
|
|
# Optional: crop the image to its bounding box
|
||
|
|
bbox = img.getbbox()
|
||
|
|
if bbox:
|
||
|
|
img = img.crop(bbox)
|
||
|
|
|
||
|
|
img.save(output_path, "PNG")
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
remove_white_bg(sys.argv[1], sys.argv[2])
|