baodan/api/insurance/poster/render_validation.py

49 lines
1.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""浏览器合成海报的文件与尺寸校验。"""
import io
from PIL import Image
from insurance.poster.format_registry import list_poster_formats
class PosterRenderValidationError(ValueError):
"""最终海报文件不符合格式契约。"""
def validate_rendered_png(image_bytes: bytes, format_id: str) -> dict:
"""完整解码 PNG并验证其真实像素尺寸。"""
format_spec = next(
(item for item in list_poster_formats() if item["id"] == format_id),
None,
)
if not format_spec:
raise PosterRenderValidationError(f"不支持的海报格式: {format_id}")
try:
with Image.open(io.BytesIO(image_bytes)) as image:
image.verify()
with Image.open(io.BytesIO(image_bytes)) as image:
image.load()
width, height = image.size
image_format = image.format
except Exception as exc:
raise PosterRenderValidationError("PNG 文件无法解码或已经损坏") from exc
if image_format != "PNG":
raise PosterRenderValidationError("最终海报必须是 PNG 格式")
expected = format_spec["output"]
if width != expected["width"]:
raise PosterRenderValidationError(
f"海报宽度不匹配,应为 {expected['width']}px实际为 {width}px"
)
if expected["height"] is not None and height != expected["height"]:
raise PosterRenderValidationError(
f"海报尺寸不匹配,应为 {expected['width']}×{expected['height']}"
f"实际为 {width}×{height}"
)
if expected["height"] is None and not 1 <= height <= 32767:
raise PosterRenderValidationError("长图高度超出浏览器安全范围")
return {"width": width, "height": height, "format": image_format}