Jason Wood
Jason Wood

Reputation: 351

Merging multiple overlapping transparent png images with php

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

Upvotes: 1

Views: 5678

Answers (4)

Chris
Chris

Reputation: 4436

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

Upvotes: 0

atulmy
atulmy

Reputation: 1383

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

?>

Upvotes: 0

PepeNietnagel
PepeNietnagel

Reputation: 239

Try this solution: Merge two images with transparencies in PHP

use imagecopyresampled instead of imagecopymerge

Upvotes: 1

Lorenz Meyer
Lorenz Meyer

Reputation: 19895

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.

Upvotes: 1

Related Questions