Merge an image with background image gives black background in php - php

I have a light blue image set as $dest.
I have the logo set as logo1
I want to insert the logo into the light blue image. So I tried the following:
<?php
$dest = imagecreatefrompng('template.png');
$logo1 = 'tst.png';
$logo1created = imagecreatefrompng($logo1);
imagealphablending($logo1created,true);
imagesavealpha($logo1created, true);
$logo1width = imagesx($logo1created);
$logo1height = imagesy($logo1created);
$bg_color = imagecolorat($logo1created,1,1); //get color of top-left pixel
imagecolortransparent($logo1created, $bg_color);
imagecopymerge($dest, $logo1created, 70, 132, 0, 0, $logo1width, $logo1height, 100);
header('Content-Type: image/png');
imagepng($dest);
imagedestroy($dest);
imagedestroy($logo1created);
?>
I get the following as the output.
The logo is not transparent (it has a white background) and I have resized the image to 124*30
I want to set transparent background to the logo when I do that there is a black background as per the screenshot above. I am not sure why? Also, the image is blurred. Can someone help me fix this?
Thanks!

Please try the following: (you may adjust the x and y by changing the values 60,70 to other values)
<?php
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);
// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}
$base = imagecreatefrompng('template.png');
$logo1 = 'tst.png';
$logo = imagecreatefrompng($logo1);
imagecopymerge_alpha($base, $logo, 60, 70, 0, 0, 124, 30, 100);
header('Content-Type: image/png');
imagepng($base);
?>

Related

Image with transparanent background becoming white when added with imagecopymerge

I'm using imagecopymerge to place an image on top of another image, however, when I do so, the transparent part of the image becomes white, which isn't what I am after. So the images I have are the below as the background:
And the image I am adding on top of it, with transparent background, is this:
This, however, (along with the rest of my code) results in the area around the circle, and within the boundaries being white:
The code I am using at the moment to inject the value is:
$magical = imagecreatefrompng('Magical.png');
imagecopymerge($img, $magical, 366, 135, 0, 0, 32, 32, 100);
Research has said I should try using things like imagealphablending or imagecopy instead of imagecopymerge, but that didn't work. I've also found references to trying imagecolortransparent and imagecolorallocate but that didn't work either. So, for example, neither of these attempts worked:
$magical = imagecreatefrompng('Magical.png');
$white = imagecolorallocate($output, 255, 255, 255);
imagecolortransparent($magical, $white);
imagecopymerge($img, $magical, 366, 135, 0, 0, 32, 32, 100);
// or this attempt
$magical = imagecreatefrompng('Magical.png');
imagealphablending($img, true);
imagealphablending($magical, true);
imagecopymerge($img, $magical, 366, 135, 0, 0, 32, 32, 100);
What am I missing here? How do I ensure that when the image is added to the other its transparency is retained?
I pulled your images into my local machine and used the imagecopymerge_alpha function listed on the PHP Documentation - https://www.php.net/manual/en/function.imagecopymerge.php#92787
<?php
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);
// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}
$img = imagecreatefrompng('baseImage.png');
$magical = imagecreatefrompng('overlay.png');
imagecopymerge_alpha($img, $magical, 366, 135, 0, 0, 32, 32, 100);
imagepng($img, "./test.png");

imagecopymerge does not work correctly with partially transparent images

I have an image that has opacity:
When I try load it with:
$img = imagecreatefrompng('cheek-01.png');
header('Content-Type: image/png');
imagepng($img);
it will become:
I want to add (merge) this image with another image (I know how can merge two png images).
What is the problem and how can I load it with GD library without losing opacity?
Update
My goal is merge some images where some of them have alpha (different opacity, like the above image), but when I merge them the alpha information is lost.
<?php
$background = imagecreatetruecolor(3508, 2480);
// set background to white
$white = imagecolorallocate($background, 255, 255, 255);
imagefill($background, 0, 0, $white);
$dest = $background;
$items = array(
'cloth-1763-1249' => 'cloth-01.png',
'skin-167-59' => "skin-01.png",
'cheek-2247-1193' => 'cheek-09.png',
'hair-167-59' => 'hair-07.png'
);
foreach ($items as $i => $item) {
$src = imagecreatefrompng($item);
imagealphablending($src, true);
imagesavealpha($src, true);
imagecolortransparent($src, 2130706432);
$src_x = imagesx($src);
$src_y = imagesy($src);
$list = explode('-', $i);
//var_dump($list);
imagecopymerge($dest, $src, intval($list[1]), intval($list[2]), 0, 0, $src_x, $src_y, 100);
imagealphablending($dest, true);
imagesavealpha($dest, true);
}
header('Content-Type: image/png');
imagepng($dest);
Just use imagecopy function. You can do this because your images have built in transparency and you do not need the "pct" parameter that imagecopymerge function offers.
Your code, simplified:
<?php
$image = imagecreatetruecolor(600, 600);
imagefill($image, 0, 0, imagecolorallocate($image, 255, 255, 255));
$items = array(
'layer1' => 'test-1.png',
'layer2' => 'test-2.png',
'layer3' => 'test-3.png',
);
foreach ($items as $i => $item) {
$src = imagecreatefrompng($item);
$srcw = imagesx($src);
$srch = imagesy($src);
imagecopy($image, $src, 0, 0, 0, 0, $srcw, $srch);
}
header('Content-Type: image/png');
imagepng($image);
The output PNG image:
The three PNG images used in the above example (the content is 50% transparent and the background is transparent, not white):
You need to enable alpha blending and imagecopymerge was never designed to respect the alpha channel (people tried to fix this back in 2009, but the PHP devs ignored this and said it was intended behaviour). According to the PHP documentation comment section this should work.
<?php
/**
* PNG ALPHA CHANNEL SUPPORT for imagecopymerge();
* by Sina Salek
*
* Bugfix by Ralph Voigt (bug which causes it
* to work only for $src_x = $src_y = 0.
* Also, inverting opacity is not necessary.)
* 08-JAN-2011
*
**/
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);
// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}
// ...Do your previous stuff...
imagecopymerge_alpha(....);
// do the other stuff
/* Output image to browser */
header('Content-type: image/png');
imagepng($imgPng);
?>

