2016-07-14 8 views
0

Я хотел бы объединить несколько png с прозрачным фоном в одно изображение. Изображения имеют разные размеры, и из-за этого, когда изображения расположены поверх друг друга, только в пределах размера самого верхнего изображения отображаются части объединенных изображений.Как объединить несколько прозрачных png с разным размером в одно изображение без обрезки, используя библиотеку PHP GD?

Это похоже на то, что последнее изображение применяется как маска для изображений, объединенных ранее. Я хотел бы, чтобы все изображения были объединены с их первоначальным размером, без обрезки частей, зависающих над размером последнего изображения.

Вот код, я использую в настоящее время:

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

Источник изображения обрезаются, потому что 'imagecopy' указывает копировать только из х0, у0 (Params 5 & 6) к X458, Y600 (PARAMS 7 & 8). Ваше утверждение «все изображения, объединенные с их первоначальным размером», противоречит вашему коду: 'imagecreatetruecolor (458, 600);'. Вам нужно либо сделать '$ destination' больше (по крайней мере столь же большим, как и самое большое исходное изображение), либо изменить размер исходных изображений, чтобы они соответствовали 458x600. Что ты хочешь делать? – timclutton

+0

Я хотел бы сделать приложение, в котором люди могут щелкнуть по частям изображения двери, и сценарий объединит их в один окончательный вариант. Размер изображения результата должен быть 458x600, а изображения разных размеров должны быть объединены в пределах этого размера. Моя проблема заключалась в том, что изображение двери больше, чем изображение дверной ручки, которое является последним, и в пределах этого 458x600 части объединенных изображений были видны только в размере изображения дверной ручки, а остальное окончательное изображение 458x600 было черным. Я хотел положить дверную ручку в дверь, когда люди нажимают на это изображение. – emipac

ответ

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; 

 Смежные вопросы

  • Нет связанных вопросов^_^