imagecopymerge无法正常使用部分透明图像

时间:2014-12-07 13:41:08

标签: php png transparency gd alpha-transparency

我的图片有不透明度:

enter image description here

当我尝试加载时:

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

它将成为:

enter image description here

我想将此图像添加(合并)到另一个图像(我知道如何合并两个png图像)。 问题是什么?如何在不丢失不透明度的情况下将其加载到GD库?

更新

我的目标是合并一些图像,其中一些图像具有alpha(不同的不透明度,如上图),但是当我合并它们时,alpha信息会丢失。

<?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 个答案:

答案 0 :(得分:5)

只需使用imagecopy功能即可。您可以这样做,因为您的图片内置了透明度,并且您不需要imagecopymerge函数提供的“pct”参数。

您的代码,简化:

<?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图像:

Output PNG

以上示例中使用的三个PNG图像(内容为50%透明,背景为透明,不是白色):

test-1.png test-2.png test-3.png

答案 1 :(得分:3)

你需要启用alpha混合和imagecopymerge从来没有设计为尊重alpha通道(人们试图在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); 
?>