ai_v/venv/Lib/site-packages/PIL/WmfImagePlugin.py
24024 d4b28a731a feat(admin): 添加系统通知管理及前端通知显示功能
- 新增 SystemNotification 模型,实现系统通知的数据存储
- 管理后台新增通知相关接口,支持通知的增删改查
- 用户端新增接口,获取最新激活通知并支持标记已读
- 在前端首页添加全局通知弹窗,实现通知自动轮询及已读同步
- 生成历史记录中兼容支持图片缩略图及新旧图片格式
- 优化后台图片同步逻辑,新增缩略图生成与存储
- 支持上传参考图的拖拽、粘贴、多文件上传及排序功能
- 增加购买积分页面入口及菜单项,调整菜单结构
- 日志系统由 Redis 列表迁移为有序集合,保留 30 天日志
- 优化日志页面样式,提升可读性及滚动体验
- 调整部分模板布局为自定义滚动条容器,增强视觉一致性
2026-01-12 23:29:29 +08:00

189 lines
5.2 KiB
Python

#
# The Python Imaging Library
# $Id$
#
# WMF stub codec
#
# history:
# 1996-12-14 fl Created
# 2004-02-22 fl Turned into a stub driver
# 2004-02-23 fl Added EMF support
#
# Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
# Copyright (c) Fredrik Lundh 1996.
#
# See the README file for information on usage and redistribution.
#
# WMF/EMF reference documentation:
# https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf
# http://wvware.sourceforge.net/caolan/index.html
# http://wvware.sourceforge.net/caolan/ora-wmf.html
from __future__ import annotations
from typing import IO
from . import Image, ImageFile
from ._binary import i16le as word
from ._binary import si16le as short
from ._binary import si32le as _long
_handler = None
def register_handler(handler: ImageFile.StubHandler | None) -> None:
"""
Install application-specific WMF image handler.
:param handler: Handler object.
"""
global _handler
_handler = handler
if hasattr(Image.core, "drawwmf"):
# install default handler (windows only)
class WmfHandler(ImageFile.StubHandler):
def open(self, im: ImageFile.StubImageFile) -> None:
im._mode = "RGB"
self.bbox = im.info["wmf_bbox"]
def load(self, im: ImageFile.StubImageFile) -> Image.Image:
assert im.fp is not None
im.fp.seek(0) # rewind
return Image.frombytes(
"RGB",
im.size,
Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
"raw",
"BGR",
(im.size[0] * 3 + 3) & -4,
-1,
)
register_handler(WmfHandler())
#
# --------------------------------------------------------------------
# Read WMF file
def _accept(prefix: bytes) -> bool:
return prefix.startswith((b"\xd7\xcd\xc6\x9a\x00\x00", b"\x01\x00\x00\x00"))
##
# Image plugin for Windows metafiles.
class WmfStubImageFile(ImageFile.StubImageFile):
format = "WMF"
format_description = "Windows Metafile"
def _open(self) -> None:
# check placeable header
assert self.fp is not None
s = self.fp.read(44)
if s.startswith(b"\xd7\xcd\xc6\x9a\x00\x00"):
# placeable windows metafile
# get units per inch
inch = word(s, 14)
if inch == 0:
msg = "Invalid inch"
raise ValueError(msg)
self._inch: tuple[float, float] = inch, inch
# get bounding box
x0 = short(s, 6)
y0 = short(s, 8)
x1 = short(s, 10)
y1 = short(s, 12)
# normalize size to 72 dots per inch
self.info["dpi"] = 72
size = (
(x1 - x0) * self.info["dpi"] // inch,
(y1 - y0) * self.info["dpi"] // inch,
)
self.info["wmf_bbox"] = x0, y0, x1, y1
# sanity check (standard metafile header)
if s[22:26] != b"\x01\x00\t\x00":
msg = "Unsupported WMF file format"
raise SyntaxError(msg)
elif s.startswith(b"\x01\x00\x00\x00") and s[40:44] == b" EMF":
# enhanced metafile
# get bounding box
x0 = _long(s, 8)
y0 = _long(s, 12)
x1 = _long(s, 16)
y1 = _long(s, 20)
# get frame (in 0.01 millimeter units)
frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36)
size = x1 - x0, y1 - y0
# calculate dots per inch from bbox and frame
xdpi = 2540.0 * (x1 - x0) / (frame[2] - frame[0])
ydpi = 2540.0 * (y1 - y0) / (frame[3] - frame[1])
self.info["wmf_bbox"] = x0, y0, x1, y1
if xdpi == ydpi:
self.info["dpi"] = xdpi
else:
self.info["dpi"] = xdpi, ydpi
self._inch = xdpi, ydpi
else:
msg = "Unsupported file format"
raise SyntaxError(msg)
self._mode = "RGB"
self._size = size
loader = self._load()
if loader:
loader.open(self)
def _load(self) -> ImageFile.StubHandler | None:
return _handler
def load(
self, dpi: float | tuple[float, float] | None = None
) -> Image.core.PixelAccess | None:
if dpi is not None:
self.info["dpi"] = dpi
x0, y0, x1, y1 = self.info["wmf_bbox"]
if not isinstance(dpi, tuple):
dpi = dpi, dpi
self._size = (
int((x1 - x0) * dpi[0] / self._inch[0]),
int((y1 - y0) * dpi[1] / self._inch[1]),
)
return super().load()
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
msg = "WMF save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename)
#
# --------------------------------------------------------------------
# Registry stuff
Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept)
Image.register_save(WmfStubImageFile.format, _save)
Image.register_extensions(WmfStubImageFile.format, [".wmf", ".emf"])