Reputation: 4421
I am trying to layer a partially transparent PNG on top of another opaque PNG.
There are many example of how to do this across this site and the net, however with every version I try I seem to not be able to maintain the foreground image's transparency.
Currently the code looks like this:
$image = imagecreatefrompng($_GET['fg']);
$frame = imagecreatefrompng($_GET['bg']);
imagealphablending($frame,true);
imagecopymerge($image, $frame, 0, 0, 0, 0, 0, 100, 100);
# Save the image to a file
$output_file = 'preview-' . time() . '.png';
imagepng( $image, $_SERVER['DOCUMENT_ROOT'] . '/share/' . $output_file );
Which produces an image made up of the foreground image with the transparent parts as white (or black).
Also I have tried this as seen in the image thumbnail generator, TimThumb, which produces the same output:
$canvas= imagecreatefrompng($_GET['bg']);
$overlay_gd_image = imagecreatefrompng( $_GET['fg'] );
$overlay_width = imagesx( $overlay_gd_image );
$overlay_height = imagesy( $overlay_gd_image );
imagealphablending($canvas, true );
imagecopy( $canvas, $overlay_gd_image, 0, 0, 0, 0, $overlay_width, $overlay_height);
imagealphablending($canvas, false );
imagesavealpha($canvas , true);
imagepng($canvas, 'new.png');
I am running out of things to try and would be grateful if anyone could shed light on the problem.
Upvotes: 2
Views: 1644
Reputation: 239
I had exactly the same issue. The solution for me was to use imagecopyresampled instead of imagecopymerge. This will preserve transparency for both images.
be aware of the slightly different parameters to pass
Upvotes: 0
Reputation: 15
The native imagecopymerge doesn't really work so well when it comes to transparent images. If you want to merge two PNG's together and not have the alpha channel get messed up, this function found on the manual page works like a charm for me and actually preserves transparency. I have been merging PNGs nonstop with this function and have not had a problem so I think it could solve yours. (Posted by "rodrigo dot polo at gmail dot com", so all credits to him/her.)
<?php
/**
* PNG ALPHA CHANNEL SUPPORT for imagecopymerge();
* This is a function like imagecopymerge but it handle alpha channel well!!!
**/
// A fix to get a function like imagecopymerge WITH ALPHA SUPPORT
// Main script by aiden dot mail at freemail dot hu
// Transformed to imagecopymerge_alpha() by rodrigo dot polo at gmail dot com
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
if(!isset($pct)){
return false;
}
$pct /= 100;
// Get image width and height
$w = imagesx( $src_im );
$h = imagesy( $src_im );
// Turn alpha blending off
imagealphablending( $src_im, false );
// Find the most opaque pixel in the image (the one with the smallest alpha value)
$minalpha = 127;
for( $x = 0; $x < $w; $x++ )
for( $y = 0; $y < $h; $y++ ){
$alpha = ( imagecolorat( $src_im, $x, $y ) >> 24 ) & 0xFF;
if( $alpha < $minalpha ){
$minalpha = $alpha;
}
}
//loop through image pixels and modify alpha for each
for( $x = 0; $x < $w; $x++ ){
for( $y = 0; $y < $h; $y++ ){
//get current alpha value (represents the TANSPARENCY!)
$colorxy = imagecolorat( $src_im, $x, $y );
$alpha = ( $colorxy >> 24 ) & 0xFF;
//calculate new alpha
if( $minalpha !== 127 ){
$alpha = 127 + 127 * $pct * ( $alpha - 127 ) / ( 127 - $minalpha );
} else {
$alpha += 127 * $pct;
}
//get the color index with new alpha
$alphacolorxy = imagecolorallocatealpha( $src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha );
//set pixel with the new color + opacity
if( !imagesetpixel( $src_im, $x, $y, $alphacolorxy ) ){
return false;
}
}
}
// The image copy
imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
}
// USAGE EXAMPLE:
$img_a = imagecreatefrompng('image1.png');
$img_b = imagecreatefrompng('wm2.png');
// SAME COMMANDS:
imagecopymerge_alpha($img_a, $img_b, 10, 10, 0, 0, imagesx($img_b), imagesy($img_b),50);
// OUTPUT IMAGE:
header("Content-Type: image/png");
imagesavealpha($img_a, true);
imagepng($img_a, NULL);
?>
If you use the example, you'll see that $img_a would be below $img_b and instead of having a weird black box, $img_b's transparency would be preserved.
Upvotes: 1