imagecopymerge не работает правильно с частично прозрачными изображениями

У меня есть изображение с непрозрачностью:

введите описание изображения здесь

Когда я пытаюсь загрузить его с:

$img = imagecreatefrompng('cheek-01.png');
header('Content-Type: image/png');
imagepng($img);

это станет:

введите описание изображения здесь

Я хочу добавить (объединить) это изображение с другим изображением (я знаю, как можно объединить два изображения PNG).
В чем проблема и как я могу загрузить его GD библиотека без потери непрозрачности?

Обновить

Моя цель — объединить некоторые изображения, где некоторые из них имеют альфа (непрозрачность, как на изображении выше), но когда я объединяю их, альфа информация теряется.

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

2

Решение

Вам необходимо включить альфа-смешивание, и imagecopymerge никогда не был разработан с учетом альфа-канала (люди пытались это исправить еще в 2009 году, но разработчики PHP проигнорировали это и сказали, что это было запланированное поведение). Согласно разделу комментариев документации PHP это должно работать.

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

Другие решения

Просто используйте imagecopy функция. Вы можете сделать это, потому что ваши изображения имеют встроенную прозрачность и вам не нужен параметр «pct», который imagecopymerge Функциональные предложения.

Ваш код, упрощенный:

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

Выходное PNG изображение:

Выходной PNG

Три PNG-изображения, использованные в приведенном выше примере (содержимое на 50% прозрачно, а фон прозрачный, а не белый):

Тест-1.png
Тест-2.png
Тест-3.png

5