【问题标题】:How can I add a drop-shadow to an image using PHP?如何使用 PHP 为图像添加阴影?
【发布时间】:2011-11-09 10:21:30
【问题描述】:

我正在寻找一种使用 PHP 向图像添加投影的方法。在您回答或投票结束之前:我希望使用 CSS 或 HTML 来执行此操作。我想生成一个图像文件。这不是this questionthis one 的重复。

我正在寻找一种非常具体的效果。例如,给定这个输入图像:

我想制作如下图片:


TL;DR:上面这张图片是使用 Photoshop 的投影效果生成的。我想要一个非常相似的外观。作为参考,这是我们设计团队使用的设置。理想情况下,我会在我的代码中对角度、距离、不透明度等进行类似的控制:

我可以完全访问我们基于 debian-linus 的服务器,因此任何 GD 或 ImageMagick 解决方案都可以使用。与任何 FOSS linux 软件解决方案一样,尽管我更喜欢使用 IM 或 GD 的方法,因为它们已经安装并且不需要安装新软件。

阴影必须能够放置在透明的非矩形 PNG 上!

我问这个问题主要是因为我在网上找到的脚本和解决方案要么只产生矩形阴影,看起来像大便,要么根本不起作用。

【问题讨论】:

  • Photoshop 虽然比 PHP-GD 先进得多。 PHP 是一个超文本预处理器,而不是图像编辑软件。不过,我相信这在某种程度上是可能的。
  • @animuson:是的,我对 GD 不抱太大希望。我希望有另一种解决方案,例如 ImageMagick,或者,正如 Marc B 所说,GIMP

标签: php image imagemagick dropshadow


【解决方案1】:

只是为了它的地狱(我知道它已被回答并接受):几个月前,为了回答关于图形设计 stackexchange 的一个关于从源文件丢失的 PNG 恢复蒙版的问题,我拍了一些东西它使用 PHP GD 函数从透明 PNG 中提取 alpha 通道。正如 Joe 在上面提到的评论中一样,您可以将 alpha 通道用作投影,只需将其偏移 x 和 y 像素,然后对其应用图像卷积模糊过滤器,然后将原始图像复制合并到顶部。以下代码可能很慢并且是概念证明,但它只是一个开始,它是您最初要求的 PHP。

<?php

$im = imagecreatefrompng('./images/alphatest_nolayer.png');
$w = imagesx($im);
$h = imagesy($im);

$om = imagecreatetruecolor($w,$h);

for ($x = 0; $x < $w; $x++) {
    for ($y = 0; $y < $h; $y++) {
        $rgb = imagecolorat($im, $x, $y);
        $colors = imagecolorsforindex($im,  $rgb);

        $orgb = imagecolorallocate($om,$colors['alpha'],$colors['alpha'],$colors['alpha']);
        imagesetpixel($om,$x,$y,$orgb);
    }
}

header('Content-Type: image/png');
imagepng($om);

imagedestroy($om);
imagedestroy($im);

?>

【讨论】:

  • 谢谢@horatio!我认为你的答案比 rlemon 的答案要好得多,应该得到更多的支持。
  • 如何将模糊应用于 Alpha 图像?我试过 imagefilter($om, IMG_FILTER_GAUSSIAN_BLUR);但阴影看起来像是在 NES 上,因为它像乐高积木一样参差不齐。
【解决方案2】:

其实这可以通过image magick的convert来完成,不需要GD库:

<?php
    $cmd = 'convert /path/to/source.png \( +clone -background black -shadow 80x3+4+4 \) \+swap -background none -layers merge +repage /path/to/destination.png';
    exec($cmd);
?>

你可以用shadow参数玩一下。

-shadow percent-opacity{xsigma}{+-}x{+-}y{%}

【讨论】:

  • 哇,我刚刚注意到这个答案,这比我认为的 Gimp 解决方案要好。
【解决方案3】:

如果没有构建完整的边缘检测器算法和显着的处理开销,您将无法在 PHP 中执行此操作。考虑使用带有一些脚本功能的GIMP,让它为您完成艰苦的工作。

