如何在Python中将Pygal生成的图片URI转换为Pillow可处理的图像
我来帮你搞定这个把Pygal生成的data URI转换成Pillow可处理图像的问题~你的代码目前只是把整个URI字符串转成了字节,但没正确提取和解码里面的图像数据,这就是为啥失败啦。下面给你拆解问题,再附上完整的解决代码:
问题根源
Pygal的render_data_uri()返回的是data URI格式的字符串,长这样:data:image/svg+xml;base64,xxxxxxxxx。逗号后面的那串才是经过base64编码的SVG图像数据,我们得先把这部分抠出来解码,才能得到Pillow能认的内容。另外要提一句:Pillow原生处理SVG需要额外依赖,所以给你准备了两种方案,按需选就行。
方案1:直接用Pillow加载SVG(需环境支持)
先确保你的环境能让Pillow处理SVG:
- Linux:先装系统依赖
sudo apt-get install librsvg2-dev,然后重新装Pillow:pip install --upgrade pillow - macOS:用Homebrew装
brew install librsvg,再重装Pillow - Windows:可以找预编译的Pillow包(比如Unofficial Windows Binaries的版本),或者直接用方案2
修正后的完整代码:
import pygal import base64 from PIL import Image from io import BytesIO # 获取调查人数 user_num = int(input("How many people are taking the survey?")) print() # 用字典存颜色计数,比单独变量简洁多了 colour_counts = {"red":0, "orange":0, "yellow":0, "green":0, "blue":0, "purple":0} # 收集用户输入的颜色 for x in range(1, user_num + 1): # 转小写,兼容用户输入的大小写(比如Red/RED都能识别) user_colour = input("What is your favourite colour?").lower() print() if user_colour in colour_counts: colour_counts[user_colour] += 1 # 生成柱状图 bar_chart = pygal.Bar() bar_chart.title = "Favourite Colour" bar_chart.x_labels = ("Red", "Orange", "Yellow", "Green", "Blue", "Purple") bar_chart.add('Favourite Colours', list(colour_counts.values())) # 获取data URI并处理 data_uri = bar_chart.render_data_uri() # 提取base64编码部分(把逗号前面的前缀去掉) base64_data = data_uri.split(',')[1] # 解码base64得到SVG的字节数据 svg_bytes = base64.b64decode(base64_data) # 把字节转成BytesIO对象,Pillow才能读 svg_io = BytesIO(svg_bytes) # 用Pillow打开SVG并操作 try: img = Image.open(svg_io) # 可以直接显示图像 img.show() # 也可以保存成PNG文件 img.save("favourite_colours.png") except Exception as e: print(f"加载SVG失败啦:{e},试试下面的方案2吧")
方案2:用svglib转成PIL图像(兼容性拉满)
要是装Pillow的SVG依赖太麻烦,就用svglib库,它专门干SVG转PIL图像的活儿:
- 先装库:
pip install svglib pillow - 把代码里的图像处理部分换成下面这段:
# ...前面的图表生成、data URI处理和方案1完全一样... from svglib.svglib import svg2rlg from reportlab.graphics import renderPM # 把SVG字节转成BytesIO,传给svglib drawing = svg2rlg(BytesIO(svg_bytes)) # 渲染成PIL图像 img = renderPM.drawToPIL(drawing) # 显示或保存图像 img.show() img.save("favourite_colours.png")
额外小优化
我把你原来的单个颜色变量改成字典了,代码更简洁,还加了.lower()处理用户输入,不管用户输Red、RED还是red都能正确计数~
这样操作后,你就能顺利把Pygal的图表转换成Pillow能处理的图像啦!
内容的提问来源于stack exchange,提问作者Infinity
相关产品推荐
相关产品推荐

