Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a SVG file that contains at least one embedded JPG/PNG image inside. I want to extract the JPG/PNG images from that SVG file and save them on disk.

I'm adding the inkscape tag as it is the program I use to edit SVG files, but I also accept solutions using other tools.

share|improve this question
1  
If nothing else, Python could probably do it with some custom glue using lxml and PIL (or equivalent). –  Keith Jun 21 '11 at 7:13
    
@Keith, indeed, I've just written a Python script to solve this question. It uses the built-in xml.etree library. –  Denilson Sá Dec 3 '13 at 23:35
add comment

5 Answers

My own solution (or... workaround):

  1. Select the image in Inkscape
  2. Open the built-in XML Editor (Shift+Ctrl+X)
  3. Select the xlink:href attribute, which will contain the image as data: URI
  4. Copy the entire data: URI
  5. Paste that data: URI into a browser, and save it from there.

Alternatively, I can open the SVG file in any text editor, locate the data: URI and copy it from there.

Although this solution works, it's kinda cumbersome and I'd love to learn a better one.

share|improve this answer
    
+1 - I exported a 3.5 MB image using this method which took a while but worked. Somehow the "Extract Image" function did not work for me. –  Martin Feb 15 '12 at 9:31
    
Please see also a command-line Python script for this purpose. –  Denilson Sá Mar 31 at 20:37
add comment

There's a better solution instead:

go to Extensions -> Images -> Extract Image..., there you can save selected raster image as a file. However this extension works weird and somehow works rather slowly (but perfectly well).

Another note: this extension is cumbersome and dies silently on vary large images. Also, with large number of raster images it can spike memory usage of inkscape to horrendous levels (like 3GB after only a handful of images extracted).

Because I've got about 20 svg files with about 70 raster images in them each, each image at least 1MB in size, I needed a different solution. After a short check using Denilson Sá tip I devised the following php script, that extracts images from svg files:

#!/usr/bin/env php
<?php

$svgs = glob('*.svg');

$existing = array();

foreach ($svgs as $svg){
    mkdir("./{$svg}.images");
    $lines = file($svg);
    $img = 0;
    foreach ($lines as $line){
        if (preg_match('%xlink:href="data:([a-z0-9-/]+);base64,([^"]+)"%i', $line, $regs)) {
            $type = $regs[1];
            $data = $regs[2];
            $md5 = md5($data);
            if (!in_array($md5, $existing)) {
                $data = str_replace(' ', "\r\n", $data);
                $data = base64_decode($data);
                $type = explode('/', $type);
                $save = "./{$svg}.images/{$img}.{$type[1]}";
                file_put_contents($save, $data);
                $img++;
                $existing[] = $md5;
            }
        } else {
            $result = "";
        }
    }
}

echo count($existing);

This way I can get all the images I want, and md5 saves me from getting repeated images.

I bet there must be another way that is a lot simpler, but it's up to inkscape devs to do it better.

share|improve this answer
    
Note: Your script only supports a single data: URL per line, and does not support newlines inside the href attribute (inkscape adds them for data URLs, and the base64 spec even mandates that lines should not be longer than 76 chars). Nice script for a quick hack, but it does not work with all kinds of SVG. –  Denilson Sá Dec 1 '13 at 2:16
add comment

As yet another workaround, you can save as PDF, then open that document.

Uncheck "embed images", and bingo, all the pngs/jpegs will be spewed out into your home directory.

Messy, but quicker than goofing about with the data: URL.

share|improve this answer
add comment
up vote 2 down vote accepted

Finally, years later, I've written a script to correctly extract all images from an SVG file, using a proper XML library to parse the SVG code.

http://bitbucket.org/denilsonsa/small_scripts/src/tip/extract_embedded_images_from_svg.py

This script is written for Python 2.7 but should be quite easy to convert to Python 3. Even better, about 50 lines can be deleted after conversion to Python 3.4, due to the new features introduced in that version.

share|improve this answer
add comment

Open your file in Inkscape and select the bitmap that you wish to export. Click File->Export Bitmap (Ctrl+Shift+E) and it should export only the selected bitmap.

share|improve this answer
    
I don't like this solution because it will re-encode the image. I would prefer a solution that extracts the image in its original format. –  Denilson Sá Dec 1 '13 at 0:21
1  
Yes, it seems like Inkscape re-encodes the image but it saves PNG images by default. So I am assuming that the re-encoding is at least lossless. –  Chris Dec 2 '13 at 17:10
1  
Well, not really. The embedded image might have had transformations (scaling, rotation…), might have been clipped, or even something else I'm not aware. Inkscape will certainly export the selected object after applying all these transformations, which means this solution is not exactly lossless. –  Denilson Sá Dec 3 '13 at 23:39
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.