merging two png images in php - php

I am trying to merge my two images in php. One image is being uploaded frim my system and the other is the one I am creating with transparent background.
Here is my code. My code is just showing a non-image icon.
I don't understand where I am wrong.
<?php
//Set the Content Type
header("Content-type: image/png");
#dispaly the image
$file=$_GET['file'];
// echo file_get_contents($file);
$im = imagecreatetruecolor(250, 200);
$black = imagecolorallocate($im, 255, 255, 255);
$blue = imagecolorallocate($im, 0, 0, 255);
imagecolortransparent($im, $black);
//text to draw
$text="hello world";
//font path
$font = '/usr/share/fonts/truetype/droid/DroidSans.ttf';
// Add the text
imagettftext($im, 15, 0, 50, 50, $blue, $font, $text);
$dest=imagecreatefrompng($file);
$src=imagecreatefrompng($im);
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopymerge($dest, $src, 10, 10, 0, 0, 100, 250, 200);
imagepng($dest);
imagedestroy($dest);
imagedestroy($src);
?>

Use $im not $src - as Sayed pointed out, imagecreatefrompng takes filename (string) as argument - not GD resource. Why set $src if $im already contains GD resource ready for use?
There is important part with imagettftext. I was able to reproduce the effect of empty icon if GD cannot find a font in given path. Check your location, permissions and letter case. Also, if you decide to just copy the .ttf file right into script location, refer to imagettftext() documentation as there is important caveat with ".ttf" extension.
Also, to create fully transparent image use:
(by George Edison in PHP doc for imagefill
$im = imagecreatetruecolor(317, 196);
$transparent = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $transparent);
imagesavealpha($im, TRUE);
Also, from PHP doc for imagecopymerge() by Sina Salek: imagecopymerge_alpha function to provide for true transperency in imagecopymerge()
So, my solution:
<?php
//Set the Content Type
header("Content-type: image/png");
#dispaly the image
$file='test.png';
$im = imagecreatetruecolor(317, 196);
$transparent = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $transparent);
imagesavealpha($im, TRUE);
$blue = imagecolorallocatealpha($im, 0, 0, 255, 0);
//text to draw
$text="hello world";
putenv('GDFONTPATH=' . realpath('.'));
$font = 'lucida';
imagettftext($im, 20, 0, 10, 50, $blue, $font, $text);
$dest=imagecreatefrompng($file);
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopymerge_alpha($dest, $im, 10, 10, 0, 0, 200, 180, 100);
imagepng($dest);
imagedestroy($dest);
imagedestroy($im);
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);
}
?>

You should use imagecopymerge() function for this.
Find out link
http://php.net/manual/en/function.imagecopymerge.php

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);
?>

Merge 2 transparent PNG images with PHP GD library

I am trying to combine two transparent PNG images. The second PNG image should have 50% opacity.
The issue:
If the second PNG covers only the non-transparent pixels of the first PNG, then everything is fine.
If the second PNG has areas which cover the transparent pixels of the first PNG, then these areas become black.
The code:
<?php
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
$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, 0, 0, $src_w, $src_h, $pct);
}
$image1 = imagecreatefrompng('a.png'); //300 x 300
$image2 = imagecreatefrompng('b.png'); //150 x 150
$merged_image = imagecreatetruecolor(300, 300);
imagealphablending($merged_image, false);
imagesavealpha($merged_image, true);
imagecopy($merged_image, $image1, 0, 0, 0, 0, 300, 300);
imagecopymerge_alpha($merged_image, $image2, 0, 0, 0, 0, 150, 150, 50);
header('Content-Type: ' . image_type_to_mime_type(IMAGETYPE_PNG));
imagepng($merged_image);
?>
How about if you try this instead? It works for me.
<?php
$image1 = imagecreatefrompng('a.png'); //300 x 300
$image2 = imagecreatefrompng('b.png'); //150 x 150
$merged_image = imagecreatetruecolor(300, 300);
// DEFINE MAGENTA AS THE TRANSPARENCY COLOR AND FILL THE IMAGE FIRST
$transparentColor = imagecolorallocate($merged_image, 255, 0, 255);
imagecolortransparent($merged_image, $transparentColor);
imagefill($merged_image, 0, 0, $transparentColor);
imagesavealpha($merged_image, true);
imagealphablending($image1, false);
imagecopyresampled($merged_image, $image1, 0, 0, 0, 0, 300, 300, 300, 300);
imagealphablending($image1, true);
imagedestroy($image1); // FREE UP SOME MEMORY
imagealphablending($image2, false);
imagecopyresampled($merged_image, $image2, 0, 0, 0, 0, 300, 300, 150, 150);
imagealphablending($image2, true);
imagedestroy($image2); // FREE UP SOME MEMORY
imagealphablending($merged_image, false);
imagesavealpha($merged_image, true);
header('Content-Type: ' . image_type_to_mime_type(IMAGETYPE_PNG));
imagepng($merged_image);
?>
It took me a lot of experimenting in this. I hope this helps you or someone else who may stumble upon this.

