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


How to merge multiple transparent pngs with different size into one image without cropping, using PHP GD library?

我想将多个具有透明背景的 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;

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

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

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