I'm in the process of writing an image script for a website I'm making, and for one of the image modes I need to both crop the image and make round corners for it. This is the code I'm using now:
$img = new Imagick();
$img->readImageBlob($data);
$img->resizeImage($width, $height, $img->FILTER_GAUSSIAN, 1);
$canvas = new Imagick();
$canvas->newImage($size[0], $size[1], new ImagickPixel('white'));
$canvas->compositeImage($img, imagick::COMPOSITE_OVER, 0, 0);
$canvas->roundCorners(10, 10);
$canvas->setImageFormat('png');
Resulting image
However, the resulting image is about half-transparent, as seen above, except for a 10-ish px border around the edge, created by roundCorner I assume. I've tried a lot of different ways of doing this, including cropping $img directly and roundCorner on it, but then the result is without round corners.
I suspect compositeImage to be the thief in this drama, but I can't say for sure. Anyone?
EDIT: Correction: If I do the crop and round solution, I end up with rounded corners, but they have a black background. This is the code I'm using here. Anyone spot the error/solution?
$img = new Imagick();
$img->readImageBlob($data);
$img->resizeImage($width, $height, $img->FILTER_GAUSSIAN, 1);
$img->cropImage($size[0], $size[1], 0, 0);
$img->roundCorners(10, 10);
EDIT 2:
The solution to the crop and round resolution was to make sure it's a png, so that is has alpha-support. However, the result is the same as the one produced from my original code.
EDIT 3:
Tried this script on my deployment server, and it worked as I wanted it to, so it seems like there's some problem with the version of imagick / php-imagick shipped with macports. Thanks for all the help!
You can tell imagemagick to give you an alpha background with
$img->setImageAlphaChannel ( imagick::ALPHACHANNEL_TRANSPARENT )
or try setting the image format to PNG24 explicitly before doing any transformations.
Order is important here, the image needs an alpha channel before you expose the background.
It was a problem with the version of Imagick / php-imagick shipped with current macports. Haven't solved it for my computer, but the script is working as intended on my deployment server.
Related
I want to make the mixed image with fade effect from two images.
Here is my PHP code.
$img1 = new Imagick();
$img1->readImage("images/1.jpg");
$img2 = new Imagick();
$img2->setOption('compose:args', '50');
$img2->readImage("images/2.jpg");
$img1->compositeImage($img2, imagick::COMPOSITE_DISSOLVE, 0, 0);
$img1->writeImage("images/3.jpg");
This code works correctly on my Mac OS.
But it doesn't work on remote server (Cent OS 6.5), the result image is same with 2.jpg.
I tried with COMPOSITE_BLEND constant, it works well.
And I tried the command in terminal.
# composite -dissolve 50 2.jpg 1.jpg 3.jpg
It also works well.
Why doesn't COMPOSITE_DISSOLVE constant work in PHP?
Please help me.
You really ought to just figure out what the difference is between your dev environment and your server. It's very likely to be the case that the version of ImageMagick on the dev server is very out of date, unless you are compiling it yourself, as the Centos packages management system seems to take a long time to get new releases.
However....the way you are blending the images is not fantastic. Although it may work for you, it requires the slightly poorly defined $img2->setOption('compose:args', '50'); line.
A much more powerful technique is to control the alpha channel yourself through the COMPOSITE_COPYOPACITY. This gives you full control for how images are blended. e.g.
$img1 = new \Imagick();
$img1->readImage(realpath("../images/Biter_500.jpg"));
$img2 = new \Imagick();
$img2->readImage(realpath("../images/Skyline_400.jpg"));
//Resize images to the same size, to look pretty.
$img1->resizeimage(
$img2->getImageWidth(),
$img2->getImageHeight(),
\Imagick::FILTER_LANCZOS,
1
);
//Create an image that the alpha will be created in.
$opacity = new \Imagick();
if (true) {
//Create a 50% grey image
$opacity->newPseudoImage($img1->getImageWidth(), $img1->getImageHeight(), "CANVAS:gray(50%)");
}
else {
//Create a far more interesting blend.
//Gradients are created top to bottom, so we need to rotate the image
$opacity->newPseudoImage($img1->getImageHeight(), $img1->getImageWidth(), "gradient:gray(10%)-gray(90%)");
$opacity->rotateimage('black', 90);
}
$img2->compositeImage($opacity, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$img1->compositeImage($img2, \Imagick::COMPOSITE_ATOP, 0, 0);
header("Content-Type: image/jpg");
echo $img1->getImageBlob();
The first way of creating the opacity image with "CANVAS:gray(50%)" does what your existing image code does. The second way of blending creates a image that is blended from 10% to 90% across the width of the image.
I have a script that handles/scales uploaded images. I noticed that some of the images come out significantly darkened, and through a process of elimination tracked the darkening back to this section of code:
$scaled = new IMagick();
$scaled->newPseudoImage($original->getImageWidth(), $original->getImageHeight(), 'xc:white');
$scaled->compositeImage($original, Imagick::COMPOSITE_DEFAULT, 0, 0);
$scaled->flattenImages();
What I'm doing here is trying to eliminate issues with transparent backgrounds in some images coming through as black when I convert to jpg.
Does anyone have any idea which part of this code is darkening the image and what a good way to fix it might be?
Edit: Still haven't figured out the heart of this issue, but I did find that I can avoid doing this to images that don't need it by wrapping it in:
if($original->getImageAlphaChannel()){
Hi I'm porting a script from a windows environment running MagickWand 0.1.8 and ImageMagick 6.2.9 where transparency worked fine with MagickRotateImage.
New environment is linux running MagickWand 1.0.8 with ImageMagick 6.5.4-7 and transparency gets lost and it shows black as the background as soon as my logo image gets rotated.
From what I've found online, seems that PixelSetColor($bg,"none") doesn't work with the newer versions hence the black. Ultimately, I need to know what to replace PixelSetColor($bg,"none") with. I just don't have a background in image creation so struggling a bit with this.
First my php runs this function which makes a local 60x60 version of 600x600 png image gotten from a url.
function makeThumb($fileContents){
GLOBAL $localImgPath1;
GLOBAL $localImgPath2;
$wand = NewMagickWand();
$lg = MagickReadImageBlob($wand,$fileContents);
$lg_w = MagickGetImageWidth($wand);
$lg_h = MagickGetImageHeight($wand);
$max = max($lg_h,$lg_w);
$scale_factor = 60/$max;
MagickResizeImage($wand,$lg_w*$scale_factor,$lg_h*$scale_factor, MW_GaussianFilter, .7);
MagickWriteImage($wand, $localImgPath1);
if($localImgPath2!="")
MagickWriteImage($wand, $localImgPath2);
$resized_w = MagickGetImageWidth($wand);
$resized_h = MagickGetImageHeight($wand);
DestroyMagickWand($wand);
}
then, I use this to read that locally written png image and rotate it:
$logo = NewMagickWand();
$bg = NewPixelWand();
PixelSetColor($bg,"none");
MagickReadImage($logo, $localImgPath1);
MagickRotateImage($logo, $bg, $r);
header('Content-Type: image/PNG');
MagickEchoImageBlob($logo);
DestroyPixelWand($bg);
DestroyMagickWand($logo);
I've tried things like adding:
$transparent = NewPixelWand("#FFFFFF");
PixelSetAlpha($transparent, 0);
//and then making the rotate call:
MagickRotateImage($logo, $transparent, $r);
Also tried adding MagickSetImageAlphaChannel($logo, MW_SetAlphaChannel); before the rotate step. Saw some posts mentioning that method but possibly that's not the correct way to use it. Not sure.
I also have the same problem in a script that draws a text string with a set font onto the image. Black immediately shows there even before rotation is applied so hoping same fix for the logo script will be useable by the font script.
Any help would be greatly appreciated. Thanks.
You've got a choice of four values for a transparent background. Try each in turn:
"none", "transparent", "#00000000", or "rgba(0, 0, 0, 0.0)"
The problem was with ImageMagick 6.5.4-7. Must have been a buggy release. Upgraded to 6.8.4-10 and above code works fine, PixelSetColor($bg,"none") works for the transparency.
I have the last few hours tried to get a PNG logo with a transparent background on top of a JPG background. I have tried several ways and with several globals as well, but I do not seem to be able to get the result I want.
"First Attempt":
$overlay = new Imagick('overlay.png');
$image = new Imagick('background.jpg');
$image->compositeImage($overlay, Imagick::COMPOSITE_DEFAULT, 10, 10);
$image->writeImage('background.jpg'); //replace original background
$overlay->destroy();
$image->destroy();
As you can see, the Jaguar logo is all black.
"Second Attempt"
$overlay = new Imagick('overlay.png');
$image = new Imagick('background.jpg');
$image->setImageColorspace($overlay->getImageColorspace() );
$image->compositeImage($overlay, Imagick::COMPOSITE_DEFAULT, 10, 10);
$image->writeImage('background.jpg'); //replace original background
$overlay->destroy();
$image->destroy();
This one the Jaguar logo looks like it should, but the background is all messed up now.
I have tried with Imagick::setImageMatte and tried to add the overlay to a white background (thought I does need to have a transparent background) and still it won't display the image properly. I have tried many other variations of the 2 above snippets but they all seem to make the PNG completely or partial black.
What am I missing or doing wrong? Can anyone give me a nudge in the right direction?
Please note this needs to be done in PHP.
Thank you very much!
I am a huge idiot! Turns out I forgot to convert the images from CMYK to RGB.
For anyone who might encounter this in the future, learn from my incompetence!
I was trying to overlay a png with transparency over the top of another png. I used this line from the PHP docs.
$src1->compositeImage($src2, Imagick::COMPOSITE_MATHEMATICS, 0, 0);
but I was getting the same problem. The overlay came through as black only. Changing it to this seemed to fix the colours.
$src1->compositeImage($src2, Imagick::COMPOSITE_DEFAULT, 0, 0);
does anyone know how to apply fade effect to an image using PHP ? what I am looking for is a way to apply gradient transparency ( i mean : at the top , the image is opaque , which gradually gets more and more transparent , and at the bottom it is completely transparent).
i have been reading up on http://php.net/manual/en/function.imagecolortransparent.php , but did not see anything about applying a gradient effect to an image.
i also read : PHP - Generate transparency (or opacity) gradient using image , but it kinda trailed off without any solution!
I am also open to any other suggestion / libraries that can do this from command line.
Obviously you'll need to work with a png for this effect, but you can convert any png into a jpg using php. The following question I believe covers what you are asking about. Part of the code will have to be removed to clear the image reflection effect.
Can You Get a Transparent Gradient using PHP ImageMagick?
The piece of code which seems to do what you are trying to accomplish is:
$im = new Imagick('image.jpg'); //Reference image location
if (!$im->getImageAlphaChannel()) {
$im->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET);
}
$refl = $im->clone();
$refl->flipImage();
$gradient = new Imagick();
$gradient->newPseudoImage($refl->getImageWidth() + 10, $refl->getImageHeight() + 10, "gradient:transparent-black");