2

I have created a few SVG files with Inkscape, embedded bitmaps there and later deleted the original bitmaps.

I'd now like to extract the bitmap from the SVGs to get the original bitmaps back. I can open the SVG in Inkscape, but copying the bitmap copies it in distorted way if the bitmap was not scaled maintaining the aspect ratio. Also, it copies the bitmap in target size, which may be larger or smaller than the original bitmap.

IMHO, the bitmap in the SVG is available in original resolution along with the modifications made to it (size, rotation etc.).

So I am looking for a tool that

  • extract bitmaps from SVG files
  • names them automatically (image0001.jpg and similar is ok)
  • do that automatically for several files at once
  • make it possible to identify the original SVG by naming the bitmaps similar to the SVG or putting them in directories named like the SVG etc.
  • works on Windows
  • is gratis

I am not looking for a do-it-yourself programming solution. I know SVG is XML and the data is contained in <image> tags, base64 encoded. I'll probably do that if no other solutions (tested etc.) are available.

1

I didn't get an answer for a long time, so finally, I implemented it in C#. You can use the free Microsoft Visual Studio 2017 Community Edition.

It matches the requirements:

  • names them automatically: starts at 0 and increases the number
  • several files at once: a number of files can be passed as argument
  • identify the original SVG by naming: it uses the original SVG name
  • works on Windows: yes
  • is gratis: yes
  • extract bitmaps from SVG files: It will not work for all image types, just PNGs for the moment.

Create a Console application and create 3 files with the content below.

File ExtractBitmapFromSvg.cs:

namespace ExtractBitmapFromSvg
{
    static class ExtractBitmapFromSvg
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                var svgFile = new SvgFile(args[i]);
                var images = svgFile.GetEmbeddedImages();
                for (var imagenumber = 0; imagenumber < images.Count; imagenumber++)
                {
                    var image = images[imagenumber];
                    image.SaveAs(args[i] + imagenumber + image.Extension);
                }
            }
        }
    }
}

File Image.cs

using System;
using System.Collections.Generic;
using System.IO;

namespace ExtractBitmapFromSvg
{
    class Image
    {
        private static readonly Dictionary<string, string> Filetypes = new Dictionary<string, string>();

        static Image()
        {
            Filetypes.Add("image/png", ".png");
        }

        internal Image(string mimeType, string base64Data)
        {
            MimeType = mimeType;
            Data = Convert.FromBase64String(base64Data);
        }

        internal string MimeType;
        internal string Extension => FindExtension(MimeType);

        private static string FindExtension(string mimeType)
        {
            return Filetypes[mimeType];
        }

        internal byte[] Data;

        public void SaveAs(string destination)
        {
            File.WriteAllBytes(destination, Data);
        }
    }
}

File SvgFile.cs:

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace ExtractBitmapFromSvg
{
    class SvgFile
    {
        private readonly XDocument xDocument;
        private const string IMAGE = "{http://www.w3.org/2000/svg}image";
        private const string HREF = "{http://www.w3.org/1999/xlink}href";
        readonly Regex regexMimeTypeAndData = new Regex("^data:(.*);base64,(.*)");

        internal SvgFile(string fileName)
        {
            xDocument = XDocument.Load(fileName);
        }

        internal List<Image> GetEmbeddedImages()
        {            
            var result = new List<Image>();
            var xElements = from svg in xDocument.Descendants(IMAGE)
                select svg.Attribute(HREF);
            foreach (var xElement in xElements)
            {
                var match = regexMimeTypeAndData.Match(xElement.Value);
                var mimeType = match.Groups[1].Value;
                var base64Data = match.Groups[2].Value;
                result.Add(new Image(mimeType, base64Data));
            }
            return result;
        }
    }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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