在Python Flask中实现在线图片URL到Blurhash编码,核心是先获取远程图片内容,再对图片进行尺寸调整和像素提取,最后调用Blurhash算法生成对应编码。整个过程不需要本地存储图片,处理完成后可直接返回编码结果给前端使用。

环境准备
首先需要安装必要的依赖库,包括Flask框架、处理HTTP请求的requests库、图片处理库Pillow,以及Blurhash的Python实现库blurhash。执行以下命令完成安装:
pip install flask requests pillow blurhash
核心实现步骤
1. 创建Flask应用并定义接口
先初始化Flask实例,定义一个接收POST请求的接口,用于接收前端传递的图片URL参数。
from flask import Flask, request, jsonify
import requests
from PIL import Image
from io import BytesIO
import blurhash
app = Flask(__name__)
@app.route('/generate_blurhash', methods=['POST'])
def generate_blurhash():
# 获取请求中的图片URL参数
data = request.get_json()
if not data or 'image_url' not in data:
return jsonify({'error': '缺少image_url参数'}), 400
image_url = data['image_url']
# 后续处理逻辑将在下面补充
return jsonify({'blurhash': '待生成'})
2. 获取远程图片内容
使用requests库发送GET请求获取图片的二进制内容,同时需要处理请求异常,比如URL无效、网络错误等情况。
try:
# 设置超时时间,避免请求长时间阻塞
response = requests.get(image_url, timeout=10)
response.raise_for_status() # 如果状态码不是200,抛出HTTPError异常
except Exception as e:
return jsonify({'error': f'获取图片失败: {str(e)}'}), 400
# 将二进制内容转为图片对象
try:
image_data = BytesIO(response.content)
img = Image.open(image_data)
except Exception as e:
return jsonify({'error': f'图片解析失败: {str(e)}'}), 400
3. 图片预处理与Blurhash生成
Blurhash算法对图片尺寸有一定要求,通常建议将图片缩放到宽度不超过100像素,保持宽高比,避免处理过大的图片导致性能问题。之后提取图片的RGB像素数据,调用blurhash.encode方法生成编码。
# 图片预处理:缩放图片,宽度设为100,高度按比例计算
max_width = 100
if img.width > max_width:
ratio = max_width / img.width
new_height = int(img.height * ratio)
img = img.resize((max_width, new_height), Image.Resampling.LANCZOS)
# 转换图片为RGB模式,避免RGBA等模式导致的问题
if img.mode != 'RGB':
img = img.convert('RGB')
# 提取像素数据,blurhash.encode需要传入图片的像素数组、宽度、高度
pixels = list(img.getdata())
width, height = img.size
# 生成Blurhash编码
blur_hash = blurhash.encode(pixels, width, height)
return jsonify({'blurhash': blur_hash})
4. 完整接口代码
将上述步骤整合后,完整的接口实现代码如下:
from flask import Flask, request, jsonify
import requests
from PIL import Image
from io import BytesIO
import blurhash
app = Flask(__name__)
@app.route('/generate_blurhash', methods=['POST'])
def generate_blurhash():
# 获取请求参数
data = request.get_json()
if not data or 'image_url' not in data:
return jsonify({'error': '缺少image_url参数'}), 400
image_url = data['image_url']
# 获取远程图片
try:
response = requests.get(image_url, timeout=10)
response.raise_for_status()
except Exception as e:
return jsonify({'error': f'获取图片失败: {str(e)}'}), 400
# 解析图片
try:
image_data = BytesIO(response.content)
img = Image.open(image_data)
except Exception as e:
return jsonify({'error': f'图片解析失败: {str(e)}'}), 400
# 图片预处理
max_width = 100
if img.width > max_width:
ratio = max_width / img.width
new_height = int(img.height * ratio)
img = img.resize((max_width, new_height), Image.Resampling.LANCZOS)
if img.mode != 'RGB':
img = img.convert('RGB')
# 生成Blurhash
pixels = list(img.getdata())
width, height = img.size
blur_hash = blurhash.encode(pixels, width, height)
return jsonify({'blurhash': blur_hash})
if __name__ == '__main__':
app.run(debug=True, port=5000)
接口测试
启动Flask应用后,可以使用curl或者Postman发送POST请求测试接口,请求示例如下:
curl -X POST http://127.0.0.1:5000/generate_blurhash
-H "Content-Type: application/json"
-d '{"image_url": "https://picsum.photos/200/300"}'
如果请求成功,会返回类似以下的响应:
{
"blurhash": "LGF5?xYk^6#M@-5c,1J5@[or[Q7M"
}
注意事项
- 远程图片URL需要支持跨域访问吗?不需要,因为是后端服务发起请求,不受浏览器跨域限制。
- 处理大尺寸图片时,建议先缩放再处理,否则会占用大量内存,影响服务性能。
- 如果图片URL是HTTP协议,部分服务器可能会拒绝请求,建议优先使用HTTPS协议的图片地址。
- 生成的Blurhash编码长度固定,前端可以直接使用该编码配合对应的Blurhash解码库渲染模糊占位图。