【问题标题】:imagecopymerge does not work correctly with partially transparent imagesimagecopymerge 不能正确处理部分透明的图像
【发布时间】:2015-02-05 05:40:35
【问题描述】:

我有一张不透明的图片:

当我尝试加载它时:

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

它会变成:

我想将此图像与另一个图像添加(合并)(我知道如何合并两个 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);

【问题讨论】:

    标签: php png transparency gd alpha-transparency


    【解决方案1】:

    您需要启用 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); 
    ?>
    

    【讨论】:

    • tnx 为您解答,它单独工作,但我还有问题,我更新问题。
    【解决方案2】:

    只需使用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图片:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-24
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 2019-09-21
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      相关资源
      最近更新 更多