Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,47 +11,43 @@ from diffusers import AutoPipelineForInpainting, AutoencoderKL
|
|
| 11 |
# Pure-CPU helpers (no CUDA here)
|
| 12 |
# -----------------------------
|
| 13 |
from PIL import Image, ImageChops
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
def autocrop_content(img: Image.Image, bg_color=(255, 255, 255), tol=12) -> Image.Image:
|
| 16 |
-
"""
|
| 17 |
-
Trim uniform white (or near-white) margins before we center/pad.
|
| 18 |
-
Works for RGB and RGBA. `tol` is tolerance for "how white".
|
| 19 |
-
"""
|
| 20 |
if img.mode in ("RGBA", "LA"):
|
| 21 |
-
# If we have transparency, use alpha channel bbox
|
| 22 |
alpha = img.split()[-1]
|
| 23 |
bbox = alpha.getbbox()
|
| 24 |
return img.crop(bbox) if bbox else img
|
| 25 |
|
| 26 |
-
# RGB: compare to a solid background
|
| 27 |
bg = Image.new(img.mode, img.size, bg_color)
|
| 28 |
diff = ImageChops.difference(img, bg).convert("L")
|
| 29 |
-
# Binarize with tolerance to catch JPEG off-white backgrounds
|
| 30 |
mask = diff.point(lambda p: 255 if p > tol else 0, mode="1")
|
| 31 |
bbox = mask.getbbox()
|
| 32 |
return img.crop(bbox) if bbox else img
|
| 33 |
|
| 34 |
def squarify_image(img: Image.Image, color="white") -> Image.Image:
|
| 35 |
-
|
| 36 |
-
1) Trim outer white margins.
|
| 37 |
-
2) Pad to square, centered.
|
| 38 |
-
"""
|
| 39 |
img = autocrop_content(img, bg_color=(255, 255, 255), tol=12)
|
| 40 |
|
| 41 |
w, h = img.size
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
bg.paste(img, ((size - w) // 2, (size - h) // 2))
|
| 45 |
-
return bg
|
| 46 |
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
def divisible_by_8(image: Image.Image) -> Image.Image:
|
| 49 |
w, h = image.size
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
| 55 |
|
| 56 |
# -----------------------------
|
| 57 |
# Lazy singletons (created inside GPU context)
|
|
|
|
| 11 |
# Pure-CPU helpers (no CUDA here)
|
| 12 |
# -----------------------------
|
| 13 |
from PIL import Image, ImageChops
|
| 14 |
+
import math
|
| 15 |
+
|
| 16 |
+
def _round_up(x, m=8):
|
| 17 |
+
return int(math.ceil(x / m) * m)
|
| 18 |
|
| 19 |
def autocrop_content(img: Image.Image, bg_color=(255, 255, 255), tol=12) -> Image.Image:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
if img.mode in ("RGBA", "LA"):
|
|
|
|
| 21 |
alpha = img.split()[-1]
|
| 22 |
bbox = alpha.getbbox()
|
| 23 |
return img.crop(bbox) if bbox else img
|
| 24 |
|
|
|
|
| 25 |
bg = Image.new(img.mode, img.size, bg_color)
|
| 26 |
diff = ImageChops.difference(img, bg).convert("L")
|
|
|
|
| 27 |
mask = diff.point(lambda p: 255 if p > tol else 0, mode="1")
|
| 28 |
bbox = mask.getbbox()
|
| 29 |
return img.crop(bbox) if bbox else img
|
| 30 |
|
| 31 |
def squarify_image(img: Image.Image, color="white") -> Image.Image:
|
| 32 |
+
# 1) trim margins
|
|
|
|
|
|
|
|
|
|
| 33 |
img = autocrop_content(img, bg_color=(255, 255, 255), tol=12)
|
| 34 |
|
| 35 |
w, h = img.size
|
| 36 |
+
# 2) target square side rounded **up** to /8
|
| 37 |
+
side = _round_up(max(w, h), 8)
|
|
|
|
|
|
|
| 38 |
|
| 39 |
+
bg = Image.new("RGB", (side, side), color=color)
|
| 40 |
+
bg.paste(img, ((side - w) // 2, (side - h) // 2))
|
| 41 |
+
return bg
|
| 42 |
|
| 43 |
def divisible_by_8(image: Image.Image) -> Image.Image:
|
| 44 |
w, h = image.size
|
| 45 |
+
# round **up** so we never shrink (keeps content + avoids 1012-style errors)
|
| 46 |
+
nw = _round_up(w, 8)
|
| 47 |
+
nh = _round_up(h, 8)
|
| 48 |
+
if (nw, nh) == (w, h):
|
| 49 |
+
return image
|
| 50 |
+
return image.resize((nw, nh), Image.LANCZOS)
|
| 51 |
|
| 52 |
# -----------------------------
|
| 53 |
# Lazy singletons (created inside GPU context)
|