之前处理一批图片压缩任务,发现有一些是压缩失败的,排查一下发现是动态图片任务造成的,
所以针对这种情况,我这里采用截取第一帧图像进行压缩
# -*- coding: UTF-8 -*-
import requests
from PIL import Image, ImageSequence
import io
import numpy as np
import cv2
def zip_img(image_bytes):
# 尝试以Pillow来打开图片
image = Image.open(io.BytesIO(image_bytes))
# 检查图片是否有多帧(即是否为动态的)
if hasattr(image, 'is_animated') and image.is_animated:
frames = [frame.copy() for frame in ImageSequence.Iterator(image)]
image = frames[0] # 只取第一帧
# 将Pillow图片对象转换为OpenCV的格式
image_np = np.array(image)
image = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
else:
# 不是动态图片,直接解码为OpenCV的图片对象
image_np = np.frombuffer(image_bytes, np.uint8)
image = cv2.imdecode(image_np, cv2.IMREAD_COLOR)
# 以下为原函数的压缩逻辑
h, w, c = np.shape(image)
max_size = 600
ratio = min(1, min(max_size / h, max_size / w))
compressed_image = cv2.resize(image, [int(w * ratio), int(h * ratio)])
success, encoded_image = cv2.imencode('.webp', compressed_image, [int(cv2.IMWRITE_WEBP_QUALITY), 80])
if success:
compressed_bytes = encoded_image.tobytes()
return compressed_bytes
else:
print('编码失败')
return False
# 下面是测试动图压缩效果 2.webp
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
}
# 不用这个头压缩后的图片会变黑?
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"DNT": "1", # Do Not Track Request Header
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1"
}
url = "https://images.dsw.com/is/image/DSWShoes/522080_660_ss_01"
response = requests.get(url, headers=headers)
# response = requests.get(url)
if response.status_code == 200:
with open('1.webp', 'wb') as f:
f.write(response.content)
# 压缩图片
zip_content = zip_img(response.content)
if zip_content:
with open('2.webp', 'wb') as f:
f.write(zip_content)
else:
print(f"Error fetching image: HTTP {response.status_code}")