Page 1 of 1

Inner shadow and drop shadow

Posted: 2015-07-20T05:30:33-07:00
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

Re: Inner shadow and drop shadow

Posted: 2015-07-20T06:25:27-07:00
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

Re: Inner shadow and drop shadow

Posted: 2015-07-20T06:49:30-07:00
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 :))

Re: Inner shadow and drop shadow

Posted: 2015-07-20T07:00:59-07:00
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.

Re: Inner shadow and drop shadow

Posted: 2015-07-20T07:37:03-07:00
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.

Re: Inner shadow and drop shadow

Posted: 2015-07-20T09:04:46-07:00
by fmw42
Please always post your IM version and platform. Syntax may be different on Windows and Unix

Re: Inner shadow and drop shadow

Posted: 2015-07-21T02:49:57-07:00
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);
		}