How do you get the width and height of an SVG picture in PHP?
Asked Answered
A

6

27

I tried to use getimagesize() on an SVG file, but it failed.

I know that SVG is “Scalable Vector Graphics”, but I find that Google Chrome’s “Review elements” can perfectly get the dimensions of an SVG picture, so I suspect that this is also possible in PHP.

If it is difficult to get the dimensions, is there any way to judge whether an SVG picture is vertical or horizontal?

Acrimony answered 30/6, 2011 at 8:49 Comment(0)
E
20

The thing is: SVG images don't have a "size" in the sense you are probably thinking of. On the other hand, they DO have a height-to-width ratio.

This ratio can usually be found in the viewBox attribute.

If, on the other hand, the viewBox attribute is not present on the root SVG element, the image ratio is highly nontrivial to determine.

Edit:

Side note: The reason Chrome gives you perfect coordinates isn't necessarily because it looks at the SVG to determine size; it could very well be a simple result of it setting the size.

Although the SVG element does have height and width attributes, these might not be specified as pixels, but any of a number of units, so they aren't necessarily a lot of help.

Exterminate answered 30/6, 2011 at 8:56 Comment(10)
@Williham Totland, I have read the viewbox, but it seems viewbox should also set the Dimensions manually, not automatic. how to transfer a SVG to viewbox xml file? it should maintain the image aspect ratio. Thanks.Acrimony
@Williham Totland, @Brian, sorry, I still not know how to use it. as viewbox example, if I have know the width="500" height="300" I can get it easily. But the real situation is I do not know it. I just know it's url http://upload.wikimedia.org/wikipedia/commons/6/6c/Cog-scripted-svg.svgAcrimony
@cj333: This particular example is trivial: Take the viewBox contents, split on space, subtract the first term from the third term to get X size, and the second term from the fourth term to get Y size.Exterminate
@Williham Totland, I'm not sure if it is trivial. It has also width and height attributes, and at least in FF 3.6 those width and height are used, i.e., size of displayed image is rather 70x100 than 350x500.Gangway
@binaryLV: As I said up in the answer; height and width are relatively irrelevant for SVG images, that's what the "S" is for. And parsing the width and height attributes can be decidedly nontrivial, as they may be specified in any number of weird units, including cm or even (shudder) inches.Exterminate
@Williham Totland, while SVG is scalable, there is (or may be) some base (or default) size of image. "Scalable" does not mean that image does not have a size, it just means that it can be scaled up or down without losing quality. If it did not have any size, there would be no reason to have viewBox, width or height attributes - it would be enough with single ratio attribute that holds value in 16:9 or 1.77 format.Gangway
@binaryLV: That's actually exactly what the viewBox does. It specifies a ratio, while also defining the coordinate space, which is handy. Width and height are just suggestions, or indications of scale, and using both is somewhat redundant.Exterminate
@Williham Totland, while redundant, that's what they are for. Also, take a look at "W3C Proposed Recommendation" about viewBox (you already gave the link), there is an example of single SVG with the same height, but different width - they are rendered differently, one is 300px wide, another is 150px wide (as specified in width attribute). To be honest, after taking a closer look at viewBox, it does not seem to specify ratio of rendered result in any way.Gangway
@binaryLV: viewBox is for the size of the image. width et. al. is for the size of the presentation, and don't strictly speaking belong in the SVG spec, IMO. In any case, my point is that using both width and height is redundant.Exterminate
$svgfile = simplexml_load_file($imageFileName); list($x_start, $y_start, $x_end, $y_end) = explode(' ', $svgfile['viewBox']);Roger
S
19

An SVG is simply an XML file, so the GD libs will not be of any help!

You should simply be able to parse the XML file to get such properties.

$xml = '
<svg width="500" height="300" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">

<rect x="90" y="10"
    width="400" height="280"
    style="fill: rgb(255,255,255); stroke: rgb(0,0,0); stroke-width: 1; " />
</svg>';

$xmlget = simplexml_load_string($xml);
$xmlattributes = $xmlget->attributes();
$width = (string) $xmlattributes->width; 
$height = (string) $xmlattributes->height;
print_r($width);
print_r($height);

The values need to be cast or they will return an object.

