Misc scribbles

Creating high-resolution screenshots (of jbrowse) with phantomJS


Generating screenshots that are of high quality can be a great benefit for things like science publications. PhantomJS is great for automating this in a reproducible way. While many HTML pages can be rendered in high resolution without modification, HTML5 canvas apps need special considerations (see this previous post on the topic).

One of the key things that we noticed when we developed the high resolution canvas rendering (see above link) is that the "devicePixelRatio" can increase based on the browser's zoom level, and it can also take fractional values. This was a difficult problem, to make rendering 100% consistent under all devicePixelRatio values, so we created a config parameter called highResolutionMode to accept arbitrary resolutions.

Later, we learned about PhantomJS and how it can be used for creating screenshots, it was clear that our design for the settings arbitrary scaling factors for the HTML5 canvas was very helpful, as we can set highResolutionMode=4 along with the phantomJS variable page.zoomFactor=4, which matches the resolutions and creates high-res canvas screenshots.

One of the reasons that this is important is that it doesn't look like PhantomJS allows "devicePixelRatio" to be emulated, so the page.zoomFactor doesn't necessarily set the devicePixelRatio to a higher number, so being able to set the the arbitrary high resolution canvas scalings ourselves is a good solution. Reference: issue open Jan 2013 https://github.com/ariya/phantomjs/issues/10964 and we are now in Aug 2015

Here are some examples of the rendering process.


  1. Rendering screenshots to PNG

    phantomjs rasterize.js "http://localhost/jbrowse/?data=sample_data/json/volvox&tracklist=0" output.png "3800px*1600px" 2

    Figure 1. A basic image output from phantomJS. It uses a zoomFactor=2 on the command line to match highResolutionMode=2 in the config file. `

  2. Rendering screenshots to PDF. In JBrowse, this requires PhantomJS 2.0. Also see footnote.

    phantomjs rasterize.js "http://localhost/jbrowse/?data=sample_data/json/volvox&tracklist=0" output.pdf "16in*8in"

    Dropbox PDF 906kb

    Figure 2. Outputted PDF from phantomJS. This still requires setting the configuration such as highResolutionMode=2 too


In the future, we want to consider adding highResolutionMode to be specified via the URL so that it doesn't need to be changed manually, although, setting highResolutionMode=2 by default is not a bad strategy.


I used the following patch for rasterize.js to help "fill out" the page space in PDF renderings (otherwise, it is a square page, not super pretty for a widescreen app). I guess rasterize.js is really just a template and not meant to be super multi-purposed, so this custom modification helps for our case.

        diff --git a/examples/rasterize.js b/examples/rasterize.js
        index b0e0f67..3b0b6e4 100644
        --- a/examples/rasterize.js
        +++ b/examples/rasterize.js
        _@@ -14,6 +14,7 @@ if (system.args.length < 3 || system.args.length > 5) {
            page.viewportSize = { width: 600, height: 600 };
            if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
                size = system.args[3].split('_');

        +       page.viewportSize.width *= parseInt(size[0])/parseInt(size[1]);
                page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }





Big improvement on font rendering