Combining transparent pngs

I have looked here on SO for solutions for my problem, but I can't find a solution that seems to work for me. Maybe I'm doing something wrong.
I am merging a number of transparent PNGs together, into one display for the customer. There are pretty much three layers (obviously the background is transparent, then fairly rectangular PNGs, but somewhat out of square, and then smaller ones on top of that).
The top layer of smaller images goes on the rectangles nicely. But the rectangles look as though they were filled with black first, then the image applied - you can see this because the image is slightly out of square, so the edges usually have this black line around it. The thing that I don't understand is why this layer has it and not the top - both images are instantiated with the same code.
Here is my code (I found the imagecopymerge_alpha function somewhere, and it seems to do pretty well, but obviously, not entirely).
// Merging:
$this->imagecopymerge_alpha($this->image, $resizedImage, $startX, $startY, 0, 0, imagesx($resizedImage), imagesy($resizedImage), 100);
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);
// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}
// Creating the background/container image:
private function createTransparent($width, $height)
{
$image = imagecreatetruecolor($width, $height);
imagealphablending($image, false);
imagesavealpha($image, true);
$transparentColor = imagecolorallocatealpha($image, 255, 255, 255, 127);
imagefill($image, 0, 0, $transparentColor);
return $image;
}
So, my question is this: do you see anything in here that would make a transparent PNG not maintain it's transparency and merge correctly with a base transparent PNG?

Adding some opacity on an image with imagecopymerge in PHP

Here my problem:
I want to change the opacity of an image, by copying it on another transparent image.
My code:
$opacity = 50;
$transparentImage = imagecreatetruecolor($width, $height);
imagesavealpha($transparentImage, true);
$transColour = imagecolorallocatealpha($transparentImage , 0, 0, 0, 127);
imagefill($transparentImage , 0, 0, $transColour);
imagecopymerge($transparentImage, $image, 0, 0, 0, 0, $width, $height, $opacity);
$image = $transparentImage;
header('Content-type: image/png');
imagepng($image);
By doing this, when I use imagecopymerge, $transparentImage loses its transparency... So $image is merged on a black image... and not on a transparent image !
However, when I show $transparentImage before calling imagecopymerge, the image is transparent in my navigator !
Is there a solution to change opacity of my image, without adding it on a colored background ?
It seems that imagecopymerge does not support the alpha (transparency) channel on images. Fortunately you can use a workaround with imagecopy to do it correctly. Here's a function to do this, taken from the comments on php.net:
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);
// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}

How to avoid black background when rotating an image 45 degree using PHP?

Hi I have to flip a thumpnail image before merge it with another jpeg file. but when I rotate 45 degree using php. It shows a black background. how can I avoid that. any body can help me.
Well, if you are generating a jpg, using PHP GD you set the color of the background as the third option of the function imagerotate. In this example I'm gonna assume that you are rotating a jpg image $filename by an arbitrary $angle degrees, and you want a white background, i.e. color code 16777215:
$rotatedImage = imagerotate(imagecreatefromjpeg($filename), ((360-$angle)%360), 16777215);
black is color code 0, which is default, and the rest of the color gamma is in between the two, so you just need to decide which background color you would like
EDIT:
for transparent backgrounds, if you are generating a png you would do:
$destimg = imagecreatefromjpeg($filename);
$transColor = imagecolorallocatealpha($destimg, 255, 255, 255, 127);
$rotatedImage = imagerotate($destimg, ((360-$angle)%360), $transColor);
Hope that helps
<?
$image = "130.jpg";
$degrees = 25;
for($i=0;$i<count($data);$i++){
$ext = "";
$extarr = "";
$extarr = explode(".", $data[$i]['name']);
$ext = array_pop($extarr);
if($ext == "png"){
$rotate = imagecreatefrompng("images/".$data[$i]['name']);
$transColor = imagecolorallocatealpha($rotate, 255, 255, 255, 270);
$watermark1[$i] = imagerotate($rotate, ((360-$degrees)%360), $transColor);
}
}
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $opct){
$w = imagesx($src_im);
$h = imagesy($src_im);
$cut = imagecreatetruecolor($src_w, $src_h);
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, (100 - $opct));
}
for($i=0; $i<count($watermark1); $i++){
if($i == 0) imagecopymerge_alpha($image, $watermark1[$i], $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, $opacity);
else imagecopymerge_alpha($image, $watermark1[$i], ($i*$dest_x)*3, ($i*$dest_y)*15, 0, 0, $watermark_width, $watermark_height, $opacity);
imagedestroy($watermark1[$i]);
}
header("content-type: image/png");
imagepng($image);
imagedestroy($image);
?>
Also, do your watermark images have alpha channel or are they fully opaque?

Categories