【讨论】:

  • 我不知道为什么我没有想到 GIMP!可能是一个挑战,但我准备好了。
  • 嗯?没有关于使用边缘检测的阴影。只需将图像的 Alpha 通道复制到黑色图像,应用模糊效果,然后将两个图像合成在一起(与阴影层有几个像素的偏移)。我对 PHP 图像库一无所知,但只要您可以使用通道并应用高斯模糊,阴影应该不难。
  • (对于其他发现此问题的人,this question looks like a good place to start 用于 PHP/GIMP 集成)
  • @Joe:这会在图像周围应用阴影。投影最多出现在 2 个“边缘”上。同样,OP 的问题中没有任何内容表明图像中的这些图块实际上被掩盖了。如果它是一个沼泽标准的矩形不透明图像,那么你的方法就是在图像边界之外构建一个模糊的阴影
  • @Marc,当然,如果您忘记应用偏移量。您可以通过向下和向右移动来使阴影出现在右下方——这就是阴影一直起作用的方式。并且 OP 指定了一个“透明的、非矩形 PNG”,它告诉我是的,它有一个完整的 alpha 通道。 (还有一个事实是 OP 说 Photoshop 可以提供他想要的阴影,如果图像没有 alpha,它就不能。)
【解决方案4】:

我使用了 Marc B 的建议,并呼吁 GIMP 为我做这件事。如果有人关心,这是我使用的代码:

/**
 * Call upon The GIMP to apply a dropshadow to a given image.
 * 
 * NOTE: This will overwrite the image file at $filename! Be sure to make a copy
 * of this file first if you need one.
 * 
 * @param string $filename
 * @param int $offset_x
 * @param int $offset_y
 * @param float $radius
 * @param array $color
 * @param int $opacity
 * @return type 
 * @todo Resize the canvas so there's room to apply dropshadows to images which have no whitespace around them.
 */
function apply_gimp_dropshadow($filename,$offset_x=8,$offset_y=8,$radius=15,$color=false,$opacity=40)
{
    if(!is_array($color))
        $color = array(0,0,0);
    $color = join(' ',$color);

    $gimpScript = <<<END_OF_SCHEME_CODE_OH_HOW_I_HATE_YOU_SCHEME
(define (dropshadow filename)
  (let* (
      (image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
      (drawable (car (gimp-image-get-active-layer image)))
    )
    (script-fu-drop-shadow image drawable 8 8 15 '($color) 40 FALSE)
    (set! drawable (car (gimp-image-merge-visible-layers image 0)))
    (gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)
    (gimp-image-delete image)
  )
)

(dropshadow "$filename")
(gimp-quit 0)
END_OF_SCHEME_CODE_OH_HOW_I_HATE_YOU_SCHEME;

    $descriptorspec = array(
        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    );

    $cwd = '/tmp';
    $gimp = proc_open('/usr/bin/gimp -i -b -', $descriptorspec, $pipes, $cwd);

    if (!is_resource($gimp))
        throw new Exception('Could not open a pipe to GIMP');

    fwrite($pipes[0], $gimpScript);
    fclose($pipes[0]);

    $gimpOutput = stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $gimpResult = proc_close($gimp);

    return $gimpResult;
}

【讨论】:

  • 哈哈@END_OF_SCHEME_CODE_OH_HOW_I_HATE_YOU_SCHEME
【解决方案5】:

你可以使用PHPs GD Image Processing Libraries

Here是一个添加阴影效果的教程。但是,如果这不符合您的需求,我相信谷歌搜索“PHP GD Drop Shadow”会成功。

【讨论】:

  • 这是我看到的众多之一。阴影看起来像垃圾,只是矩形。我需要比这更多的力量。
  • 遗憾的是,谷歌在这方面让我失望了。 “PHP Dropshadow (GD|ImageMagick)”的信噪比只是 waaaay 太低了。所以我在这里问天才!
  • 顺便说一句,当我用谷歌搜索那个确切的短语时,这个页面是最热门的:p
【解决方案6】:

此答案没有提供 Python 解决方案,但确实提供了所需的通用算法

我不知道 Python 或任何关于它的知识,但大概这个算法可以帮助你,或者其他人偶然发现这个问题。

注意:严格来说这应该是一个评论,但我真的希望能够展示图片。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多