0

I have set up a new Windows machine where I would like to rasterize a bunch of SVG documents to PNG images. I have simplified Ariya Hidayat's rasterize script to this :

var page = require('webpage').create(),
    system = require('system'),
    fs = require('fs'),
    svgPath, output;

if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: rasterize.js URL output');
    phantom.exit(1);
} else {
    svgPath = fs.workingDirectory + '/' + system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 600, height: 120 };

    if (!fs.isFile(svgPath)) {
        console.log(svgPath+' does not exist');
        phantom.exit(1);
    }

    page.onLoadFinished = function() {
        page.render(output);
        console.log('thumbnail created');
        phantom.exit(0);
    };

    page.open(svgPath);
}

And here is how I call the script : bin\phantomjs js/headless/rasterize.js "simple.svg" "simple.svg.png" 2>&1

simple.svg contains this data :

<svg width="110" height="60" id="simple" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <rect x="10" y="10" height="50" width="100" style="stroke:#ff0000; fill: #0000ff"/>
</svg>

Once the script has been executed (without error), simple.svg.png is rendered like this : simple.svg.png

This is really strange, and I'm pretty sure the thumbnail was correctly generated on the previous machine. Why does it just render the SVG's source code ?

Bruno Pérel
  • 575
  • 6
  • 21
  • 1
    Test your phatomjs with their stock SVG `phantomjs rasterize.js http://ariya.github.io/svg/tiger.svg tiger.png`, if that works then try it without `2>&1` which redirects the stderr to stdout. – Alvin K. Jul 15 '15 at 05:20
  • Thanks for the suggestion. It works indeed when using an HTTP-based (and not file-based) SVG. I solved the problem by creating a local server so that the SVG content type could be handled when renderning it. – Bruno Pérel Jul 15 '15 at 08:30

2 Answers2

0

It looks like the issue is that I load the SVG from the file system, and PhantomJS has no way of knowing that I want to show the SVG as an image and not as a text. The solution was to instantiate a local server where I can load the SVG from the file system and configure the content type to make it be actually rendered like you would expect an SVG to be :

var page = require('webpage').create(),
    server = require('webserver').create(),
    system = require('system'),
    fs = require('fs'),
    svgPath, output;

var serverUrl = '127.0.0.1:8888';

server.listen(serverUrl, function (request, response) {
    var cleanedUrl = request.url
        .replace(/\//g, fs.separator)
        .replace(/\?.*$/g, '');
    var pagePath = fs.workingDirectory + cleanedUrl;
    response.statusCode = 200;
    response.setHeader("Content-Type", "image/svg+xml");
    try {
        response.write(fs.read(pagePath));
    } catch(err) {
        console.error('Error while reading ' + cleanedUrl + '(requested URL : '+request.url+')');
        response.close();
        phantom.exit(1);
    }
    response.close();
});

if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: rasterize.js URL output');
    phantom.exit(1);
} else {
    svgPath = fs.workingDirectory + '/' + system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 600, height: 120 };

    if (!fs.isFile(svgPath)) {
        console.log(svgPath+' does not exist');
        phantom.exit(1);
    }

    page.onLoadFinished = function() {
        page.render(output);
        console.log('thumbnail created');
        server.close();
        phantom.exit(0);
    };

    page.open('http://'+serverUrl+'/'+system.args[1]);
}
Bruno Pérel
  • 575
  • 6
  • 21
0

I got the same result when executing the conversion via Java's ProcesBuilder while it worked fine when launching it via cmdline. I've tried to prefix the source file with file:// protocol, e.g. file:///D:/phantomjs/test.svg and it works as expected in my case.

Jan Tosovsky
  • 498
  • 5
  • 18