0

I'm using ImageMagick 7.0.8-66 Q16 x64 on Windows 8.1 My PHP is 7.4.1 on XAMPP.

I've been running the following command successfully with exec() in PHP:

convert _temp_.jpg 
( +clone -background black -shadow 88x3+2+2 ) 
+swap -background none -layers merge 
+repage -background #eeeeee -layers flatten 
+repage -shave 3x3 
( -size 100x100 xc:#eeeeee ) 
+swap -gravity northwest -geometry +5+5 -compose over -composite output.jpg

It takes an image, resizes it to fit in a 100x100 thumbnail, and adds a drop shadow to the image over a neutral #eeeeee background canvas. It works.

I want to rewrite it to use the Imagick PHP extension, but I'm having trouble translating it. Here's how I've translated it (with annotations), which is not working:

// convert _temp_.jpg 
$im = new imagick();
$im->readImage('_temp_.jpg');

// ( +clone -background black -shadow 88x3+2+2 ) 
$im_clone = clone $im;
$im_clone->setImageBackgroundColor('black');
$im_clone->shadowImage(88, 3, 2, 2);

// +swap -background none -layers merge 
$im->setImageBackgroundColor('none');
$im->addImage($im_clone);
$im->mergeImageLayers(imagick::LAYERMETHOD_MERGE);

// +repage -background #eeeeee -layers flatten 
$im->cropImage(88, 88, +5, +5);
$im->setImagePage(88, 88, 0, 0);
$im->setImageBackgroundColor('#eeeeee');
$im->mergeImageLayers(imagick::LAYERMETHOD_FLATTEN);

// +repage -shave 3x3 
$im->cropImage(88, 88, +5, +5);
$im->setImagePage(88, 88, 0, 0);
$im->shaveImage(3, 3);

// ( -size 100x100 xc:#eeeeee )
$im_pseudo = new Imagick();
$im_pseudo->newPseudoImage(100, 100, 'xc:#eeeeee');

// +swap -gravity northwest -geometry +5+5 -compose over -composite output.jpg
$im->setImageGravity(imagick::GRAVITY_NORTHWEST);
$im->compositeImage($im_pseudo, Imagick::COMPOSITE_OVER, 5, 5);

$im->writeImage('output.jpg');

What am I missing?

Source image: Starting Image

Resulting image: Ending Image

6
  • What is not working? I would work through each step and get it working before I moved onto the next. One thing I would try changing is the ' ' to " " Commented Jan 1, 2020 at 17:01
  • I have done that. When I process just the parts corresponding to "convert temp.jpg ( +clone -background black -shadow 88x3+2+2 ) +swap -background none -layers merge ", the result is not the same. Also, using single quotes vs. doubles quotes makes no difference. Commented Jan 1, 2020 at 17:07
  • You should attach your input image and expected output image along with the result you have. Commented Jan 1, 2020 at 17:09
  • Done. See above. Commented Jan 1, 2020 at 17:22
  • Maybe you could add how it's supposed to look. Commented Jan 1, 2020 at 17:51

1 Answer 1

2

As I say if you go in steps you can see what is happening. This is from the php Imagick manual and creates the Shadow:

/* Read the image into the object */ 
$im = new Imagick( 'DOqeZ.jpg' ); 
$im->setImageFormat("png"); 

/* Make the image a little smaller, maintain aspect ratio */ 
$im->thumbnailImage( 200, null ); 

/* Clone the current object */ 
$shadow = $im->clone(); 

/* Set image background color to black 
        (this is the color of the shadow) */ 
$shadow->setImageBackgroundColor( new ImagickPixel( 'black' ) ); 

/* Create the shadow */ 
$shadow->shadowImage( 80, 3, 5, 5 ); 

/* Imagick::shadowImage only creates the shadow. 
        That is why the original image is composited over it */ 
$shadow->compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 ); 

/* Display the image */ 
$shadow->writeImage('shadow.png');

enter image description here

UPDATE: I thought I would let you see if you could do the rest

The creating the background and compositing it should work but extent should be better. I have other things to be getting on with but some updated code below for you to play with:

/* Read the image into the object */ 
$im = new Imagick( 'DOqeZ.jpg' ); 
$im->setImageFormat("png"); 

/* Make the image a little smaller, maintain aspect ratio */ 
$im->thumbnailImage( 80, null ); 

/* Clone the current object */ 
$shadow = $im->clone(); 

/* Set image background color to black 
        (this is the color of the shadow) */ 
$shadow->setImageBackgroundColor( new ImagickPixel( 'black' ) ); 

/* Create the shadow */ 
$shadow->shadowImage( 80, 3, 5, 5 ); 

/* Imagick::shadowImage only creates the shadow. 
        That is why the original image is composited over it */ 
$shadow->compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 ); 

/* Create the background image 100x100 with a background colour */
/* Gravity seems to have no effect  */
/* $shadow->setImageGravity(imagick::GRAVITY_CENTER);*/
$shadow->setImageBackgroundColor( '#eeeeee' );
$height = $shadow->getImageHeight();
$width =  $shadow->getImageWidth();
$shadow->extentImage( 100, 100, (((100 - $width)/2)*-1 ), (((100 - $height)/2)*-1 ));    

$shadow->writeImage('shadow.jpg');

enter image description here

**** Code updated to centre the image and use a hex value for the colour **** enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

I can't tell if you understand that the desired result is that the input image is resized to retain aspect ratio yet fit within (on top of) a 100x100 gray background. What you've created above is lovely, except that it's merely an image with a drop shadow. The goal of my routine (and the result it gets correctly in the command-line version) is an aspect-ratio-retained resizing of the original with a drop shadow that floats on top of a neutral gray background, hence all of the steps in my command-line procedure.
...and by "floats above a neutral gray background" I do mean that the background is part of the composite picture. Save the second image I provided above and you'll see.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.