【问题标题】:Save image on RAM and work on it using ImageMagick将图像保存在 RAM 上并使用 ImageMagick 处理它
【发布时间】:2017-10-31 18:47:39
【问题描述】:

我正在开发一个项目,客户可以通过将不同的图层(图像)合并为单个图像来创建动态图像,然后将生成的图像显示给客户端。目前我的代码是这样的

$output = uniqid().'.jpg';
exec('convert -size 600x800 xc:white '.$output);
$layers = array(//array of about hundreds of PNG images);
foreach($layers as $key => $singleLayer)
{
    $layerIs = $singleLayer['image'];
    $positionsXY = explode(',', $singleLayer['xy']);
    exec('composite -geometry  +'.$positionsXY[0].'+'.$positionsXY[1].' '.$layerIs.' '.$output.' '.$output);
}
$base64 = base64_encode(file_get_contents($output));
unlink($output);
return 'data:image/jpeg;base64,'.$base64;

在我上面的代码中,我正在生成一个白色背景图像,然后在其上合并多个 PNG 图像,这些图像超过 100 个。同时每次合并单个图层时都会保存此图像,然后将最终图像输出到客户端删除生成的图像后。这一切都需要大约 15 秒来完成。

所以,我的问题是,如果 ImageMagick 有一个选项可以让我将图像保存在内存上而不是保存在硬盘上,这反过来又可以加快我的处理速度?

虽然我找到了这个http://www.imagemagick.org/discourse-server/viewtopic.php?t=20295,但我不太明白我该如何实现它。

【问题讨论】:

  • 您可以尝试使用image magick的readImageBlob函数:php.net/manual/en/imagick.readimageblob.php并使用image magick对象的__toString方法将图像输出到一个变量中。
  • @Jite 我在 ImageMagick 中并不聪明。如果您不介意,您可以用很少的代码详细说明,以便我更好地理解它。请注意,我使用 exec() 命令来处理 ImageMagick 而不是 PHP 过程语言。因此,在其中使用变量会造成一些混乱:(
  • 我首先推荐使用 imagemagick 的 php 扩展。那可能吗?检查您的phpinfo() 并查看它是否已安装。根据答案,我会尝试给你一些进一步的解释。
  • @Jite 是的,它已安装,因为我有 VPS 并且我已经安装了它

标签: php html image-processing imagemagick gd


【解决方案1】:

在 php 中使用 ImageMagick 最简单的方法是使用 ImageMagick 扩展 & 类。我不建议使用 exec 函数。

首先,转换图像并将其存储在变量中。
你说你不习惯变量,但你的代码看起来像你,你可能只是不知道。
例如,您的 $output 是一个变量。该变量包含输出后的图像(如果成功)。

现在,我不能 100% 确定您的 layers 数组包含什么,如果它的图像或图像路径,但我希望它的路径,所以我会假设。

您的第一个exec 电话进行了转换,我认为这不是必要的,因为您没有输入,您所需要的只是我所看到的“白色图像”。
为此,请创建一个新的图像对象并创建一个具有正确大小和背景颜色的新图像:

$image = new Imagick();
$image->newImage(600, 800, "white");

然后你像往常一样遍历层,但你使用上面创建的 imagemagick 图像而不是 exec:

foreach($layers as $key => $singleLayer) {
    $layerIs = $singleLayer['image'];
    $positionsXY = explode(',', $singleLayer['xy']);
    // Each loop should load the image into a new imagemagick object, but we release it when the scope is exited.
    $layer = new IMagick($layerIs);
    $image->compositeImage($layer, Imagick::COMPOSITE_DEFAULT, $positionsXY[0], $positionsXY[1]);
}

循环完成后,$image 变量将包含合成图像,您可以根据需要返回该图像。

$image->setImageFormat('jpg');
return "data:image/jpeg;base64,{base64_encode($image)}";

注意:代码不是直接在浏览器中测试和编写的。所以可能需要重写!

【讨论】:

  • 太棒了! Jite 您的代码运行良好。但是为什么它在性能方面没有任何区别。完成处理同样需要 15 秒。
  • 我认为真正的瓶颈是加载 100 层以用于图像合成。我不确定可以优化多少,可能是通过使用更小的图像或更少的图像,但这在很大程度上取决于它们的使用方式。图像处理通常是一项繁重的工作,因此无论您如何处理它都可能需要一些时间。
  • 如果您认为答案回答了问题,请随时将其标记为正确和/或投票!
  • 嗯,你是对的 Jite。感谢您的支持。
  • 优秀的杰特。非常感谢。这真的很有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2019-06-04
  • 1970-01-01
相关资源
最近更新 更多