My program makes a simple chart using pygal, and outputs the chart as a URI string. I want to convert this URI into an image that I can then manipulate with pillow. I've tried decoding the string but haven't been able to make it work. The current version of my code takes the URI and converts it into bytes as I was hoping that would make conversion easier, if I don't need to do this I can remove that line.
#Pygal graphing test
import pygal
import base64
from PIL import Image
#Get number of loops needed
user_num = int(input("How many people are taking the survey?"))
print()
#Give values to colour variables
red = 0
orange = 0
yellow = 0
green = 0
blue = 0
purple = 0
#Loop getting data from user
for x in range(1,user_num + 1):
user_colour = input("What is your favourite colour?")
print()
if user_colour == "red":
red = red + 1
elif user_colour == "orange":
orange = orange + 1
elif user_colour == "yellow":
yellow = yellow + 1
elif user_colour == "green":
green = green + 1
elif user_colour == "blue":
blue = blue + 1
elif user_colour == "purple":
purple = purple + 1
#Create bar graph object
bar_chart = pygal.Bar()
#Title of graph
bar_chart.title = "Favourite Colour"
#X-Axis label
bar_chart.x_labels = ("Red", "Orange", "Yellow", "Green", "Blue", "Purple")
#Add values
bar_chart.add('Favourite Colours', [red,orange,yellow,green,blue,purple])
#Save chart
data = bar_chart.render_data_uri()
#Convert string to bytes
b = bytes(data, 'utf-8')
I was unable to make PIL.Image
read the data because the image that you are generating seems to be an SVG image and PIL does not support it. You can check the reasons here.
In order to convert SVG to PNG as described here, we can use cairosvg
:
import base64
import io
from PIL import Image
import pygal
from cairosvg import svg2png
# ... your code
# Save chart
data = bar_chart.render_data_uri()
# Remove the header placed by the URI
data = data.replace('data:image/svg+xml;charset=utf-8;base64,', '')
# Convert to bytes
data = data.encode()
# The data is encoded as base64, so we decode it.
data = base64.b64decode(data)
# Open a bytes file object
with io.BytesIO() as f:
# write the svg data as a png to file object
svg2png(bytestring=data, write_to=f)
# read the file object with PIL and display
img = Image.open(f)
img.show()
Update
I'd recommend using Anaconda to install cairosvg
in an environment. This is what I did to create the environment and install the dependencies.
$ conda create -n test python=3.5
$ source activate test
$ conda install --channel-priority -c conda-forge cairosvg
$ pip install pygal
$ python graph_testing.py # run code