Most of the friction with web-based image tools comes from small mismatches: a PNG that is 23 MB, a poster that is one pixel too wide, a "transparent" file that was saved as JPEG on the way back. None of these are hard problems, but they waste a round trip each time.
This post walks through two short Python scripts that sit next to a background-removal workflow. The first checks a folder of images against the tool's upload limits and fixes what it can. The second inspects the downloaded result and tells you whether it actually has an alpha channel. The limits used here come from the HiDream Background Remover page.
The limits
According to the tool page, an upload must be:
- JPG, PNG or WEBP
- up to 5 MB
- between 256 and 4096 pixels on each side
- at most 16 million pixels in total
The tool returns an image with a transparent background. The FAQ adds two practical notes: the download format depends on the task result, so check it if you need PNG, and avoid JPEG when exporting transparency, because JPEG has no alpha channel. If you need a white or branded background, the page suggests adding it later in a design editor.
Script 1: preflight.py
The script walks a folder, reports what is wrong with each file, and writes a fixed copy into ready/ when a fix is possible. Fixing means two things: scaling down until both the side limit and the pixel limit are met, and re-encoding as JPEG with decreasing quality until the file fits under 5 MB. Uploads can be JPEG because the transparency is created by the tool, not by your input.
"""Check and fix images before uploading them to a background remover.
Limits (from the tool page): JPG/PNG/WEBP, <= 5 MB,
each side 256-4096 px, <= 16 million pixels."""
import io, sys
from pathlib import Path
from PIL import Image
MAX_BYTES = 5 * 1024 * 1024
MIN_SIDE, MAX_SIDE, MAX_PIXELS = 256, 4096, 16_000_000
FORMATS = {"JPEG", "PNG", "WEBP"}
def problems(path: Path) -> list[str]:
out = []
with Image.open(path) as im:
w, h = im.size
if im.format not in FORMATS:
out.append(f"format {im.format}")
if min(w, h) < MIN_SIDE:
out.append(f"short side {min(w, h)} < {MIN_SIDE}")
if max(w, h) > MAX_SIDE:
out.append(f"long side {max(w, h)} > {MAX_SIDE}")
if w * h > MAX_PIXELS:
out.append(f"{w * h:,} px > {MAX_PIXELS:,}")
if path.stat().st_size > MAX_BYTES:
out.append(f"{path.stat().st_size / 1e6:.1f} MB > 5 MB")
return out
def fix(path: Path, outdir: Path) -> Path:
with Image.open(path) as im:
im = im.convert("RGB")
w, h = im.size
scale = min(1.0, MAX_SIDE / max(w, h), (MAX_PIXELS / (w * h)) ** 0.5)
if scale < 1.0:
im = im.resize((int(w * scale), int(h * scale)), Image.LANCZOS)
quality = 92
while True:
buf = io.BytesIO()
im.save(buf, "JPEG", quality=quality)
if buf.tell() <= MAX_BYTES or quality <= 60:
break
quality -= 8
out = outdir / (path.stem + "_upload.jpg")
out.write_bytes(buf.getvalue())
return out
if __name__ == "__main__":
outdir = Path("ready"); outdir.mkdir(exist_ok=True)
for p in sorted(Path(sys.argv[1]).iterdir()):
try:
issues = problems(p)
except Exception:
print(f"SKIP {p.name}: not an image"); continue
if not issues:
print(f"OK {p.name}"); continue
fixed = fix(p, outdir)
left = problems(fixed)
print(f"FIXED {p.name}: {', '.join(issues)} -> {fixed.name}"
+ (f" (still: {', '.join(left)})" if left else ""))
I ran it on a test folder with five files: a normal product photo, an oversized poster, a tiny icon, a very noisy PNG and a text file.
$ python3 preflight.py in
FIXED icon.png: short side 180 < 256 -> icon_upload.jpg (still: short side 180 < 256)
FIXED noisy.png: 22.9 MB > 5 MB -> noisy_upload.jpg
SKIP notes.txt: not an image
FIXED poster.png: long side 5000 > 4096, 17,500,000 px > 16,000,000 -> poster_upload.jpg
OK shoe.jpg
Two details are worth pointing out.
First, the poster broke two rules at once. 5000 × 3500 is over the side limit and over the pixel limit, so the scale factor is the minimum of both constraints. Checking only the long side would have produced a 4096 × 2867 image, which happens to pass, but a nearly square 4000 × 4000 image would pass the side check and still fail the pixel check. Computing both avoids that trap.
Second, the icon cannot be fixed. The script only scales down, and the line ends with (still: ...) so you notice. Upscaling a 180-pixel icon to meet a minimum is possible, but it is a decision about quality you should make on purpose, for example with an image enhancer first, rather than something a script does silently.
Script 2: check_alpha.py
After processing, the page asks you to compare with the original and inspect edges and transparent areas before downloading. A quick numeric check helps before you look closely:
"""After download: does the result really have transparency?"""
import sys
from PIL import Image
for name in sys.argv[1:]:
with Image.open(name) as im:
if "A" not in im.getbands():
print(f"{name}: no alpha channel ({im.mode}) - re-export as PNG/WEBP")
continue
a = im.getchannel("A")
hist = a.histogram()
total = im.width * im.height
clear, solid = hist[0] / total, hist[255] / total
partial = 1 - clear - solid
print(f"{name}: transparent {clear:.0%}, opaque {solid:.0%}, soft edge {partial:.1%}")
On a test cutout and a flattened JPEG:
$ python3 check_alpha.py cutout.png flat.jpg
cutout.png: transparent 65%, opaque 35%, soft edge 0.0%
flat.jpg: no alpha channel (RGB) - re-export as PNG/WEBP
The "soft edge" share is the fraction of pixels that are neither fully transparent nor fully opaque. My synthetic test circle has hard edges, so it reads 0.0%. A real cutout of hair, fur or glass will show a noticeable soft-edge share, and those are exactly the areas the page tells you to inspect. The FAQ is direct about it: results depend on the source, and hair, glass and fine edges may need manual touch-ups.
Running it on a whole folder
A practical routine: point the preflight at the folder of product shots before a batch, upload everything from ready/ plus the files marked OK, and keep the original files untouched. After downloading the results, run the alpha check on all of them at once:
$ python3 check_alpha.py results/*.png
Anything without an alpha channel is the first thing to fix, usually by downloading again in a format that keeps transparency. Anything with a large soft-edge share goes to the top of the manual review list. The two scripts together take a few seconds and change the order in which you look at files, which is most of the value.
Where this fits
The page lists three typical sources: product photos (check edges and small components), portraits and pets (hair, fur and low-contrast edges), and illustrations or AI images (translucent materials depend on the source). The scripts do not judge any of that. They only remove the boring failures, so the review time goes to the edges.
Summary
- Check format, size, side length and total pixels together before uploading.
- Only scale down automatically; flag images that are too small.
- After download, confirm the alpha channel exists and look at the soft-edge areas by eye.
- Keep transparency in PNG or WEBP, and add any background color later in your design tool.




Top comments (0)