如何使用 PHP 为图像添加阴影?

发布于 2024-12-02 11:38:18 字数 1112 浏览 0 评论 0原文

我正在寻找一种使用 PHP 向图像添加阴影的方法。在您回答或投票结束之前:我希望使用 CSS 或 HTML 来做到这一点。我想生成一个图像文件。这不是这个问题的重复< /a> 也不是这个

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

It's an image!

我想生成以下图像:

这是一张图像,带有阴影!


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

It's some Photoshop settings!

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

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

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

I am looking for a way to add a drop shadow to an image using PHP. Before you answer or vote to close: I am not looking to do this using CSS or HTML. I want to generate an image file. This is not a duplicate of this question nor this one.

I am looking for a very specific effect. For example, given this input image:

It's an image!

I want to produce the following image:

It's an image, with a drop shadow!


TL;DR: This image above was generated using Photoshop's Drop Shadow effect. I want a look very similar to that. For reference, here's the settings our design team used. Ideally, I'd have similar control in my code for angle, distance, opacity, etc:

It's some Photoshop settings!

I have full access to our debian-linus-based servers, so any GD or ImageMagick solution will work. As will any FOSS linux software solution, although I'd prefer a way to do it with IM or GD as those are already installed and don't require new software to be installed.

The shadow must be able to be placed on a transparent, non-rectangular PNG!

I'm asking the question mainly because the scripts and solutions I have found on the web either only produce rectangular shadows, look like total poo, or just plain don't work at all.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

因为看清所以看轻 2024-12-09 11:38:18

只是为了它的地狱(我知道它已被回答并接受):几个月前,为了回答图形设计 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);

?>

Just for the hell of it (I know it was answered and accepted): a few months ago, in response to a question on graphic design stackexchange about recovering a mask from a PNG where the source file was lost I slapped together something which uses PHP GD functions to extract the alpha channel from a transparent PNG. As Joe in a comment mentioned above, you can use the alpha channel as the drop shadow, merely offset it by x and y pixels, and then apply an image convolution blur filter to it, then copymerge the original on top. Following code is probably SLOW and proof of concept, but it is a start and it is in PHP as you originally requested.

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

?>
泪是无色的血 2024-12-09 11:38:18

实际上这可以通过 image magick 的转换来完成,不需要 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 percent-opacity{xsigma}{+-}x{+-}y{%}

结果

Actually this can be done with image magick's convert, no need for GD library:

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

you can play a little with the shadow parameter.

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

result

贪恋 2024-12-09 11:38:18

如果不构建完整的边缘检测器算法和大量的处理开销,您将无法在 PHP 中执行此操作。考虑使用 GIMP 和一些 script-fu,并让它为您完成艰苦的工作。

You're not going to be able to do this in PHP without building in a full edge-detector algorithm and significant processing overhead. Look into using GIMP with some script-fu, and let it do the hard work for you.

半夏半凉 2024-12-09 11:38:18

我采纳了 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;
}

I used Marc B's advice, and called upon The GIMP to do this for me. If anyone else cares, here's the code I used:

/**
 * 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;
}
下壹個目標 2024-12-09 11:38:18

您可以使用 PHP GD 图像处理库

这里是有关如何添加阴影效果的教程。但是,如果这不符合您的需求,我确信谷歌搜索“PHP GD Drop Shadow”就能解决问题。

You can use PHPs GD Image Processing Libraries

Here is a tutorial on how to add the shadow effect. However if this doesn't fit your needs i'm sure googling "PHP GD Drop Shadow" will do the trick.

策马西风 2024-12-09 11:38:18

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

我不知道Python,或任何有关它的东西,但大概是这个< em>算法可以帮助您或其他遇到这个问题的人。

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

This answer doesn't provide a Python solution, but it does give the generic algorithm required.

i don't know Python, or anything about it, but presumably this algorithm can help you, or someone else stumbling across this question.

Note: Strictly speaking this should be a comment, but i really wanted to be able to show the images.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文