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:
I want to produce the following image:
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:
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 b开发者_Go百科ecause 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.
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);
?>
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{%}
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.
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;
}
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.
This answer doesn't provide a Python solution, but it does give the generic algorithm required.
Taking images from an outstanding question about drop-shadows that i have, we start with an image:
convert the image to black and white:
apply a gaussian blur, and offset the image as desired:
finally overlay the original image:
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.
精彩评论