Removing red eye in PHP using Imagick - php

I'm trying to adapt the script available here [http://www.fmwconcepts.com/imagemagick/redeye/index.php][1] in PHP using the API version of Imagick.
Actually, the selection is done in jQuery then passed to the following script to draw the selection.
Here's my code so far:
<?php
extract($_POST);
// Load the original image
$image = new Imagick($path);
// Duplicate and desaturate the original image
$image2 = clone $image;
$image2->modulateImage(15, 0, 100);
// Create the mask on which the selection will be drawn
$image3 = clone $image;
$image3->colorfloodfillimage(new ImagickPixel('white'), 18, new ImagickPixel('white'), 0, 1);
foreach ($redeye as $selection){
try{
$draw = new ImagickDraw();
$draw->setstrokewidth(0);
$draw->setstrokecolor(new ImagickPixel('black'));
$draw->setFillColor(new ImagickPixel( 'black' ));
$draw->setfillalpha(1);
$draw->ellipse( $selection['ox'], $selection['oy'], $selection['rx'], $selection['ry'], 0, 360 );
$image3->drawImage($draw);
} catch (ImagickException $ie){
echo $ie->getMessage();
}
}
?>
I know very little about image processing and don't know how to merge the 3 layers.
I don't really understand the code of the convert function when merging the layer.
Any help would be greatly appreciated!
EDIT:
convert $tmpA1 $tmpA2 $tmpA3 -compose over -composite $tmpA2
As I understand this should be written like the following using the API:
$image2->compositeImage($image3,Imagick::COMPOSITE_OVER, 0, 0);
$image2->compositeImage($image2,Imagick::COMPOSITE_OVER, 0, 0);
$image2->compositeImage($image,Imagick::COMPOSITE_OVER, 0, 0);
Then
convert $tmpA2 \( $tmpA1 -modulate 100,0,100 \) $tmpA4 -compose over -composite $outfile
Should be written like that:
$image->modulateImage(100, 0, 100);
$image->compositeImage($image,Imagick::COMPOSITE_OVER,0, 0);
$image->compositeImage($image2,Imagick::COMPOSITE_OVER,0, 0);
But I don't understand this part:
convert $tmpA3 ( +clone -morphology close disk:$rad $dilation ) -compose difference -composite -auto-level -negate -threshold 0 -negate $tmpA4

Related

PHP Imagick: problem converting ImageMagick command-line code

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:
Resulting image:
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');
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');
**** Code updated to centre the image and use a hex value for the colour ****

Convert Imagemagick command to php imagick

