Spaces:
Paused
Paused
Download uploads.py from internlm/Intern-Decision: direct link, hf CLI and curl.
- Browser
- Download file 4.18 kB
-
https://huggingface.co/spaces/internlm/Intern-Decision/resolve/main/uploads.py
- Command line
-
hf download hf://spaces/internlm/Intern-Decision/uploads.py
-
curl -L -o uploads.py https://huggingface.co/spaces/internlm/Intern-Decision/resolve/main/uploads.py
4.18 kB
| """Validate browser image bytes and create request-scoped, private image files.""" | |
| import base64 | |
| import binascii | |
| import io | |
| import shutil | |
| import tempfile | |
| import warnings | |
| from pathlib import Path | |
| from PIL import Image, ImageOps, UnidentifiedImageError | |
| MAX_UPLOAD_BYTES = 12 * 1024 * 1024 | |
| MAX_UPLOAD_TOTAL = 32 * 1024 * 1024 | |
| MAX_IMAGES = 8 | |
| MAX_IMAGE_PIXELS = 16_000_000 | |
| FORMATS = {"image/jpeg": "JPEG", "image/png": "PNG", "image/webp": "WEBP", "image/gif": "GIF"} | |
| def materialize_images(request): | |
| images = request.get("images", []) | |
| if not isinstance(images, list) or len(images) > MAX_IMAGES: | |
| raise ValueError("images must be a list of at most 8 uploaded files.") | |
| if not images: | |
| return request, None | |
| # mkdtemp creates a private directory; client filenames never become paths. | |
| directory = Path(tempfile.mkdtemp(prefix="interndecision-upload-")) | |
| paths, total, normalized_total = [], 0, 0 | |
| try: | |
| for index, item in enumerate(images): | |
| if not isinstance(item, dict) or not isinstance(item.get("data"), str): | |
| raise ValueError("Upload image bytes; local paths and remote URLs are not accepted.") | |
| data = item["data"] | |
| if len(data) > 4 * ((MAX_UPLOAD_BYTES + 2) // 3) + 128: | |
| raise ValueError("Each image is limited to 12 MB.") | |
| if data.startswith("data:"): | |
| header, separator, encoded = data.partition(",") | |
| if not separator or not header.endswith(";base64"): | |
| raise ValueError("Images must use base64 data URLs.") | |
| content_type = header[5:].split(";")[0].lower() | |
| else: | |
| encoded, content_type = data, str(item.get("type", "")).lower() | |
| if content_type not in FORMATS: | |
| raise ValueError("Supported image formats: JPEG, PNG, WebP and static GIF.") | |
| try: | |
| payload = base64.b64decode(encoded, validate=True) | |
| except (ValueError, binascii.Error) as exc: | |
| raise ValueError("Invalid image base64.") from exc | |
| if not payload or len(payload) > MAX_UPLOAD_BYTES: | |
| raise ValueError("Each image must be between 1 byte and 12 MB.") | |
| total += len(payload) | |
| if total > MAX_UPLOAD_TOTAL: | |
| raise ValueError("Combined image upload is limited to 32 MB.") | |
| try: | |
| with warnings.catch_warnings(): | |
| warnings.simplefilter("error", Image.DecompressionBombWarning) | |
| with Image.open(io.BytesIO(payload)) as source: | |
| if source.format != FORMATS[content_type]: | |
| raise ValueError("Image content does not match its declared format.") | |
| if source.width * source.height > MAX_IMAGE_PIXELS: | |
| raise ValueError("Each image is limited to 16 million pixels.") | |
| if getattr(source, "n_frames", 1) != 1: | |
| raise ValueError("Animated images are not supported; upload a still image.") | |
| source.load() | |
| # Apply camera orientation, strip metadata and preserve pixel resolution. | |
| image = ImageOps.exif_transpose(source).convert("RGB") | |
| image.info.clear() | |
| path = directory / f"{index:02d}.png" | |
| image.save(path, format="PNG") | |
| image.close() | |
| except ( | |
| UnidentifiedImageError, | |
| OSError, | |
| Image.DecompressionBombError, | |
| Image.DecompressionBombWarning, | |
| ) as exc: | |
| raise ValueError("Invalid, incomplete or oversized image.") from exc | |
| normalized_total += path.stat().st_size | |
| if normalized_total > MAX_UPLOAD_TOTAL: | |
| raise ValueError("Decoded images exceed 32 MB; upload smaller images.") | |
| paths.append(str(path)) | |
| return {**request, "images": paths}, directory | |
| except BaseException: | |
| shutil.rmtree(directory, ignore_errors=True) | |
| raise | |