Sash answered 30/6, 2011 at 8:57 Comment(3)
how to do that? use simplexml_load_file(filename.svg) ? ThanksAcrimony
There you go :) - edited answer. Yeah obviously get from file, just done string XML to show it works.Sash
Btw, as Williham Totland mentioned, these may not be guaranteed to be pixels unless you're in control of the SVG files and are sure of things.Sash
J
17

Regarding dimensions there are basically three different types of SVG images:

  1. Fixed dimensions: Images that have width and height attributes. Chrome can show these dimensions perfectly and converts the specified units to pixels.

  2. Proportional dimensions: SVG images with a viewBox attribute. Chrome shows the size of such images maximized to 300x150. So an image with a 16:9 ratio is shown as 267x150.

  3. No dimensions: SVG images without width, height and viewBox. Chrome (and other browsers as well) use a default size of 300x150 for such images.

It is possible to do get the dimensions with PHP by reading the contents of the SVG image with PHPs DOM extension and applying the rules from above. I wrote the PHP library contao/imagine-svg that does exactly that and can be used as follows:

$size = (new Contao\ImagineSvg\Imagine)
    ->open('/path/to/image.svg')
    ->getSize();
echo $size->getWidth();
echo $size->getHeight();

If you don’t want to rely on a third party library, you can look at the source code of the getSize() method to see how the library determines the dimensions.

Januarius answered 26/2, 2018 at 17:51 Comment(0)
K
7

I had the same question as I could not find an answer, invent and resolved as follows:

<?php
    $svgfile = simplexml_load_file("svgimage.svg");
    $width = substr($svgfile["width"],0,-2);
    $height = substr($svgfile["height"],0,-2);
?>

Note that the SVG file I used was created in Adobe Illustrator. So, the SVG code of the image starts as follows:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 width="400px" height="738px" viewBox="0 0 400 738" enable-background="new 0 0 400 738" xml:space="preserve">
...

Thanks to this, I could get width and height values.

And I use substr because $svgfile[width] returns the value with "px" suffix. I could also use viewBox value and split it to get the values.

Greetings from Santiago, Chile

Kissiah answered 16/4, 2014 at 4:43 Comment(4)
$svgfile = simplexml_load_file($imageFileName); list($x_start, $y_start, $x_end, $y_end) = explode(' ', $svgfile['viewBox']);Roger
I like this solution but I already saw svg files with width=100% and height=100%, might be considered.Coprophilia
Solution to remove any alphanumeric signs in height and width ("px", "%", etc.): $svgwidth = preg_replace("/[^0-9,.]/", "", $svgfile[width]); $svgheight = preg_replace("/[^0-9,.]/", "", $svgfile[height]);Coprophilia
@UjjwalSingh the viewBox attribute might use a space or a comma to separate the four numbers developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBoxBesse
L
2

Here's a quick and dirty hack to check the viewbox size with regex. It works in most cases but do see the other answers to get an idea of its limitations.

preg_match("#viewbox=[\"']\d* \d* (\d*) (\d*)#i", file_get_contents('file.svg'), $d);
$width = $d[1];
$height = $d[2];
Last answered 26/7, 2018 at 19:23 Comment(1)
doesn't work with viewBox values that have decimals (totally valid). You can change both (\d*) to (\d*+(\.?+\d*)) to fix this. $height is on position 3 then.Henri
H
1

with simplexml_load_file

$svgXML = simplexml_load_file($imgUri);
list($originX, $originY, $relWidth, $relHeight) = explode(' ', $svgXML['viewBox']);

with preg_match regex (this one does for int and float values in viewBow values)

preg_match("#viewbox=[\"']\d* \d* (\d*+(\.?+\d*)) (\d*+(\.?+\d*))#i", file_get_contents($imgUri), $d);
$relWidth = (float) $d[1];
$relHeight = (float) $d[3];
Henri answered 29/1, 2020 at 23:23 Comment(2)
The viewBox attribute might use a space or a comma to separate the four numbers developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBoxBesse
@Besse good point. I have never seen one using comma in the wild but totally valid I guess. Can anyone fix my regex?Henri

© 2022 - 2024 — McMap. All rights reserved.