File size: 1,997 Bytes
ebd40f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3f7a009
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import re
from pathlib import Path
from PIL import Image


def natural_key(s: str):
    """Natural sort key: '10.png' sorts after '2.png' correctly."""
    return [int(t) if t.isdigit() else t.lower() for t in re.split(r"(\d+)", s)]


def load_rgb_image(path: str | Path) -> Image.Image:
    img = Image.open(path)
    if img.mode != "RGB":
        img = img.convert("RGB")
    return img


def save_rgb_png(img: Image.Image, path: str | Path):
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)
    img.save(path, format="PNG")


def make_rgba_with_alpha(rgb_img: Image.Image, alpha_mask: Image.Image) -> Image.Image:
    """
    rgb_img: RGB PIL
    alpha_mask: L PIL, same size or will be resized
    Returns RGBA PIL where alpha channel is the mask.
    """
    if rgb_img.mode != "RGB":
        rgb_img = rgb_img.convert("RGB")
    if alpha_mask.mode != "L":
        alpha_mask = alpha_mask.convert("L")
    if alpha_mask.size != rgb_img.size:
        alpha_mask = alpha_mask.resize(rgb_img.size, Image.NEAREST)
    rgba = rgb_img.copy()
    rgba.putalpha(alpha_mask)
    return rgba


def save_rgba_png(img: Image.Image, path: str | Path):
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)
    img.save(path, format="PNG")


def remove_white_background_alpha(img: Image.Image, threshold: int = 240) -> Image.Image:
    """
    Create an alpha mask by treating near-white pixels as background.
    Pixels where R, G, B are all >= threshold are considered background (alpha=0).
    All other pixels get alpha=255.
    Returns L mode image (0=background, 255=foreground).
    """
    import numpy as np

    if img.mode != "RGB":
        img = img.convert("RGB")
    arr = np.array(img)  # (H, W, 3)
    # Background = all channels >= threshold
    is_white = (arr[:, :, 0] >= threshold) & (arr[:, :, 1] >= threshold) & (arr[:, :, 2] >= threshold)
    alpha = np.where(is_white, 0, 255).astype(np.uint8)
    return Image.fromarray(alpha, mode="L")