feat(notification): 新增图片压缩处理
- 新增 ImageUtils.compress_image_if_needed 方法,用于压缩图片大小 - 在 MAA.py 和 notification.py 中集成图片压缩功能 - 添加对不同图片格式(JPEG、PNG)的压缩支持 - 优化图片路径处理,确保压缩后图片正确发送 - 更新 requirements.txt,添加 pillow 依赖
This commit is contained in:
@@ -1999,13 +1999,34 @@ class MaaManager(QObject):
|
||||
"好羡慕~\n\nAUTO_MAA 敬上",
|
||||
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||
)
|
||||
app_path = Config.apppath
|
||||
app_path = Config.app_path
|
||||
image_path = app_path / "resources/images/notification/six_star.png"
|
||||
image_base64 = ImageUtils.get_base64_from_file(image_path)
|
||||
image_md5 = ImageUtils.calculate_md5_from_file(image_path)
|
||||
Notify.CompanyWebHookBotPushImage(
|
||||
image_base64, image_md5, user_data["Notify"]["CompanyWebHookBotUrl"]
|
||||
|
||||
# 压缩后得到的仍然是字符串路径
|
||||
final_image_path = ImageUtils.compress_image_if_needed(
|
||||
str(image_path)
|
||||
)
|
||||
# 转回Path对象,方便exists判断
|
||||
final_image_path = Path(
|
||||
final_image_path
|
||||
)
|
||||
|
||||
if final_image_path.exists():
|
||||
image_base64 = ImageUtils.get_base64_from_file(
|
||||
str(final_image_path)
|
||||
)
|
||||
image_md5 = ImageUtils.calculate_md5_from_file(
|
||||
str(final_image_path)
|
||||
)
|
||||
Notify.CompanyWebHookBotPushImage(
|
||||
image_base64,
|
||||
image_md5,
|
||||
user_data["Notify"]["CompanyWebHookBotUrl"],
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{self.name} | 图片不存在或者压缩失败,请检查图片路径是否正确"
|
||||
)
|
||||
|
||||
# 发送用户单独通知
|
||||
if user_data["Notify"]["Enabled"] and user_data["Notify"]["IfSendSixStar"]:
|
||||
@@ -2052,4 +2073,5 @@ class MaaManager(QObject):
|
||||
logger.error(
|
||||
f"{self.name} |用户CompanyWebHookBot密钥为空,无法发送用户单独的CompanyWebHookBot通知"
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
@@ -32,6 +32,7 @@ from email.header import Header
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.utils import formataddr
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
@@ -386,15 +387,25 @@ class Notification(QObject):
|
||||
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||
)
|
||||
app_path = Config.app_path
|
||||
# 拼接图片路径
|
||||
image_path = app_path / "resources/images/notification/test_notify.png"
|
||||
image_base64 = ImageUtils.get_base64_from_file(image_path)
|
||||
image_md5 = ImageUtils.calculate_md5_from_file(image_path)
|
||||
self.CompanyWebHookBotPushImage(
|
||||
image_base64,
|
||||
image_md5,
|
||||
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||
)
|
||||
|
||||
# 压缩后得到的仍然是字符串路径
|
||||
final_image_path = ImageUtils.compress_image_if_needed(str(image_path))
|
||||
# 转回Path对象,方便exists判断
|
||||
final_image_path = Path(final_image_path)
|
||||
|
||||
if final_image_path.exists():
|
||||
image_base64 = ImageUtils.get_base64_from_file(str(final_image_path))
|
||||
image_md5 = ImageUtils.calculate_md5_from_file(str(final_image_path))
|
||||
Notify.CompanyWebHookBotPushImage(
|
||||
image_base64,
|
||||
image_md5,
|
||||
Config.get(Config.notify_CompanyWebHookBotUrl),
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"通知测试 | 图片不存在或者压缩失败,请检查图片路径是否正确"
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import base64
|
||||
import hashlib
|
||||
import os
|
||||
from PIL import Image
|
||||
|
||||
class ImageUtils:
|
||||
@staticmethod
|
||||
@@ -19,3 +21,51 @@ class ImageUtils:
|
||||
"""从base64字符串计算md5"""
|
||||
image_data = base64.b64decode(base64_content)
|
||||
return hashlib.md5(image_data).hexdigest()
|
||||
|
||||
@staticmethod
|
||||
def compress_image_if_needed(image_path, max_size_mb=2):
|
||||
"""
|
||||
如果图片大于max_size_mb(默认2MB),则压缩到max_size_mb以内,
|
||||
返回压缩后文件路径(压缩文件与原图同目录,命名为xxx_compressed.xxx),
|
||||
如果不超过则返回原文件路径
|
||||
"""
|
||||
|
||||
if hasattr(Image, "Resampling"): # Pillow 9.1.0及以后
|
||||
RESAMPLE = Image.Resampling.LANCZOS
|
||||
else: # Pillow 老版本
|
||||
RESAMPLE = Image.ANTIALIAS
|
||||
|
||||
max_size = max_size_mb * 1024 * 1024
|
||||
file_size = os.path.getsize(image_path)
|
||||
if file_size <= max_size:
|
||||
return image_path # 小于2MB,直接返回原路径
|
||||
|
||||
# 只支持JPEG、PNG压缩
|
||||
file_root, file_ext = os.path.splitext(image_path)
|
||||
compressed_path = f"{file_root}_compressed{file_ext}"
|
||||
|
||||
img = Image.open(image_path)
|
||||
quality = 90 if file_ext.lower() in ['.jpg', '.jpeg'] else None
|
||||
step = 5 # 每次降低5质量或5%尺寸
|
||||
|
||||
# 如果是JPG/JPEG
|
||||
if file_ext.lower() in ['.jpg', '.jpeg']:
|
||||
while True:
|
||||
img.save(compressed_path, quality=quality, optimize=True)
|
||||
if os.path.getsize(compressed_path) <= max_size or quality <= 10:
|
||||
break
|
||||
quality -= step
|
||||
# PNG 只能调整尺寸来压缩
|
||||
elif file_ext.lower() == '.png':
|
||||
width, height = img.size
|
||||
while True:
|
||||
img.save(compressed_path, optimize=True)
|
||||
if os.path.getsize(compressed_path) <= max_size or width <= 200 or height <= 200:
|
||||
break
|
||||
width = int(width * 0.95)
|
||||
height = int(height * 0.95)
|
||||
img = img.resize((width, height), RESAMPLE)
|
||||
else:
|
||||
raise ValueError("仅支持JPG/JPEG和PNG格式图片的压缩。")
|
||||
|
||||
return compressed_path
|
||||
|
||||
@@ -9,4 +9,5 @@ pycryptodome
|
||||
requests
|
||||
markdown
|
||||
Jinja2
|
||||
nuitka
|
||||
nuitka
|
||||
pillow
|
||||
Reference in New Issue
Block a user