Merge two PNG images with PHP GD library

Does anybody have a script which can merge two PNG images?
With the following conditions:
Both images have transparent areas
The second image must have 50% opacity (it is overlaid over the first image)
Here is what I tried to do but without luck:
<?php
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
$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, 0, 0, $src_w, $src_h, $pct);
}
$image1 = imagecreatefrompng('a.png'); //300 x 300
$image2 = imagecreatefrompng('b.png'); //150 x 150
$merged_image = imagecreatetruecolor(300, 300);
imagealphablending($merged_image, false);
imagesavealpha($merged_image, true);
imagecopy($merged_image, $image1, 0, 0, 0, 0, 300, 300);
imagecopymerge_alpha($merged_image, $image2, 0, 0, 0, 0, 150, 150, 50);
header('Content-Type: image/png');
imagepng($merged_image);
?>
Edit:
First Image (left) and Second Image (right)
This is how it should be (left) and the result of my code (right)
The result of the solution proposed by dqhendricks
$image1 = imagecreatefrompng('a.png'); //300 x 300
$image2 = imagecreatefrompng('b.png'); //150 x 150
imagecopymerge($image1, $image2, 0, 0, 75, 75, 150, 150, 50);
this should be all you need. $image1 should hold the merged image where image2 has been overlayed with 50% opacity. the last argument is the alpha of the merged copy.
http://php.net/manual/en/function.imagecopymerge.php
$merged_image = imagecreatetruecolor(300, 300);
imagealphablending($merged_image, false);
imagesavealpha($merged_image, true);
imagecopy($merged_image, $image1, 0, 0, 0, 0, 300, 300);
// after first time of "imagecopy" change "imagealphablending"
imagealphablending($merged_image, **true**);
imagecopy($merged_image, $image2, 0, 0, 0, 0, 300, 300);

Copy an Image with Drop Shadow and Tranparent Background

I tried to duplicate a PNG image, which has drop shadow (i.e. alpha channel) and transparent background. However, the resulting image paints the shadow and transparent background with black. I tried with imagecopy and imagecopymerge; neither yielded to valid results, which aren't the same with the original image.
Preview of the images.
$src = imagecreatefrompng('img_box3-bg.png');
/* Using imagecopy. */
$dest = imagecreatetruecolor(116, 100);
imagecopy($dest, $src, 0, 0, 0, 0, 116, 100);
imagepng($dest, 'img_box3-bg.imagecopy.png');
imagedestroy($dest);
/* Using imagecopymerge. */
$dest2 = imagecreatetruecolor(116, 100);
imagecopymerge($dest2, $src, 0, 0, 0, 0, 116, 100, 100);
imagepng($dest2, 'img_box3-bg.imagecopymerge.png');
imagedestroy($dest2);
imagedestroy($src);
Help? Thanks beforehand.
Something like this:
$src = imagecreatefrompng('img_box3-bg.png');
/* Using imagecopy. */
$dest = imagecreatetruecolor(116, 100);
// this is new
imagesavealpha($dest, true);
$transparent = imagecolorallocatealpha($dest, 0, 0, 0, 127);
imagefill($dest, 0, 0, $transparent);
imagecopy($dest, $src, 0, 0, 0, 0, 116, 100);
header('Content-Type: image/png');
imagepng($dest);
imagedestroy($dest);

Categories