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
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import io
|
||||||
|
import mimetypes
|
||||||
import re
|
import re
|
||||||
import ssl
|
import ssl
|
||||||
import tempfile
|
import tempfile
|
||||||
@ -15,6 +17,10 @@ from typing import Iterable
|
|||||||
from openpyxl import load_workbook
|
from openpyxl import load_workbook
|
||||||
from openpyxl.drawing.image import Image as XLImage
|
from openpyxl.drawing.image import Image as XLImage
|
||||||
from openpyxl.utils import column_index_from_string, get_column_letter
|
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 = {
|
CONTENT_TYPE_TO_EXT = {
|
||||||
@ -27,6 +33,8 @@ CONTENT_TYPE_TO_EXT = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SUPPORTED_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp", ".bmp", ".gif"}
|
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 = (
|
IMAGE_HINT_HEADERS = (
|
||||||
"图片链接",
|
"图片链接",
|
||||||
"商品图片",
|
"商品图片",
|
||||||
@ -36,6 +44,8 @@ IMAGE_HINT_HEADERS = (
|
|||||||
"image url",
|
"image url",
|
||||||
"图片",
|
"图片",
|
||||||
)
|
)
|
||||||
|
mimetypes.add_type("image/webp", ".webp", strict=True)
|
||||||
|
mimetypes.add_type("image/webp", ".webp", strict=False)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -235,6 +245,22 @@ def download_image(url: str, timeout: int, ssl_context):
|
|||||||
return data, guess_extension(url, content_type)
|
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:
|
def pixels_to_excel_width(px: int) -> float:
|
||||||
return max(12.0, round((px + 12) / 7, 2))
|
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:
|
try:
|
||||||
payload, extension = download_image(url, args.timeout, ssl_context)
|
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:
|
with tempfile.NamedTemporaryFile(delete=False, suffix=extension) as temp_file:
|
||||||
temp_file.write(payload)
|
temp_file.write(payload)
|
||||||
temp_path = Path(temp_file.name)
|
temp_path = Path(temp_file.name)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user