I need to flip an image so that a character faces in the right direction. This needs to be done "on the fly' as they say.
The issue I am having is that with Gif images, I seem to lose the transparency. (The background goes white)
Below is the code: (Alternatively someone could send me to a good example)
$img = imagecreatefromgif("./unit.gif");
$size_x = imagesx($img);
$size_y = imagesy($img);
$temp = imagecreatetruecolor($size_x, $size_y);
imagecolortransparent($img, imagecolorallocate($img, 0, 0, 0));
imagealphablending($img, false);
imagesavealpha($img, true);
$x = imagecopyresampled($temp, $img, 0, 0, ($size_x-1), 0, $size_x, $size_y, 0-$size_x, $size_y);
if ($x) {
$img = $temp;
}
else {
die("Unable to flip image");
}
header("Content-type: image/gif");
imagegif($img);
imagedestroy($img);
Shouldn't this:
imagecolortransparent($img, imagecolorallocate($img, 0, 0, 0));
imagealphablending($img, false);
imagesavealpha($img, true);
...be this:
imagecolortransparent($temp, imagecolorallocate($img, 0, 0, 0));
imagealphablending($temp, false);
imagesavealpha($temp, true);
Note you should be calling these functions for the $temp image you have created, not the source image.
Final Results:
$size_x = imagesx($img);
$size_y = imagesy($img);
$temp = imagecreatetruecolor($size_x, $size_y);
imagecolortransparent($temp, imagecolorallocate($temp, 0, 0, 0));
imagealphablending($temp, false);
imagesavealpha($temp, true);
$x = imagecopyresampled($temp, $img, 0, 0, ($size_x-1), 0, $size_x, $size_y, 0-$size_x, $size_y);
if ($x) {
$img = $temp;
}
else {
die("Unable to flip image");
}
header("Content-type: image/gif");
imagegif($img);
imagedestroy($img);
If you can guarantee the presence of ImageMagick, you can use their mogrify -flop command. It preserves transparency.
Related
I want to add a color layer over a image in php using gd.
This is the image:
I want to overlay this with this color: #ABD0D2
I made a quick image how it should look at the end.
Keep in mind that the image should still be transparent
So far I have this code:
$img = imagecreatefrompng('image.png');
imagesavealpha($img, true);
imagefill($img, 0, 0, imagecolorallocatealpha($img, 0, 0, 0, 127));
// make overlay with new color???
imagepng($img, 'new.png');
imagedestroy($img);
You can create a new image, filled with your target colour, and then merge the two:
$img = imagecreatefrompng('image.png');
$w = imagesx($img);
$h = imagesy($img);
imagesavealpha($img, true);
$img2 = imagecreatetruecolor($w, $h);
imagefill($img2, 0, 0, imagecolorallocatealpha($img, 0xAB, 0xD0, 0xD2, 64));
imagecopy($img, $img2, 0, 0, 0, 0, $w, $h);
imagepng($img, 'new.png');
imagedestroy($img);
imagedestroy($img2);
Result:
It's not completely clear to me how you want to maintain transparency (as your expected result image isn't transparent) so in the code above I've set the 'mask' colour at 50% opacity.
That worked for me:
$width = 400;
$height = 400;
$image = imagecreatefrompng('img.png');
$blueOverlay = imagecreatetruecolor($width, $height);
imagesavealpha($image, true);
imagealphablending($image, false);
imagesavealpha($blueOverlay, true);
$blue = imagecolorallocatealpha($blueOverlay, 0, 0, 255, ceil(0.22 * 127));
imagefill($blueOverlay, 0, 0, $blue);
imagecopymerge($blueOverlay, $image, 0, 0, 0, 0, $width, $height, 70);
imagepng($blueOverlay, 'imgWithOverlay.png');
imagedestroy($image);
imagedestroy($blueOverlay);
So I'm trying to take two large images (but later I'll be combinging 6 images in total), resize them to the x, y width, height I have taken from photoshop, and combine them into one 460 x 230 sized image.
This is the code I'm using
<?php
$dest = imagecreatefrompng('https://blzgdapipro-a.akamaihd.net/hero/ana/career-portrait.png');
$src = imagecreatefrompng('https://blzgdapipro-a.akamaihd.net/game/rank-icons/season-2/rank-6.png');
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagealphablending($src, false);
imagesavealpha($src, true);
//imagescale($dest, 396, 161.92);
$some = imagecreate(460, 230);
$dest2 = resize($dest, 396, 162);
$src2 = resize($src, 79.19, 79.19);
//imagecopyresized($dest, $dest, 0, 0, 0, 0, 396, 161.92, 1098, 449);
imagecopyresized($src, $src, 10, 10, 0, 0, 79.19, 79.19, 256, 256);
//$img2 = imagecopymerge($dest, $src, 0, 0, 0, 0, 256, 256, 100); //have to play with these numbers for it to work for you, etc.
imagecopymerge($dest2, $src2, 0, 0, 0, 0, 460, 230, 50);
header('Content-Type: image/png');
imagepng($dest, 'merged2.png');
imagepng($dest2);
//file_put_contents('merged.png', $contents);
imagedestroy($dest);
imagedestroy($src);
imagedestroy($some);
imagedestroy($dest2);
imagedestroy($src2);
imagedestroy($img2);
//imagedestroy($then);
function resize($img, $width, $height, $stretch = false)
{
$temp = imagecreatetruecolor($width, $height);
imagealphablending($temp, true);
imagesavealpha($temp, true);
$bg = imagecolorallocatealpha($temp, 0, 0, 0, 0); // Background color
imagefill($temp, 0, 0, $bg);
if ($stretch)
{
imagecopyresampled($temp, img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img));
}
else
{
if (imagesx($img) <= $width && imagesy($img) <= $height)
{
$fwidth = imagesx($img);
$fheight = imagesy($img);
}
else
{
$wscale = $width / imagesx($img);
$hscale = $height / imagesy($img);
$scale = min($wscale, $hscale);
$fwidth = $scale * imagesx($img);
$fheight = $scale * imagesy($img);
}
imagecopyresampled($temp,
$img,
($width - $fwidth) / 2, ($height - $fheight) / 2,
0, 0,
$fwidth, $fheight,
imagesx($img), imagesy($img)
);
}
return $temp;
}
The issue is that the image rendered is very faded
because of this line:
imagecopymerge($dest2, $src2, 0, 0, 0, 0, 460, 230, 50);
If I change the 50, which is the PCT value to 100, it shows one image with a black background (masking the other image), but if I change it to 0, it shows only the other image with a black background (masking the other image)
If the value is either 0 or 100, the image shown is at its full color though. How do I merge these 2 images together while preserving their transparency and vibrancy of color?
Instead of imagecopymerge use imagecopy. You also always need to correctly specify the dimensions of the source image when copying:
$dest = imagecreatefrompng('https://blzgdapipro-a.akamaihd.net/hero/ana/career-portrait.png');
$src = imagecreatefrompng('https://blzgdapipro-a.akamaihd.net/game/rank-icons/season-2/rank-6.png');
$dest2 = resize($dest, 396, 162);
imagedestroy($dest);
$src2 = resize($src, 79, 79); // should be int not float.
imagedestroy($src);
// the last 2 params must match the width/height of the $src2 image.
imagecopy($dest2, $src2, 0, 0, 0, 0, 79, 79);
imagedestroy($src2);
header('Content-Type: image/png');
imagepng($dest2);
imagedestroy($dest2);
You don't need to change the alpha settings on $dest or $src because they aren't being rendered - you render the new image resource created in, and returned by, your resize function. Because of this you do need to slightly change the function:
function resize($img, $width, $height, $stretch = false)
{
$temp = imagecreatetruecolor($width, $height);
imagealphablending($temp, false); // changed to false.
imagesavealpha($temp, true);
...
Edit:
You might be better off simply using the imagescale function instead of using your own resize function:
$dest = imagecreatefrompng('https://blzgdapipro-a.akamaihd.net/hero/ana/career-portrait.png');
$src = imagecreatefrompng('https://blzgdapipro-a.akamaihd.net/game/rank-icons/season-2/rank-6.png');
$dest2 = imagescale($dest, 396);
imagealphablending($dest2, false);
imagesavealpha($dest2, true);
$src2 = imagescale($src, 79);
imagecopy($dest2, $src2, 0, 0, 0, 0, 79, 79);
header('Content-Type: image/png');
imagepng($dest2);
imagedestroy($dest);
imagedestroy($src);
imagedestroy($dest2);
imagedestroy($src2);
I have a custom bicycle configurator that layers transparent png files with css.
http://www.gallantbicycles.com/build/no1/
I need to add the ability to combine them into one file dynamically so the user can download an image or share it.
This is where I'm at right now, but it results in a black background and only the front most image is seen in the result:
$width = 720;
$height = 500;
$layers = array();
$layers[] = imagecreatefrompng("pathtomyimage/image.png");
$layers[] = imagecreatefrompng("pathtomyimage/image.png");
$layers[] = imagecreatefrompng("pathtomyimage/image.png");
$image = imagecreatetruecolor($width, $height);
imagealphablending($image, false);
imagesavealpha($image, true);
for ($i = 0; $i < count($layers); $i++) {
imagecopymerge($image, $layers[$i], 0, 0, 0, 0, $width, $height, 100);
}
header('Content-type: image/png');
imagepng($image);
You have to replace this code
imagealphablending($image, false);
imagesavealpha($image, true);
for ($i = 0; $i < count($layers); $i++) {
imagecopymerge($image, $layers[$i], 0, 0, 0, 0, $width, $height, 100);
}
by
imagealphablending($image, true);
for ($i = 0; $i < count($layers); $i++) {
imagecopymerge($image, $layers[$i], 0, 0, 0, 0, $width, $height, 100);
}
imagealphablending($image, false);
imagesavealpha($image, true);
imagealphablending must be true in order to correcly stack the layers, but it must be false to save the image.
Try this solution: Merge two images with transparencies in PHP
use imagecopyresampled instead of imagecopymerge
Here is code which works:
$width = 210;
$height = 190;
$layers = array();
$layers[] = imagecreatefrompng("img/01_boy_faceB.png");
$layers[] = imagecreatefrompng("img/01_boy_hairB.png");
$image = imagecreatetruecolor($width, $height);
// to make background transparent
imagealphablending($image, false);
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127);
imagefill($image, 0, 0, $transparency);
imagesavealpha($image, true);
/* if you want to set background color
$white = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $white);
*/
imagealphablending($image, true);
for ($i = 0; $i < count($layers); $i++) {
imagecopy($image, $layers[$i], 0, 0, 0, 0, $width, $height);
}
imagealphablending($image, false);
imagesavealpha($image, true);
imagepng($image, 'final_img.png');
?>
All right! I combined all of your answers to come up with a solution that actually works!
Thanks for the help and I hope this helps someone!
$width = $height = null;
$layers = [];
foreach ($imageLayerPaths as $layer) {
if (!is_file($layer)) {
continue;
}
$layers[] = imagecreatefrompng($layer);
if ($width === null) {
$size = getimagesize($layer);
$width = $size[0];
$height = $size[1];
}
}
if (empty($layers)) {
throw new \Exception("No valid image layers to create the image");
}
// Create image base with transparent background
$image = imagecreatetruecolor($width, $height);
imagealphablending($image, false);
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127);
imagefill($image, 0, 0, $transparency);
imagesavealpha($image, true);
// Add each layer on the image
imagealphablending($image, true);
foreach ($layers as $layer) {
imagecopyresampled($image, $layer, 0, 0, 0, 0, $width, $height, $width, $height);
}
imagealphablending($image, false);
imagesavealpha($image, true);
imagepng($image, "path/where/you/want/to/save/the/image.png");
I have a white icon (256x256) with a transparent background. Somehow, I want to be able to change the white icon, which has some transparent pixels in it (for anti-aliasing), to any RGB color.
I have tried using the following function but
imagefilter($im, IMG_FILTER_COLORIZE, 0, 255, 0)
Is there any way to do this in PHP GD? What functions can I look into?
I just created the following code and it works wonders.
Beware: If you set $backgroundTransparent to false, the image may lose quality when the background is painted under it.
<?php
$width = 256;
$height = 256;
$backgroundColor = array(0, 255, 0);
$backgroundTransparent = true;
$icon = imagecreatefrompng('Access-New.png');
imagealphablending($icon, false);
imagesavealpha($icon, true);
imagefilter($icon, IMG_FILTER_BRIGHTNESS, -255);
imagefilter($icon, IMG_FILTER_COLORIZE, 255, 0, 0);
if($backgroundTransparent == false) {
$background = imagecreatetruecolor($width, $height);
imagefill($background, 0, 0, imagecolorallocate($background, $backgroundColor[0], $backgroundColor[1], $backgroundColor[2]));
imagealphablending($icon, true);
imagecopy($background, $icon, 0, 0, 0, 0, $width, $height);
imagepng($background, NULL, 0, PNG_NO_FILTER);
}
else {
imagepng($icon, NULL, 0, PNG_NO_FILTER);
}
header("Content-type: image/png");
imagedestroy($background);
?>
Friends i want to generate one png image from multiple transparent PNG image but the issue is that i can generate only last image
Both images can not combine.
My code is given below
$x = 363;
$y = 267;
$im_dest = imagecreatetruecolor ($x, $y);
imagealphablending($im_dest, false);
$im = imagecreatefrompng('2.png');
$im1 = imagecreatefrompng('1.png');
imagecopy($im_dest, $im1, 0, 0, 0, 0, $x, $y);
imagecopy($im_dest, $im, 0, 0, 0, 0, $x, $y);
imagesavealpha($im_dest, true);
imagepng($im_dest, 'small_redfade.png');
These are the images which i am using to join in single image
http://s11.postimg.org/h6lui7yjn/image.png
http://s21.postimg.org/o7zdnwcnb/image.png
Here is code which works:
$width = 210;
$height = 190;
$layers = array();
$layers[] = imagecreatefrompng("img/01_boy_faceB.png");
$layers[] = imagecreatefrompng("img/01_boy_hairB.png");
$image = imagecreatetruecolor($width, $height);
// to make background transparent
imagealphablending($image, false);
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127);
imagefill($image, 0, 0, $transparency);
imagesavealpha($image, true);
/* if you want to set background color
$white = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $white);
*/
imagealphablending($image, true);
for ($i = 0; $i < count($layers); $i++) {
imagecopy($image, $layers[$i], 0, 0, 0, 0, $width, $height);
}
imagealphablending($image, false);
imagesavealpha($image, true);
imagepng($image, 'final_img.png');
?>
ImageMagick::Composite can handle this, sadly haven't done in GD so will leave others to explain how to do it there.
Something like:
<?php
$firstImage = new Imagick("firstImage.png");
$secondImage = new Imagick("secondImage.png");
$firstImage->compositeImage($secondImage, Imagick::COMPOSITE_COPYOPACITY, 0, 0 );
header('Content-type: image/png');
echo $firstImage;
?>
This should preserve alpha.