fix: convert webp images to png before excel embedding
This commit is contained in:
parent
20d45b5f1d
commit
629a520201
@ -2,6 +2,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import mimetypes
|
||||
import re
|
||||
import ssl
|
||||
import tempfile
|
||||
@ -15,6 +17,10 @@ from typing import Iterable
|
||||
from openpyxl import load_workbook
|
||||
from openpyxl.drawing.image import Image as XLImage
|
||||
from openpyxl.utils import column_index_from_string, get_column_letter
|
||||
try:
|
||||
from PIL import Image as PILImage
|
||||
except Exception: # noqa: BLE001
|
||||
PILImage = None
|
||||
|
||||
|
||||
CONTENT_TYPE_TO_EXT = {
|
||||
@ -27,6 +33,8 @@ CONTENT_TYPE_TO_EXT = {
|
||||
}
|
||||
|
||||
SUPPORTED_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp", ".bmp", ".gif"}
|
||||
EXCEL_SAFE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".bmp", ".gif"}
|
||||
UNSAFE_OR_UNKNOWN_EXTENSIONS = {".webp", ".tif", ".tiff", ".heic", ".avif"}
|
||||
IMAGE_HINT_HEADERS = (
|
||||
"图片链接",
|
||||
"商品图片",
|
||||
@ -36,6 +44,8 @@ IMAGE_HINT_HEADERS = (
|
||||
"image url",
|
||||
"图片",
|
||||
)
|
||||
mimetypes.add_type("image/webp", ".webp", strict=True)
|
||||
mimetypes.add_type("image/webp", ".webp", strict=False)
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -235,6 +245,22 @@ def download_image(url: str, timeout: int, ssl_context):
|
||||
return data, guess_extension(url, content_type)
|
||||
|
||||
|
||||
def to_excel_safe_image(payload: bytes, extension: str) -> tuple[bytes, str]:
|
||||
ext = (extension or "").lower()
|
||||
if ext in EXCEL_SAFE_EXTENSIONS and ext not in UNSAFE_OR_UNKNOWN_EXTENSIONS:
|
||||
return payload, ext
|
||||
|
||||
if PILImage is None:
|
||||
return payload, ".png"
|
||||
|
||||
with PILImage.open(io.BytesIO(payload)) as image:
|
||||
if image.mode not in {"RGB", "RGBA"}:
|
||||
image = image.convert("RGBA")
|
||||
output = io.BytesIO()
|
||||
image.save(output, format="PNG")
|
||||
return output.getvalue(), ".png"
|
||||
|
||||
|
||||
def pixels_to_excel_width(px: int) -> float:
|
||||
return max(12.0, round((px + 12) / 7, 2))
|
||||
|
||||
@ -282,6 +308,7 @@ def process_sheet(sheet, args: argparse.Namespace, ssl_context, temp_files: list
|
||||
|
||||
try:
|
||||
payload, extension = download_image(url, args.timeout, ssl_context)
|
||||
payload, extension = to_excel_safe_image(payload, extension)
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=extension) as temp_file:
|
||||
temp_file.write(payload)
|
||||
temp_path = Path(temp_file.name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user