Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rsvg doesn't render linked images

Tags:

svg

librsvg

I use the python rsvg bindings to render an svg image into cairo and save to file, which mostly works. But if the svg file contains a linked image, like so:

<image href="static/usrimgs/tmpDtIKpx.png" x="10" y="10" width="600px" height="400px"></image>

the image doesn't show up in the final file (the rest of the svg renders just fine). The relative path is correct based on where the script is running, but I'm guessing there's some problem with the fact that it would normally be a relative URL, not a relative filepath. How do I get around this?

like image 436
colinmarc Avatar asked Jun 02 '10 21:06

colinmarc


4 Answers

There are many factors which must be satisfied for LibRsvg to allow an image resource to be loaded. As of v2.40 these include:

  • the image must have an xlink:href attribute
  • that attribute must contain a full, valid URI
  • the scheme can be data:// or file://
  • file:// paths must be absolute
  • file:// paths must be in or below the path of the SVG source file (after any symlinks have been dereferenced)

Note that if input is passed to rsvg-convert via stdin, then no paths count as subdirectories of the input file and all file:// images will be denied.

rsvg-convert < input.svg > output.png  # images denied

rsvg-convert -o output.png input.svg  # images allowed

The code governing image URL resolution can be found in the LibRsvg source in rsvg-base.c, function _rsvg_handle_allow_load.

To add a debugging notification to rsvg-convert when image loading fails, one can append

#define G_ENABLE_DEBUG

to config.h in the source and recompile.

like image 105
Ian Mackinnon Avatar answered Nov 04 '22 15:11

Ian Mackinnon


The answer was to process the links to start with file:/// and be a full absolute path.

like image 38
colinmarc Avatar answered Nov 04 '22 16:11

colinmarc


It seems that, if the file you are including is not on the same path or under the path of the SVG file you want to convert, it will not find it. I regard this as a bug.

like image 28
reallyniceguy Avatar answered Nov 04 '22 15:11

reallyniceguy


I wanted to get librsvg image rendering working on my Mac to speed up SVG rendering. Ian Mackinnon's great answer has all the ingredients but implementing a change to the library is tricky. These steps made librsvg correctly render linked images with relative paths. I hope this saves someone some time.

First, I installed librsvg using:

brew install --build-from-source librsvg

At the time of writing, this installs version 2.40.13 and the necessary libraries to build it. I then downloaded and extracted the source archive into my home directory:

wget https://download.gnome.org/sources/librsvg/2.40/librsvg-2.40.13.tar.xz
tar jxvf librsvg-2.40.13.tar.xz
cd librsvg-2.40.13

I edited the _rsvg_handle_allow_load function in rsvg-base.c in this directory to bypass the path loading restrictions by adding this code around line 2275:

2275
2276     goto allow; // Just try and load it!
2277     

I also needed to edit the rsvg_cairo_surface_new_from_href function in rsvg-image.c and stop it loading using mime types - just replace the function like this:

55     if (mime_type) {
56         // loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, error);     // This doesn't work on my mac
57         loader = gdk_pixbuf_loader_new (); // This works
58     } else {
59         loader = gdk_pixbuf_loader_new ();
60     }

I needed to use these slightly modified commands to compile and install the modified library:

make clean
make install gdk_pixbuf_binarydir=/usr/local/Cellar/librsvg/2.40.13/lib/gdk-pixbuf-2.0/2.10.0/loaders gdk_pixbuf_moduledir=/usr/local/Cellar/librsvg/2.40.13/lib/gdk-pixbuf-2.0/2.10.0/loaders

Depending on your system, you might need to add sudo to the above commands.

Once this was done, I could render relative SVG links using the rsvg-convert command line tool that is installed with librsvg:

rsvg-convert test.svg -o test.png

I was also able to use ImageMagick to convert SVGs with relative image links to PNG files if I installed it after installing librsvg in this way:

convert test.svg test.png

This will let you test rsvg function and performance - I found it was 2-3x faster than Inkscape for my application. I recommend changing the code more intelligently if you use this in a production environment.

like image 3
Luke Stutters Avatar answered Nov 04 '22 16:11

Luke Stutters