I’ve read a range of Questions and web articles but seem to be up against a brick wall. I have reduced my problem to a very simple SVG file, containing a single image. When converted from PHP via imagick, the image is rendered blank, but from the command line using the same rsvg engine it renders fine.
This project has worked like a charm on my local Fedora dev machine, only when moving to production on Centos have I had this trouble.
Environment: Centos 6.2 server, PHP 5.6.36 using php-fpm, Imagick module version 3.4.3 using ImageMagick library version 6.7.8-9 2016-06-16
Note: my apache server does not jail or chroot the file system at all, so all normal path references should work fine, e.g. it writes to a log file in the web root using an absolute path name without problem.
$ identify -list format | grep -i svg
MSVG SVG rw+ ImageMagick's own SVG internal renderer
SVG SVG rw+ Scalable Vector Graphics (RSVG 2.39.0)
SVGZ SVG rw+ Compressed Scalable Vector Graphics (RSVG 2.39.0)
$ identify -list delegate | grep -i svg
cdr => "uniconvertor" "%i" "%o.svg"; mv "%o.svg" "%o"
dot => "dot" -Tsvg "%i" -o "%o"
svg => "rsvg-convert" -o "%o" "%i"
So I believe the format ‘SVG’ indicates it will use RSVG for the conversion from PHP.
My SVG (saved from Inkscape):
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="620mm" height="640mm" viewBox="0 0 620 640" version="1.1" id="svg28" inkscape:version="0.92.3 (2405546, 2018-03-11)" sodipodi:docname="radcover-620x640b.svg">
<defs id="defs22"/>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.24748737" inkscape:cx="1386.1321" inkscape:cy="1147.0763" inkscape:document-units="mm" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="1920" inkscape:window-height="1016" inkscape:window-x="2048" inkscape:window-y="27" inkscape:window-maximized="1" inkscape:snap-global="false"/>
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,343)">
<image fill-opacity="0" stroke="none" stroke-opacity="0" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4" x="54.336063385009766" y="-280.25213623046875" width="280.0984802246094" height="175.3288116455078" preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="image.jpg" data-number="1" transform="matrix(0.98887052,-0.14877865,0.14877865,0.98887052,0.00000000,0.00000000)"/>
</g>
</svg>
My PHP code:
<?php
$widthPx = 500;
$heightPx = 500;
$outFilename = 'out.png';
$svg = file_get_contents('src.svg');
$im = new Imagick();
$im->readImageBlob('<?xml version="1.0"?>' . $svg);
$im->setImageFormat('png24');
$im->resizeImage($widthPx, $heightPx, imagick::FILTER_LANCZOS, 1);
$im->writeImage($outFilename);
echo "Done.n";
The same attempt from command line:
convert rsvg:src.svg cli.jpg
The same using rsvg-convert
(as indicated in delegates output above):
rsvg-convert src.svg -o rsvg-convert.jpg
Result: Both command line attempts, cli.jpg
and rsvg-convert.jpg
, show the image just fine. The attempt from PHP shows a blank output i.e. the <image>
element did not render.
There is no exception thrown, or error output that I can find.
I have tried:
- Make the
xlink:href
be afile://
URL with absolute path, i.e.xlink:href="file:///home/myuser/public_html/test/svg-problem/image.jpg"
- Make the
xlink:href
be afile://
URL with relative to path current directory i.e.xlink:href="file://./image.jpg"
- Make the
xlink:href
be afile://
URL with no path i.e.xlink:href="file://image.jpg"
- Force ‘RSVG’ usage with
$im->setFormat('RSVG')
.. it throws an exception withUnable to set format
. I cannot see why.
Since the conversion via PHP completes without calling setFormat
, and the formats list shows above says it will use RSVG by default, I think it’s using RSVG, even though my attempt to force RSVG format failed.
I have read that you can recompile the rsvg library to show more error output when it fails to load a file, but on my production cPanel managed server I am very loath to try recompiling anything.
Any ideas what to try next? Pulling my hair out here 🙂
2
Answers
The problem here is that I don’t know how ImageMagick uses the librsvg interface in detail. But a few things stand out in the latest librsvg doc. While the paragraphs were only added in the v2.42 doc, I think they apply also to older versions, according to what I have observed in Gnome systems.
Depending on the ImageMagick implementation, that leads to two possible solutions:
Load the SVG directly from a file with
Use the string, but set the second file argument in
Only as an aside,
$im->setFormat('RSVG')
doesn’t make any sense, since "RSVG" is only the name of the library and not a file format.I could not make it work through IMagick PHP library, but using
proc_open
leads to exactly same result as when calling from command line: