gpt4 book ai didi

php - 如何使用 Imagick/ImageMagick 调整 SVG 大小

转载 作者:行者123 更新时间:2023-12-03 01:15:41 30 4
gpt4 key购买 nike

我将 SVG 文件的字符串表示形式发送到服务器,并使用 Imagick 按以下方式将其转换为 jpeg:

$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();

但是,我希望在光栅化 SVG 之前调整其大小,以便生成的图像大于 SVG 文件中指定的尺寸。

我将代码修改为以下内容:

$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();

此代码应计算出分辨率并相应地调整 SVG 的大小。如果 SVG Canvas 及其元素具有基于“百分比”的宽度,则它可以完美工作,但它似乎不适用于“px”中定义的元素。不幸的是,这是一个要求。

将发送到服务器的典型 SVG 字符串如下所示:

<?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>

正如您所看到的,组成此 SVG 的元素具有像素定义宽度和高度(遗憾的是,此应用程序不支持使用百分比)

有什么办法可以解决这个问题吗?或者将 SVG 转换为 png 并以给定大小渲染它而不损失质量的任何其他方法。

谢谢。

编辑:尽管我从未真正找到完美的解决方案。相反,我结束了以 json 形式发送 SVG 数据,在服务器端循环并将像素缩放到预期高度。

然后,经过多次尝试和错误,我意识到 imagemagick 在标准 SVG 变换/旋转命令方面存在问题,导致任何操作的元素都出现问题。我最终切换了“inkscape”以将生成的 SVG 渲染为光栅化图像。一切都很好。我仍在挖掘潜在的公式化解决方案来抵消 imagemagick 造成的差异。如果我成功了,我会再次更新这个问题。

最佳答案

作为 php_imagick's bug 的解决方法,您可以缩放 svg 的 width=".."和 height="..":

function svgScaleHack($svg, $minWidth, $minHeight)
{
$reW = '/(.*<svg[^>]* width=")([\d.]+px)(.*)/si';
$reH = '/(.*<svg[^>]* height=")([\d.]+px)(.*)/si';
preg_match($reW, $svg, $mw);
preg_match($reH, $svg, $mh);
$width = floatval($mw[2]);
$height = floatval($mh[2]);
if (!$width || !$height) return false;

// scale to make width and height big enough
$scale = 1;
if ($width < $minWidth)
$scale = $minWidth/$width;
if ($height < $minHeight)
$scale = max($scale, ($minHeight/$height));

$width *= $scale*2;
$height *= $scale*2;

$svg = preg_replace($reW, "\${1}{$width}px\${3}", $svg);
$svg = preg_replace($reH, "\${1}{$height}px\${3}", $svg);

return $svg;
}

然后你就可以轻松创建漂亮的透明PNG!

createThumbnail('a.svg', 'a.png');

function createThumbnail($filename, $thname, $size=50)
{
$im = new Imagick();
$svgdata = file_get_contents($filename);
$svgdata = svgScaleHack($svgdata, $size, $size);

$im->setBackgroundColor(new ImagickPixel('transparent'));
$im->readImageBlob($svgdata);

$im->setImageFormat("png32");
$im->resizeImage($size, $size, imagick::FILTER_LANCZOS, 1);

file_put_contents($thname, $im->getImageBlob());
$im->clear();
$im->destroy();
}

注意:我一直在寻找一种解决方案,如何将 SVG 从最初的小尺寸重新缩放。然而 imagick::setResolution 似乎已损坏。但是,ImageMagick 库本身正在工作,因此您可以使用 exec('convert...')(出于安全原因可能会被托管提供商禁用)。

因此,要从较小的 svg 创建 50x50 的缩略图,您可以这样做:

convert -density 500 -resize 50 50 -background transparent a.svg PNG32:a.png

关于php - 如何使用 Imagick/ImageMagick 调整 SVG 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10383305/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com