Inner shadow and drop shadow

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
dsmeef
Posts: 3
Joined: 2015-07-20T04:07:46-07:00
Authentication code: 1151

Inner shadow and drop shadow

Post by dsmeef »

Hi all,

I have been searching through a lot of examples, and through this forum, but I did not find any hints on how to add both an inner shadow (in black, from top to bottom) AND a drop shadow (in white, from bottom to top) to a logo image. That should give the following effect:

http://picpaste.com/embos-example-ngxfSAj5.png

I've seen the embossing function, but that is not what I want as you can see. The logo will be a user uploaded PNG file, so any script to handle the logo should not hold any hard-coded values :)

I will be using it in PHP, and am not sure if I can use the command line on the server this script will be running on, so if it can be done via PHP - that would be awesome!

Thanks in advance,
dsmeef
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Inner shadow and drop shadow

Post by snibgo »

Without seeing a before and after image, it's hard to be specific.

"-shade" will probably do what you want. See http://www.imagemagick.org/script/comma ... .php#shade and http://www.imagemagick.org/Usage/transform/#shade
snibgo's IM pages: im.snibgo.com
dsmeef
Posts: 3
Joined: 2015-07-20T04:07:46-07:00
Authentication code: 1151

Re: Inner shadow and drop shadow

Post by dsmeef »

Hi Snibgo,

The 'after' state was visible in the link, but per your request I have made a before/after image, to make clear what I want to achieve:

http://picpaste.com/example-mNAd4vv0.png

In the before part you can see a logo on the left, and the background image where it will be placed.
In the after part you can see the logo AFTER the effect placed on top of the background (they remain two seperate layers, the background can be changed by the user)

Hope this makes it more clear what I want to do.

I have looked into the http://php.net/manual/en/imagick.shadeimage.php shading of images, but that did not really provide the effect I was looking for I am afraid, or I was doing things wrongly (which will not surprise me, as I am not good at image scripting :))
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Inner shadow and drop shadow

Post by snibgo »

Sorry, I wasn't clear. Please provide at least two image files:

1. All input images. This seems to need two inputs: a logo, and a background. Please provide them both.

2. An output mage.

These should be image files, not screenshots.
snibgo's IM pages: im.snibgo.com
Bonzo
Posts: 2971
Joined: 2006-05-20T08:08:19-07:00
Location: Cambridge, England

Re: Inner shadow and drop shadow

Post by Bonzo »

Probably not quite what you want but you can try this:

Code: Select all

<?php  
// Get the size of the image 
$size = getimagesize("$input14"); 

// Size for watermark - scaled to fit the image 
$width = $size[0]*.9; 
$height = $size[0]*.25; 

// Create an image with the text 
$cmd = "-size {$width}x{$height} -background none -font Utopia-bold ". 
" -fill white -gravity center caption:\"Copyright of Rubblewebs\" ". 
" -shade 240x40"; 

exec("convert $cmd font.png "); 

// Add the text image to the photo 
exec("composite -watermark 30% -gravity south font.png $input14 embossed.png"); 

// Delete the tempory image 
unlink ('font.png'); ?> 
The code can probably be improved as it is an old example on my website.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Inner shadow and drop shadow

Post by fmw42 »

Please always post your IM version and platform. Syntax may be different on Windows and Unix
dsmeef
Posts: 3
Joined: 2015-07-20T04:07:46-07:00
Authentication code: 1151

Re: Inner shadow and drop shadow

Post by dsmeef »

Snibgo was indeed pointing me in the right direction! It was not the function that was doing strange things, it was me (ofcourse) who did not supply the right input :) I had tried that function, but it gave really weird results. Turned out you had to input a black/grey/white (alpha map) image, and not just the uploaded image itself..

After some tweaks, converting the image to black/white, and using that as input > I did get a good result. But with a background, and no longer transparent - so I wrote another piece of script that removed the background. And after that, the result is very nice! Thanks for all the help :)

For future reference, I'll post the entire function that does what I need in PHP:

Code: Select all

		public function createEmbossedLogo($imagePath, $embossedFilePath) {
 			// initialize Imagick and load the image
			$imagick = new \Imagick(realpath($imagePath));

			// make sure we are using PNG, so we can use the alpha channel
			$imagick->setImageFormat('png');

			// resize the logo, so we do not have to process too many pixels
			$imagick->resizeImage(200, null,\Imagick::FILTER_CATROM,1);

			// if the image does not have any margin around the content,
			// the shade would be cut off at the sides,
			// so we add an invisible border of 5 pixels, to add some margin
			$imagick->borderImage('rgba(255,0,0,0)',5, 5);

			// now we have to convert the image to a black/white image, using only the alpha channel
			// and use the alpha channel value as the R/G/B channel values

			// load the pixels of the image
			$imageIterator = $imagick->getPixelIterator();
			foreach ($imageIterator as $row => $pixels) { /* Loop through pixel rows */
				foreach ($pixels as $column => $pixel) { /* Loop through the pixels in the row (columns) */
					/** @var $pixel \ImagickPixel */
					$nor_color = $pixel->getColor(true); //normalized color

					// the alpha channel will be 0 if it is completely invisible and 1 if visibile
					// but can be any value in between 0-1
					// by using the alpha channel as the white/grey/black value, we create an alpha map
					$alpha = $nor_color['a'];
					$rgbValue = $alpha*255;
					$pixel->setColor('rgba('.$rgbValue.','.$rgbValue.','.$rgbValue.',1');
				}

				$imageIterator->syncIterator(); /* Sync the iterator, this is important to do on each iteration */
			}

			// add the shading, the first parameter makes sure that all the 'to be removed' pixels
			// are the same color, so we can find them in the next loop through all pixels
			// they would otherwise be black, one of the colors we do need to keep in the result
			$imagick->shadeImage(true,270,45);

			// the shadeImage function will make all the pixels grey that should be transparent
			// so we loop over all the pixels in the image once again to remove them
			$imageIterator = $imagick->getPixelIterator();
			$colorFound = false;
			$colorRange = 10;
			foreach ($imageIterator as $row => $pixels) { /* Loop through pixel rows */
				foreach ($pixels as $column => $pixel) { /* Loop through the pixels in the row (columns) */
					/** @var $pixel \ImagickPixel */
					$color = $pixel->getColor(); //normalized color
					if (!$colorFound) {
						// since added some margin around the image, we can take the first pixel
						// of the top left corner, and use it as the color to make transparent
						// and since the image is in black/white, we only need one 'color' channel
						$colorFound = array();
						$colorFound['r'] = $color['r'];
					}

					// the default alpha for pixels to keep is 1
					$alpha = 1;

					// see if the color of this pixel is close to that of the 'color to be deleted'
					// if so, we will not totally delete it, but change the alpha channel accordingly
					$diff = abs($color['r']-$colorFound['r']);
					if ($diff<=$colorRange) {
						// set alpha value for this pixel, based on the difference from the removed color
						$alpha = $diff / $colorRange;
					}

					// the entire opacity of the image has to brought down, to make the image a bit 'softer'
					$alpha *= 0.35;

					// this pixel matches the 'to be removed' color, so we set it to a new value with alpha 0
					$pixel->setColor('rgba('.$color['r'].','.$color['g'].','.$color['b'].','.$alpha.')');
				}

				$imageIterator->syncIterator(); /* Sync the iterator, this is important to do on each iteration */
			}

			// remove any excess margins that are not needed
			$imagick->trimImage(0);

			// store the image
			$imagick->writeImage($embossedFilePath);
		}
Post Reply