Извлечение растровых изображений из SVG

Я создал несколько файлов SVG с помощью Inkscape, внедрил туда растровые изображения, а затем удалил исходные растровые изображения.

Теперь я хотел бы извлечь растровое изображение из SVG, чтобы вернуть исходные растровые изображения. Я могу открыть SVG в Inkscape, но копирование растрового изображения копирует его в искаженном виде, если растровое изображение не было масштабировано с сохранением соотношения сторон. Кроме того, он копирует растровое изображение целевого размера, который может быть больше или меньше исходного растрового изображения.

ИМХО, растровое изображение в SVG доступно в исходном разрешении вместе с внесенными в него изменениями (размер, поворот и т. д.).

Поэтому я ищу инструмент, который

  • извлекать растровые изображения из файлов SVG
  • имена им автоматически (image0001.jpg и подобные в порядке)
  • сделать это автоматически для нескольких файлов одновременно
  • позволяют идентифицировать исходный SVG, называя растровые изображения, похожие на SVG, или помещая их в каталоги с именами, подобными SVG и т. д.
  • работает на винде
  • бесплатно

Я не ищу самодельное решение для программирования. Я знаю, что SVG — это XML, а данные содержатся в <image>тегах в кодировке base64. Я, вероятно, сделаю это, если другие решения (протестированные и т. д.) недоступны.

Ответы (1)

Я долго не получал ответа, поэтому, наконец, я реализовал его на C#. Вы можете использовать бесплатную версию Microsoft Visual Studio 2017 Community Edition .

Он соответствует требованиям:

  • называет их автоматически: начинается с 0 и увеличивается число
  • несколько файлов одновременно: в качестве аргумента может быть передано количество файлов
  • определить исходный SVG по имени: он использует исходное имя SVG
  • работает в Windows: да
  • бесплатно: да
  • извлечение растровых изображений из файлов SVG: на данный момент это не будет работать для всех типов изображений, только для PNG.

Создайте консольное приложение и создайте 3 файла с указанным ниже содержимым.

Файл 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);
                }
            }
        }
    }
}

Файл 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);
        }
    }
}

Файл 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;
        }
    }
}