Как преобразовать изображение SVG в одноцветное растровое изображение?

Используя пакет NuGet SVG.NET для преобразования изображений SVG в растровые изображения в .NET, я пытаюсь изменить цвет изображения во время рендеринга.

Например. У меня есть это исходное изображение SVG:

введите здесь описание изображения

и хотите сделать это, например. как зеленое растровое изображение:

введите здесь описание изображения

(В моем сценарии все исходные изображения SVG только одноцветные).

Мой текущий неудачный код выглядит так:

var svgDoc = SvgDocument.Open<SvgDocument>(svgFilePath, null);

// Tried several things, all without any changes in the resulting bitmap:
svgDoc.Color = new SvgColourServer(Color.DarkGreen);
svgDoc.StopColor = new SvgColourServer(Color.DarkGreen);
svgDoc.Stroke = new SvgColourServer(Color.DarkGreen);
svgDoc.Fill = new SvgColourServer(Color.DarkGreen);

var bitmap = svgDoc.Draw();

Я также проверил исходный код и просмотрел его, но так и не нашел способа изменить цвет.

Мой вопрос:

Как изменить цвет во время рендеринга изображения SVG в растровое изображение с помощью SVG.NET?

(спрашиваю здесь на SO, а не только на их странице GitHub, так как кажется, что авторы не отвечают на вопросы вообще или очень редко)

Обновление 1:

Что сработало, так это следующий фрагмент:

var svgDoc = SvgDocument.Open<SvgDocument>(svgFilePath, null);

// Recursively change all nodes.
processNodes(svgDoc.Descendants(), new SvgColourServer(Color.DarkGreen));

var bitmap = svgDoc.Draw();

вместе с этой функцией:

private void processNodes(IEnumerable<SvgElement> nodes, SvgPaintServer colorServer)
{
    foreach (var node in nodes)
    {
        if (node.Fill != SvgPaintServer.None) node.Fill = colorServer;
        if (node.Color != SvgPaintServer.None) node.Color = colorServer;
        if (node.StopColor != SvgPaintServer.None) node.StopColor = colorServer;
        if (node.Stroke != SvgPaintServer.None) node.Stroke = colorServer;

        processNodes(node.Descendants(), colorServer);
    }
}

Хотя я не уверен в стоимости этой рекурсивной итерации всех узлов и в том, есть ли более быстрый способ.


person Uwe Keim    schedule 27.08.2018    source источник
comment
Что вы пробовали? Вы пытались добавить цвет к заливке?   -  person vfle    schedule 27.08.2018
comment
Мой исходный код в вопросе показывает, что я пробовал.   -  person Uwe Keim    schedule 27.08.2018


Ответы (1)


Звучит разумно, что ваша первая попытка не удалась, потому что вы установили fill и stroke только для родительского элемента <svg>, а заливка/обводка родителя не переопределяет заливку/обводку дочернего элемента. Пример:

<svg fill="green" stroke="green" xmlns="http://www.w3.org/2000/svg" width="200" height="200" >
    <g stroke="black" stroke-width="2" fill="none" >
        <path d="M90,90 v-80 a80,80 0 0,0 -80,80 z" fill="red" />
        <path d="M100,100 h-80 a80,80 0 1,0 80,-80 z" fill="gold" />
    </g>
</svg>

Одной из альтернатив вашему обновленному подходу является установка заливки/штриха с помощью CSS, потому что CSS переопределит любые атрибуты fill и stroke. Итак, если SVG.NET позволяет вам вставлять/редактировать элемент <style> в вашем SVG, вы можете сделать это:

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" >
    <style>
        * {
            fill: green;
            stroke: green;
        }
    </style>
    <g stroke="black" stroke-width="2" fill="none" >
        <path d="M90,90 v-80 a80,80 0 0,0 -80,80 z" fill="red" />
        <path d="M100,100 h-80 a80,80 0 1,0 80,-80 z" fill="gold" />
    </g>
</svg>

person Sphinxxx    schedule 27.08.2018
comment
Поддерживает ли SVG.NET CSS? Кажется, но я не совсем уверен. Спасибо за ваш ответ, я постараюсь копнуть дальше в этом направлении. - person Uwe Keim; 27.08.2018