How to export Highchart graph to PNG and embed into a PDF file

TL;DR – Though a little tedious, it’s possible. You can export your Highchart graph to a PNG file and then you can embed it in a PDF file for an export – this is without using the built in Highchart export mechanism – which I found a little bit too heavy to configure. If you are interested, read on.

Set up I am using

  • CodeIgniter as my PHP framework
  • Highchart graph rendered via Javascript (or Coffeescript)

Goal

Export the Highchart graph as a separate PNG file and then embed that into a PDF file via the server.

Why are you not using Highchart’s own export feature?

Read through its documentation. I found its setup rather too involved. I need to use another backend setup using their JAR-based export module. It was too much. I wanted a flexible and simpler way to creating an image of my Highchart.

Step 1 – Preparing a canvas element

The highchart graph is drawn as a SVG element. In order to ultimately convert this to a PNG format, we first need to “move” this SVG element into HTML5 Canvas element. The easiest way to do this is by using Canvg plugin. Download the plugin and install it as instructed on the plugin website.

Once that’s done, we can do this conversion process from SVG to Canvas via following:

canvg(document.getElementById('canvas'), $(".highcharts-container").html() )        
canvas = document.getElementById("canvas")
img = canvas.toDataURL("image/png")

Here, we are moving the SVG DOM element of the highchart graph into a canvas DIV element in our view. So I am assuming the following HTML elements exist on your page.

<div id="canvas"></div>
<div class=".highchart-container">.... highchart graph svg element would be here</div>

The Highchart graph is by default wrapped in the “.highchart-container” class.

Step 2 – Pass the file name to the server

The PNG file would now be in “img” variable. You can test it by

$("body").append("<img src=" + img + "/>")

If you print it out, you would also realise that the img is a very long string, rather than an actual file name. This is the “representation” of the SVG graph image, which we just converted by using Canvg. (Spec is here)

You can now pass that “img” to the server – but make sure you use “POST” since the length of img can be quite lengthy (depends on the complexity of your graph).

Step 3 – Saving the PNG as a file

On the server-side (in my case, PHP, CodeIgniter), we can  now save this PNG as a file. You can do this by the following:

$encodeData = str_replace('[removed]', 'data:image/png;base64, ', $this->input->post('img'));
$encodeData = substr($encodeData, strpos($encodeData, ',') + 1);
$decodeData = base64_decode($encodeData);
$handle = fopen('chart.png', 'w');
fwrite($handle, $decodeData);
fclose($handle);

Above basically processes the image representation into a file with the correct “decoding/encoding”. The first line may not be necessary in your case, but in my project the data format information was removed (possibly because of CI security feature?), so I just replace it back. Make sure you have an empty “chart.png” file available with the right permission. Or you can create a new file by “fopen(‘chart.png’, ‘x+’)” with the correct permission. Once above steps run successfully then voila, you will have your PNG file.

Step 4 – Embed into your PDF

In my case, I used DOM_PDF library. The CodeIgniter-version is also available here.  It’s a pretty simple process and since you already have the image file, it’s just a matter of embedding the image into your final HTML via “<img src=’image.png’ />”.

Conclusion

Of course, there are other ways to tackle this issue, but from all the options, for me this seemed to work the best. I needed a simple(r) yet flexible way to generate a PNG and embed in PDF, without using the Highchart’s export module. Love to hear your opinions and let me know if you found any mistakes in the above steps!

2 thoughts on “How to export Highchart graph to PNG and embed into a PDF file

  1. Great post. I followed everything and I am getting a chart.png image, but it is empty, only 747 b.

    I am not posting the svg string, so I guess I didn’t follow everything!, I hoping I can do this just passing the string.

    Or is this the problem?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>