I need to convert the ImageMagick Command to PHP Imagick. I have tried a few combinations but nothing worked as expected. The command creates a line with pointy edges and gradient at the edges
The command is:
convert -size 300x1 xc:red \
\( -size 1x300 gradient: -rotate 90 -solarize 50% -level 0x50% -white-threshold 50% +write grad.png \) \
-alpha off -compose copy_opacity -composite red_grad.png`
thanks to #fmw42 for this command
I have tried the following code:
$line = new Imagick();
$line->newPseudoImage(300,1,'xc:red');
$shadow = new Imagick();
$shadow->newPseudoImage(1, 300, 'gradient:red-white');
$shadow->rotateImage('transparent', 90);
$shadow->solarizeImage(50);
$shadow->levelImage(0,50,50);
$shadow->whiteThresholdImage('white');
$shadow->setImageCompose(0);
$shadow->writeImage('grad.png');
$shadow->compositeImage($line, Imagick::COMPOSITE_MATHEMATICS, 0, 0);
Please point out where am I going wrong
My best guess at translation would be the following. However, this is untested and I do not know Imagick well.
$redline = new Imagick();
$redline->newPseudoImage(300,1,'xc:red');
$grad = new Imagick();
$grad->newPseudoImage(1, 300, 'gradient:black-white');
$grad->rotateImage('white', 90);
$grad->solarizeImage(50*Imagick::getQuantumRange/100);
$grad->levelImage(0,1,50*Imagick::getQuantumRange/100);
$grad->whiteThresholdImage(50*Imagick::getQuantumRange/100);
$redline->compositeImage($grad, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$redline->writeImage("redline.png");
With a few tweaks, #fmw42 answer worked for me. The correct solution is given below
$redline = new Imagick();
$redline->newPseudoImage(1100,3,'xc:'.$chipColourPixel->getColorAsString());
$grad = new Imagick();
$grad->newPseudoImage(3, 900, 'gradient:black-white');
$grad->rotateImage('white', 90);
$grad->solarizeImage((int)ceil(50*Imagick::QUANTUM_RANGE/100));
$grad->levelImage(0,1,50*Imagick::QUANTUM_RANGE/100);
$redline->compositeImage($grad, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$redline->writeImage("redline.png");

How to make specified area of an image transparent with Imagick?

I want to make a part of an image transparent, I tried the code below, even tried many constants as COMPOSITE_DSTOUT, but all didn't work, does anyone know how to?
$fooImage->newImage(256, 256, new ImagickPixel('transparent'));
$Image->compositeImage($fooImage, Imagick::COMPOSITE_DSTOUT, $offsetX, offsetY);
I tested the code below, just got yellow with black, not transparent:
$width = 256;
$height = 256;
$image = new Imagick();
$image->newImage($width, $height, new ImagickPixel('yellow'));
$x = 50;
$y = 100;
$fooWidth = 100;
$fooHeight = 60;
//Create a new transparent image of the same size
$mask = new Imagick();
$mask->newImage($width, $height, new ImagickPixel('none'));
$mask->setImageFormat('png');
//Draw onto the new image the areas you want to be transparent in the original
$draw = new ImagickDraw();
$draw->setFillColor('black');
$draw->rectangle($x, $y, $x + $fooWidth, $y + $fooHeight);
$mask->drawImage($draw);
//Composite the images
$image->compositeImage($mask, Imagick::COMPOSITE_DSTOUT, 0, 0,
Imagick::CHANNEL_ALPHA);
$image->setImageFormat('png');
$image->writeImage($path);
Got black inside yellow, not transparent in yellow
You need to make a black and white mask image the size of your input (white where you want it to be opaque and black where you want it to be transparent). Then use the equivalent of -compose copyopacity -composite to put the mask into the alpha channel of the image. Sorry, I do not code Imagick.
Here is an example using ImageMagick command line syntax:
Input:
convert logo.jpg \( -size 640x480 xc:white -size 200x200 xc:black -geometry +200+100 -compose over -composite \) +geometry -alpha off -compose copy_opacity -composite result.png
You can see it is transparent by compositing it over another image (in this case a checkerboard).
convert ( -size 640x480 pattern:checkerboard ) result.png -compose over -composite result2.jpg
Do you try \Imagick::COMPOSITE_COPYOPACITY ?
Because that's probably the right one.

padding images using php imagick

I need to create square images with no image loss. I found a tool that does the job as a bash script using ImageMagick but can never seem to be able to do it with php Imagick.
The script I found is called squareup from http://www.fmwconcepts.com/imagemagick/squareup/index.php
My code looks like this currently:
$image = new Imagick($srcimage);
$image->setCompressionQuality(100);
if ($image->getImageHeight() <= $image->getImageWidth())
$image->resizeImage($maxsize, 0, Imagick::FILTER_MITCHELL, 1);
else
$image->resizeImage(0, $maxsize, Imagick::FILTER_MITCHELL, 1);
$h=$image->getImageHeight();
$w=$image->getimagewidth();
$hlarge=0;
$wlarge=0;
if ($w>$h) {
$diff=intval(($w-$h)/2);
$wlarge=1;
$h=$w;
} else {
$diff=intval(($h-$w)/2);
$w=$h;
$hlarge=1;
}
$newimage = new Imagick();
if ($image->getImageColorspace() == Imagick::COLORSPACE_CMYK) {
$fg="cmyk(0,0,0,0)";
$fg_pixel=new ImagickPixel($fg);
$newimage->newImage($w, $h, $fg_pixel);
$newimage->setImageColorspace(Imagick::COLORSPACE_CMYK);
} else {
$newimage->newImage($w, $h, new ImagickPixel('#ffffff'));
}
$newimage->compositeImage($image,\Imagick::COMPOSITE_OVER,0,0);
$newimage->setImageCompression(Imagick::COMPRESSION_JPEG);
$newimage->setImageCompressionQuality(100);
$newimage->stripImage();
$newimage->writeImage($contactimage);
$newimage->destroy();
$image->destroy();
The simplest way to do pad to square or crop to square in ImageMagick 6 is as follows:
Input:
size=`convert hatching_orig.jpg -format "%[fx:max(w,h)]" info:`
convert hatching_orig.jpg -background red -gravity center -extent ${size}x${size} hatching_pad.jpg
size=`convert hatching_orig.jpg -format "%[fx:min(w,h)]" info:`
convert hatching_orig.jpg -background red -gravity center -extent ${size}x${size} hatching_crop.jpg
Same command, but different size variable.
In IM 7, you can do each in one command line.
These commands should be easy to convert to Imagick, I would expect. But should be done in sRGB colorspace. See http://us3.php.net/manual/en/imagick.extentimage.php

Imagick Equivalent Of This Imagemagick Command?

I'm trying to create a vignette effect, and I can get desired result through command line. But when I try it with Imagick, I'm not getting the desired result
convert i.jpg ( -size 150x150 radial-gradient:black-white -gravity center -crop 100x100+0+0 +repage ) -compose multiply -flatten o.jpg
I tried the following Imagick commands
$gra = new Imagick();
$gra->newPseudoImage(150, 150, "radial-gradient:black-white");
$gra->cropThumbnailImage(100, 100);
$gra->setImagePage(100, 100, 0, 0);
$img = new Imagick("i.jpg");
$img->compositeImage($gra, Imagick::COMPOSITE_MULTIPLY, 0, 0);
$img->flattenImages();
$img->writeImage("o.jpg");
Thanks for any help!

Categories