rsvg doesn't render linked images

Deadly 提交于 2019-11-29 14:03:17

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.

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

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.

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!