Page 1 of 1
Reading transparent SVG files
Posted: 2014-03-23T20:47:15-07:00
by mrsam
I am trying to read a small SVG file with a transparent background. This is what I'm doing:
Code: Select all
Magick::Image image;
image.type(Magick::TrueColorMatteType);
image.read(Magick::Geometry(width, height), filename);
auto packet=image.getConstPixels(0, 0, width, height);
Scanning all of the pixel packets I get back, each packet's opacity value is 0, making all pixels technically transparent. If I override the opacity, and make each pixel fully opaque, I'm getting the right image.
Well, more or less. A second, minor problem, is that ImageMagick is convinced that the SVG file's dimensions are 40x40:
$ identify images/default/checkbox1.svg
images/default/checkbox1.svg SVG 40x40 40x40+0+0 16-bit sRGB 1.22KB 0.000u 0:00.009
In Inkscape, this was created as a 32x32 image, and other tools, such as eog, correctly report it as a 32x32 image (and eog correctly displays the image with its transparent background).
Re: Reading transparent SVG files
Posted: 2014-03-23T22:44:24-07:00
by dlemstra
Can you add a link to your svg file or post the content in a code block?
Re: Reading transparent SVG files
Posted: 2014-03-24T03:51:41-07:00
by mrsam
Here's a couple of them. I wouldn't mind hacking the XML, if it meant getting the transparency right, but this is coming straight out of Inkscape.
Code: Select all
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="32"
height="32"
id="svg3866">
<defs
id="defs3868" />
<metadata
id="metadata3871">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<rect
width="12"
height="12"
x="10"
y="10"
id="rect3876"
style="fill:none;stroke:#4d4d4d" />
<rect
width="14"
height="14"
x="9"
y="9"
id="rect3878"
style="fill:none;stroke:#000000;stroke-opacity:1" />
<rect
width="10"
height="10"
x="11"
y="11"
id="rect3880"
style="fill:none;stroke:#000000;stroke-opacity:1" />
</g>
</svg>
Code: Select all
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="32"
height="32"
id="svg3866">
<defs
id="defs3868" />
<metadata
id="metadata3871">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<rect
width="12"
height="12"
x="10"
y="10"
id="rect3876"
style="fill:none;stroke:#4d4d4d" />
<rect
width="14"
height="14"
x="9"
y="9"
id="rect3878"
style="fill:none;stroke:#000000;stroke-opacity:1" />
<rect
width="10"
height="10"
x="11"
y="11"
id="rect3880"
style="fill:none;stroke:#000000;stroke-opacity:1" />
<path
d="M 7,12 16,20 29,1 16,16 z"
id="path3901"
style="fill:#008000;stroke:#008000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
d="m 7,13 9,8"
id="path3903"
style="fill:none;stroke:#004200;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
d="M 29,2 16,21"
id="path4413"
style="fill:none;stroke:#004200;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>
Re: Reading transparent SVG files
Posted: 2014-03-24T04:59:43-07:00
by dlemstra
You should set the image.backgroundColor to transparent before you read the image.
Which delegate are you using for SVG? With RSVG on windows I get the correct dimensions:
Code: Select all
convert -list format
SVG SVG rw+ Scalable Vector Graphics (RSVG 2.40.1)
Re: Reading transparent SVG files
Posted: 2014-03-24T05:28:30-07:00
by mrsam
So now I have:
Code: Select all
image.type(Magick::TrueColorMatteType);
image.backgroundColor(Magick::Color(0, 0, 0, 0));
After loading the image, the opacity of every pixel is still 0. It's not really that I'm not seeing the transparent background. With opacity 0, all pixels are transparent. There is one difference, though. After loading the image, the red, green, and blue components of transparent pixels are all 0. Without the backgroundColor() call, they're all QUANTUM_MAX. So, the SVG data is getting rendered into the image, but the rendered pixels remain at opacity 0.
I'm running 6.8.6.3 on Linux.
$ convert -list format | grep SVG
MSVG SVG rw+ ImageMagick's own SVG internal renderer
SVG SVG rw+ Scalable Vector Graphics (RSVG 2.37.0)
SVGZ SVG rw+ Compressed Scalable Vector Graphics (RSVG 2.37.0)
And, despite what the XML says:
$ identify images/default/checkbox2.svg
images/default/checkbox2.svg SVG 40x40 40x40+0+0 16-bit sRGB 1.76KB 0.000u 0:00.000
Do you also get the 40x40 dimensions?
Re: Reading transparent SVG files
Posted: 2014-03-24T05:38:45-07:00
by mrsam
Maybe I'm not interpreting the opacity value correctly. I thought that the pixel's opacity value of 0 means total transparency, and QUANTUM_MAX is solid color, the same way X RENDER interprets the alpha channel.
If I set backgroundColor to Color(0, 0, 0, QUANTUM_MAX), then after loading the SVG image the transparent pixels still have a QUANTUM_MAX opacity value, but the solid color pixels loaded from the SVG file have an opacity of 0. So, by doing that and subtracting each pixels opacity from QUANTUM_MAX, I end up with the correct alpha channel value. That feels wrong, though, and doesn't explain why a 32x32 image is seen as a 40x40 image. Haven't yet analyzed where the extra pixels are...
Re: Reading transparent SVG files
Posted: 2014-03-24T07:45:34-07:00
by dlemstra
My output image is 32x32, you should probably upgrade librsvg. And yes ImageMagick is handling transparency incorrectly, we will fix this in IM7.
Re: Reading transparent SVG files
Posted: 2014-03-24T16:43:50-07:00
by mrsam
Actually it turns out that I do have the updated librsvg2 2.40, it was updated after ImageMagick was built, and -list format was just reporting the old version. Rebuilding ImageMagick made it report 2.40, but resulted in no change in identity's output.
To make sure which library was getting loaded, I straced it and confirmed this. But it turns out that the first thing that was happening was the library trying to fork and exec inkscape, for the apparent purpose of converting the SVG file to PNG, before loading it.
That was failing since inkscape was not installed on that particular box; and afterwards that the incorrect size of 40x40 was getting reported back to me. After installing inkscape, identity started showing the correct size. So that answers that -- well, not really. Tried a test program using librsvg2 directly. Calling rsvg_handle_new_from_file(), followed by rsvg_handle_get_dimensions(). This was returning the correct 32x32 dimension, so librsvg2 was getting it right. The breakdown, when inkscape was not installed, was happening somewhere else.