deeplook / svglib

Read SVG files and convert them to other formats.
GNU Lesser General Public License v3.0
311 stars 80 forks source link

Can't load SVG with gradient unless flattened #336

Closed eddex closed 2 years ago

eddex commented 2 years ago

Description When I try to open an svg file that contains a gradient, the svg2rlg method throws an error saying Can't handle color: url(#_Linear1).

Steps to reproduce

from svglib.svglib import svg2rlg
g1 = svg2rlg("./gradient.svg")
<svg width="100%" height="100%" viewBox="0 0 420 142" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
    <rect x="0" y="0" width="420" height="142" style="fill:url(#_Linear1);" />
    <defs>
        <linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(420,0,0,420,0,142)">
            <stop offset="0" style="stop-color:#ebebeb;stop-opacity:1" />
            <stop offset="1" style="stop-color:#a3a3a3;stop-opacity:1" />
        </linearGradient>
    </defs>
</svg>

gradient gradient.svg

Workaround

When I flatten the svg during export, thus replacing the <linearGradient> element with an <image> element, the svg can be loaded:

<svg width="100%" height="100%" viewBox="0 0 420 142" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
    <use xlink:href="#_Image1" x="0" y="0" width="420px" height="142px"/>
    <defs>
        <image id="_Image1" width="420px" height="142px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAACOCAYAAAB+DHzRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACVklEQVR4nO3VQQqEMBQFQcf7nzCXiXuFwTAMtFK1DPlv258xxtxO5rw8fbX6/+7N23fv/n/a7uqNXbu//rf7zN3zzb58BQB/IEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQIEgAJAgSAAmCBECCIAGQcAAfsnY3lsW7GAAAAABJRU5ErkJggg=="/>
    </defs>
</svg>
github-actions[bot] commented 2 years ago

Thank you for raising your first issue! Your help to improve svglib is much appreciated!

claudep commented 2 years ago

Can't handle color is a warning, not an error. Is that a problem? svglib (and ReportLab) doesn't support gradients, that's a documented limitation.

eddex commented 2 years ago

The problem is that the data is missing and I can't use the loaded svg. But if this is a known limitation, it's ok. I can flatten the gradient into an image as described above.

claudep commented 2 years ago

Unfortunately that's the right workaround, waiting for gradient support in ReportLab.

cbeytas commented 2 years ago

Can we detect when this happens so we know the resulting drawing is incorrect? Often I get a blank or very deformed image. I'd like to raise an exception if this happens so I can substitute a default image.

DrakeGladiator commented 1 year ago

I wrote a script to remove the gradients in the svg file. It certainly deserves some polishing, and there is no color averaging implemented yet, but it works such that you still have a vectorized graphic.

https://github.com/DrakeGladiator/SVGGradientRemover

claudep commented 1 year ago

Interesting, thanks. I guess something like that could be integrated in svglib (storing linear def node ids while iterating nodes, and replacing url() by a fill color when appropriate. Exercise left for the reader :smile: