如何使用PHP GD库将不同大小的多个透明png合并到一个图像中而不进行裁剪?

时间:2016-07-14 12:31:00

标签: php merge png php-gd

我想将透明背景的多个png合并到一个图像中。图像具有不同的尺寸,因此,当图像被放置在彼此的顶部上时,仅在最上面的图像的尺寸内显示合并图像的部分。

就像最后一张图像适用于之前合并的图像的蒙版一样。我希望看到所有图像都与原始尺寸合并,而不会裁剪掉最后一张图像大小的部分。

这是我目前正在使用的代码:

$images = array();
    foreach (scandir($this->img_dir) as $key => $dirname) {
        if(!strstr($dirname, "."))
        {
            if(isset($_GET[$dirname])) 
            {
                foreach ($this->layer_order as $lkey => $order) {
                    if($lkey == $dirname)
                        $images[$order] = glob($this->img_dir . "/" . $dirname . "/" . $_GET[$dirname] . ".png");
                }
            }
        }
    }


    $destination = imagecreatetruecolor(458, 600);


    imagealphablending($destination, true);
    imagesavealpha($destination, true);

    ksort($images);
    foreach($images as $key => $value) {        
        foreach ($value as $fn) {
            // Load image
            $source = imagecreatefrompng($fn);
            //$source = $this->resize_image($source, 50, 50, 2);

            // Copy over image
            imagecopy($destination, $source, 10, 50, 0, 0, 458, 600);

            // Free memory
            imagedestroy($source);
        }
    }

    return $destination;

1 个答案:

答案 0 :(得分:1)

我不知道这是否是我试图实现的最佳解决方案,但经过多次尝试和一些研究后,我使用了一种相当简单的方法来避免合并队列中的最后一个图像,掩盖其他图像它的尺寸相对较小。这样,每个图像将根据用户的需要在指定的画布大小内以其透明度进行合并和定位。

如果有人需要类似的解决方案,我会发布该功能的全部内容。这是一个类中的函数。

    $images = array();

    // Foreach loop to set images order and creating an array with image paths using params from $_GET before merging
    foreach (scandir($this->img_dir) as $key => $dirname) {
        if(!strstr($dirname, "."))
        {
            if(isset($_GET[$dirname])) 
            {
                foreach ($this->layer_order as $lkey => $order) {
                    if($lkey == $dirname) {
                        $imageArray = glob($this->img_dir . "/" . $dirname . "/" . ($dirname == "door" && isset($_GET['type']) ? $_GET['type']."/" : "") . $_GET[$dirname] . ".png");
                        foreach ($imageArray as $imgPath) {
                            $images[$order] = $imgPath;
                        }
                    }       
                }
            }
        }
    }

    // Allocate new image
    $destination = imagecreatetruecolor($this->canvas_width, $this->canvas_height);

    imagealphablending($destination, false);
    $col = imagecolorallocatealpha($destination, 255, 255, 255, 127);
    imagefilledrectangle($destination, 0, 0, $this->canvas_width, $this->canvas_height, $col);
    imagealphablending($destination, true);

    // Sort order
    ksort($images);

    // Merging images
    foreach($images as $key => $fn) {

        // Load image
        if(strstr($fn, "handle")) 
        {
            $source = $this->resizePng($fn, 0.18, 100, 205);
            imagecopy($destination, $source, 0, 0, 0, 0, $this->canvas_width, $this->canvas_height);
        }
        elseif (strstr($fn, "glass")) 
        {
            // Create a background image by filling a canvas with small image tiles. Params: $file, $shrink_ratio_percent, $column_size, $stretch
            $source = $this->multiplyMergeAndResizePngs($fn, 0.2095, 3, 3.6);
            // Applying mask on images based on black and white patterns
            if ($this->glass_mask)
                $source = $this->createMask($source, $this->glass_mask);
            imagecopy($destination, $source, 118, 28, 0, 0, $this->canvas_width, $this->canvas_height);
        }
        elseif (strstr($fn, "door")) 
        {    
            $source = imagecreatefrompng($fn);
            imagecopy($destination, $source, 32, 0, 0, 0, $this->canvas_width, $this->canvas_height);
        } else {
            $source = imagecreatefrompng($fn);
            imagecopy($destination, $source, 0, 0, 0, 0, $this->canvas_width, $this->canvas_height);
        }

        imagealphablending($destination, true);

        // Free memory
        imagedestroy($source);
    }

    return $destination;