[cairo] [PATCH] Enable links to image files in SVG backend

Adrian Johnson ajohnson at redneon.com
Fri Jan 1 01:36:50 PST 2010

Alexander Shulgin wrote:
> I'm scratching my personal itch here as I writing a simple Ruby
> program to generate nice calendars.  I've used rcairo and pango and
> everything worked well except for putting photographic images into SVG
> files.  Here comes inevitable rant... ;)
> 1. I have to convert[1] images from JPEG to PNG beforehand (a bit slow)
> 2. Then load them with rcairo (slow)
> 3. And render on SVG surface (even slower)
> 4. And then I get the output file of ridiculous 10-15 megs in size
> 5. Which can be finally loaded with Inkscape (really slow again) to
> fine-tune it.

The cairo 1.9.4 development snapshot contains new API for embedding JPEG 
data in backends that support it (currently SVG, PDF, PS, and 

The cairo_surface_set_mime_data() function associates JPEG data (and 
other formats) with a surface. When a surface with mime data is used as 
a source in a backend that supports the mime data, the mime data will be 
embedded instead of the image data.

> [1] Again, I'm doing my stuff in Ruby, and I found no way to obtain
> necessary image data from JPEG file to feed to
> cairo_image_surface_create_for_data().  Using gdk-pixbuf is of no help
> as it gives BGR instead of RGB expected by cairo (or vice-versa).

If you are only using a backend that supports JPEG embedding and you 
know that no fallback images containing any part of your image will be 
used you can get away with using uninitialized image data as only the 
mime data will be used.

> I'd also would like to see something like
> cairo_placeholder_surface_create(width, height) which will create a
> surface with no image data associated--I don't need it to render to
> SVG with links to file.  Currently I'm forced to use
> cairo_image_surface_create() which still allocates height*stride
> bytes.  No problem for a desktop, but can hurt some server's memory
> footprint.

If the image data will not be used, a solution to reduce the memory 
usage would be to create a 1x1 image surface and set the JPEG mime data 
on it. When painting the surface, you would need to scale the 1x1 image 
with size of the JPEG image to get the correct size output.


     image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1);
     cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JPEG,
                                      data, len, free, data);
     cairo_scale (cr, jpeg_width, jpeg_height);
     cairo_set_source_surface (cr, image, 0, 0);
     cairo_paint (cr);

However testing this with the PDF, PS, and SVG backends shows that none 
of them work. They only work if the image size is the same size as the 
JPEG image. But that should not be hard to fix.

More information about the cairo mailing list