I am sending a string representation of an SVG file to the server and using Imagick to turn this into a jpeg in the following manner:
$image = stripslashes($_POST['json']);
$filename = $_POST['filename'];
$unique = time();
$im = new Imagick();
$im->readImageBlob($image);
$im->setImageFormat("jpeg");
$im->writeImage('../photos/' . $type . '/humourised_' . $unique . $filename);
$im->clear();
$im->destroy();
However I wish to resize the SVG prior to rasterizing it so the the resulting image is larger than the dimensions specified within the SVG file.
I modified my code to the following:
$image = stripslashes($_POST['json']);
$filename = $_POST['filename'];
$unique = time();
$im = new Imagick();
$im->readImageBlob($image);
$res = $im->getImageResolution();
$x_ratio = $res['x'] / $im->getImageWidth();
$y_ratio = $res['y'] / $im->getImageHeight();
$im->removeImage();
$im->setResolution($width_in_pixels * $x_ratio, $height_in_pixels * $y_ratio);
$im->readImageBlob($image);
$im->setImageFormat("jpeg");
$im->writeImage('../photos/' . $type . '/humourised_' . $unique . $filename);
$im->clear();
$im->destroy();
This code should work out the resolution and resize the SVG accordingly. It works perfectly if the SVG canvas and it's elements have 'percentage' based widths, however it doesn't appear to work with elements defined in 'px'. Which is unfortunately a requirement.
A typical SVG string that will be sent to the server looks like this:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
<svg id="tempsvg" style="overflow: hidden; position: relative;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="333" version="1.1" height="444">
<image transform="matrix(1,0,0,1,0,0)" preserveAspectRatio="none" x="0" y="0" width="333" height="444" xlink:href="http://www.songbanc.com/assets/embed/photos/full/133578615720079914224f9e7aad9ac871.jpg"></image>
<image transform="matrix(1,0,0,1,0,0)" preserveAspectRatio="none" x="85.5" y="114" width="50" height="38" xlink:href="http://www.songbanc.com/assets/embed/humourise/elements/thumb/thumb_lips4.png"></image>
<path transform="matrix(1,0,0,1,0,0)" fill="none" stroke="#000" d="M110.5,133L140.5,133" stroke-dasharray="- " opacity="0.5"></path>
<circle transform="matrix(1,0,0,1,0,0)" cx="140.5" cy="133" r="5" fill="#000" stroke="#000"></circle>
<path transform="matrix(1,0,0,1,0,0)" fill="none" stroke="#000" d="M110.5,133L110.5,155.8" stroke-dasharray="- " opacity="0.5"></path>
<circle transform="matrix(1,0,0,1,0,0)" cx="110.5" cy="155.8" r="5" fill="#000" stroke="#000"></circle>
<circle transform="matrix(1,0,0,1,0,0)" cx="110.5" cy="133" r="5" fill="#000" stroke="#000"></circle>
</svg>
As you can see the elements that make up this SVG has pixel definition widths and heights (using percentages is unfortunately not an option for this application)
Is there any way around this? Or any other method of converting an SVG to png and rendering it at a given size without loss of quality.
Thanks.
EDIT: Although I never actually managed to find a perfect solution. Instead I ended sending the SVG data as json, looping through it server side and scaling the pixels to the intended height.
Then, after much trial and error I realised that imagemagick had issues wih the standard SVG transform/rotate commands, throwing any manipulated elements out of whack. I ended up switching too 'inkscape' to render the resulting SVG as a rasterised image. And all is well. I'm still digging into a potential formulatic solution to offset the differences that imagemagick makes. If I have any success I will update this question again.
See Question&Answers more detail:
os