коллаж изображений в PHP

Я ищу финишное решение или, возможно, математику / алгоритмы для создания большого коллажа изображений из изображений меньшего размера? Я знаю, как сделать это в квадратной форме, с изображений того же размера с gd / imagemagick, но я бы хотел, чтобы некоторые вариации были встроены.

Например, некоторые из изображений могут быть немного выше, и если все имеют одинаковый размер и квадрат – я бы хотел, чтобы один из них занимал больше места, просто чтобы смешать дизайн. сохраняя его интересным.

тем больше я думаю об этом, тем сложнее, что это похоже на формулу. с предопределенными «шаблонами» для всех возможных сценариев не будет работать, поскольку количество изображений может варьироваться от 1 (без работы) до 10+.

я не ищу никаких вращений или спецэффектов, просто изображения в сетке, возможно, промежуток между ними и не перекрывается.

любые идеи, как это сделать, и разве действительно нет ничего готового выйти туда?

Я предлагаю вам создать подход к сетке и весу.

Этот ответ разделен на 3 части:

  1. Работа с виртуальной сетью
  2. Случайно удаляйте изображение в эту сетку
  3. Обеспечить прозрачность

Работа с виртуальной сетью

Создайте новое изображение с реальной шириной / высотой (например: 600×800), но также шириной / высотой сетки (например: 10×10). Затем вы можете предоставить изображениям виртуальный размер и виртуальную позицию. Я постараюсь сделать это шаг за шагом, чтобы вы поняли, что я имею в виду.

Прежде всего, для этого нам нужна среда.

class imageGrid { private $realWidth; private $realHeight; private $gridWidth; private $gridHeight; private $image; public function __construct($realWidth, $realHeight, $gridWidth, $gridHeight) { $this->realWidth = $realWidth; $this->realHeight = $realHeight; $this->gridWidth = $gridWidth; $this->gridHeight = $gridHeight; // create destination image $this->image = imagecreatetruecolor($realWidth, $realHeight); // set image default background $white = imagecolorallocate($this->image, 255, 255, 255); imagefill($this->image, 0, 0, $white); } public function __destruct() { imagedestroy($this->image); } public function display() { header("Content-type: image/png"); imagepng($this->image); } } $imageGrid = new imageGrid(800, 600, 10, 10); $imageGrid->display(); 

Это даст нам красивый белый квадрат. Затем нам нужна сетка для отображения изображений. Потому что это, возможно, трудно себе представить, давайте покажем его.

 public function demoGrid() { $black = imagecolorallocate($this->image, 0, 0, 0); imagesetthickness($this->image, 3); $cellWidth = ($this->realWidth - 1) / $this->gridWidth; // note: -1 to avoid writting $cellHeight = ($this->realHeight - 1) / $this->gridHeight; // a pixel outside the image for ($x = 0; ($x <= $this->gridWidth); $x++) { for ($y = 0; ($y <= $this->gridHeight); $y++) { imageline($this->image, ($x * $cellWidth), 0, ($x * $cellWidth), $this->realHeight, $black); imageline($this->image, 0, ($y * $cellHeight), $this->realWidth, ($y * $cellHeight), $black); } } } 

Позвонив:

 $imageGrid = new imageGrid(800, 600, 10, 10); $imageGrid->demoGrid(); $imageGrid->display(); 

Мы можем видеть :

введите описание изображения здесь

Теперь мы хотим знать, как написать прямоугольник 3×4, и вставить его в (2,5) в наши виртуальные меры. Нам нужно искать, как получить реальные размеры и позиции нашего прямоугольника.

 public function demoPutSquare($sizeW, $sizeH, $posX, $posY) { // Cell width $cellWidth = $this->realWidth / $this->gridWidth; $cellHeight = $this->realHeight / $this->gridHeight; // Conversion of our virtual sizes/positions to real ones $realSizeW = ($cellWidth * $sizeW); $realSizeH = ($cellHeight * $sizeH); $realPosX = ($cellWidth * $posX); $realPosY = ($cellHeight * $posY); // Getting top left and bottom right of our rectangle $topLeftX = $realPosX; $topLeftY = $realPosY; $bottomRightX = $realPosX + $realSizeW; $bottomRightY = $realPosY + $realSizeH; // Displaying rectangle $red = imagecolorallocate($this->image, 100, 0, 0); imagefilledrectangle($this->image, $topLeftX, $topLeftY, $bottomRightX, $bottomRightY, $red); } 

Позвонив:

 $imageGrid = new imageGrid(800, 600, 10, 10); $imageGrid->demoGrid(); $imageGrid->demoPutSquare(3, 4, 2, 5); $imageGrid->display(); 

Мы получаем квадрат 3×4, расположенный в (2,5) в нашей сетке:

введите описание изображения здесь

Теперь давайте сделаем это более серьёзно, у нас есть хорошие меры, чтобы мы могли вставить изображение.

 public function putImage($img, $sizeW, $sizeH, $posX, $posY) { // Cell width $cellWidth = $this->realWidth / $this->gridWidth; $cellHeight = $this->realHeight / $this->gridHeight; // Conversion of our virtual sizes/positions to real ones $realSizeW = ceil($cellWidth * $sizeW); $realSizeH = ceil($cellHeight * $sizeH); $realPosX = ($cellWidth * $posX); $realPosY = ($cellHeight * $posY); // Copying the image imagecopyresampled($this->image, $img, $realPosX, $realPosY, 0, 0, $realSizeW, $realSizeH, imagesx($img), imagesy($img)); } 

Позвонив:

 $imageGrid = new imageGrid(800, 600, 10, 10); $imageGrid->demoGrid(); $img = imagecreatefromjpeg("ninsuo.jpg"); $imageGrid->putImage($img, 3, 4, 2, 5); $imageGrid->display(); 

Мы получаем :

введите описание изображения здесь

Таким образом, у нас есть картина в хорошем месте, но мы потеряли соотношение сторон. Давайте добавим метод для правильного изменения нашего изображения.

 public function resizePreservingAspectRatio($img, $targetWidth, $targetHeight) { $srcWidth = imagesx($img); $srcHeight = imagesy($img); $srcRatio = $srcWidth / $srcHeight; $targetRatio = $targetWidth / $targetHeight; if (($srcWidth <= $targetWidth) && ($srcHeight <= $targetHeight)) { $imgTargetWidth = $srcWidth; $imgTargetHeight = $srcHeight; } else if ($targetRatio > $srcRatio) { $imgTargetWidth = (int) ($targetHeight * $srcRatio); $imgTargetHeight = $targetHeight; } else { $imgTargetWidth = $targetWidth; $imgTargetHeight = (int) ($targetWidth / $srcRatio); } $targetImg = imagecreatetruecolor($targetWidth, $targetHeight); imagecopyresampled( $targetImg, $img, ($targetWidth - $imgTargetWidth) / 2, // centered ($targetHeight - $imgTargetHeight) / 2, // centered 0, 0, $imgTargetWidth, $imgTargetHeight, $srcWidth, $srcHeight ); return $targetImg; } 

И как раз перед:

  imagecopyresampled($this->image, $img, $realPosX, $realPosY, 0, 0, $realSizeW, $realSizeH, imagesx($img), imagesy($img)); 

Мы ставим:

  $img = $this->resizePreservingAspectRatio($img, $realSizeW, $realSizeH); 

Это выглядит так:

введите описание изображения здесь

Теперь у нас есть полный функциональный класс, чтобы сделать вашу работу.

 class imageGrid { private $realWidth; private $realHeight; private $gridWidth; private $gridHeight; private $image; public function __construct($realWidth, $realHeight, $gridWidth, $gridHeight) { $this->realWidth = $realWidth; $this->realHeight = $realHeight; $this->gridWidth = $gridWidth; $this->gridHeight = $gridHeight; // create destination image $this->image = imagecreatetruecolor($realWidth, $realHeight); $black = imagecolorallocate($this->image, 0, 0, 0); imagecolortransparent($this->image, $black); } public function __destruct() { imagedestroy($this->image); } public function display() { header("Content-type: image/png"); imagepng($this->image); } public function putImage($img, $sizeW, $sizeH, $posX, $posY) { // Cell width $cellWidth = $this->realWidth / $this->gridWidth; $cellHeight = $this->realHeight / $this->gridHeight; // Conversion of our virtual sizes/positions to real ones $realSizeW = ceil($cellWidth * $sizeW); $realSizeH = ceil($cellHeight * $sizeH); $realPosX = ($cellWidth * $posX); $realPosY = ($cellHeight * $posY); $img = $this->resizePreservingAspectRatio($img, $realSizeW, $realSizeH); // Copying the image imagecopyresampled($this->image, $img, $realPosX, $realPosY, 0, 0, $realSizeW, $realSizeH, imagesx($img), imagesy($img)); } public function resizePreservingAspectRatio($img, $targetWidth, $targetHeight) { $srcWidth = imagesx($img); $srcHeight = imagesy($img); $srcRatio = $srcWidth / $srcHeight; $targetRatio = $targetWidth / $targetHeight; if (($srcWidth <= $targetWidth) && ($srcHeight <= $targetHeight)) { $imgTargetWidth = $srcWidth; $imgTargetHeight = $srcHeight; } else if ($targetRatio > $srcRatio) { $imgTargetWidth = (int) ($targetHeight * $srcRatio); $imgTargetHeight = $targetHeight; } else { $imgTargetWidth = $targetWidth; $imgTargetHeight = (int) ($targetWidth / $srcRatio); } $targetImg = imagecreatetruecolor($targetWidth, $targetHeight); imagecopyresampled( $targetImg, $img, ($targetWidth - $imgTargetWidth) / 2, // centered ($targetHeight - $imgTargetHeight) / 2, // centered 0, 0, $imgTargetWidth, $imgTargetHeight, $srcWidth, $srcHeight ); return $targetImg; } } 

Теперь мы можем играть с ним, чтобы увидеть, работает ли это:

 $imageGrid = new imageGrid(800, 400, 12, 2); $blue = imagecreatefrompng("cheers_blue.png"); $imageGrid->putImage($blue, 6, 2, 0, 0); imagedestroy($blue); $green = imagecreatefrompng("cheers_green.png"); $imageGrid->putImage($green, 2, 1, 6, 0); imagedestroy($green); $red = imagecreatefrompng("cheers_red.png"); $imageGrid->putImage($red, 2, 1, 8, 0); imagedestroy($red); $yellow = imagecreatefrompng("cheers_yellow.png"); $imageGrid->putImage($yellow, 2, 1, 10, 0); imagedestroy($yellow); $purple = imagecreatefrompng("cheers_purple.png"); $imageGrid->putImage($purple, 3, 1, 6, 1); imagedestroy($purple); $cyan = imagecreatefrompng("cheers_cyan.png"); $imageGrid->putImage($cyan, 3, 1, 9, 1); imagedestroy($cyan); $imageGrid->display(); 

введите описание изображения здесь

Лично я предпочитаю тот, не сохраняя соотношение сторон 🙂

введите описание изображения здесь

Ура! (эх, наслаждайся, я бы сказал!)

Случайно удаляйте изображение в эту сетку

Подход состоит в следующем: мы пошамнем все наши образы, чтобы получить случайный массив, и произвольно удалим их по строкам: от 1 до 4 изображений в строке (вы сможете изменить это значение) и будете использовать более высокое изображение в каждой строке для определения высоты каждой линии. Поэтому, если изображение на 50% выше другого, если они не находятся в одной строке, вы сохраните пропорции.

Это немного сложнее, поэтому я решил никогда не использовать графику во время разработки этой части. Вот почему есть много шагов и отладок, но это помогает многому добиться шаг за шагом до конечного результата.

Мы получаем высоту всех наших изображений и их сумму:

 $images = array (); $totalHeight = 0; foreach (glob("images/*.jpg") as $jpg) { $img = imagecreatefromjpeg($jpg); $images[$jpg] = imagesy($img); $totalHeight += $images[$jpg]; imagedestroy($img); } echo "image list with heights:\n"; var_dump($images); echo "total heights: {$totalHeight}\n"; 

Дает нам :

 image list with heights: array(12) { ["images/image1.jpg"]=> int(392) ["images/image10.jpg"]=> int(640) ["images/image11.jpg"]=> int(364) ["images/image12.jpg"]=> int(324) ["images/image2.jpg"]=> int(533) ["images/image3.jpg"]=> int(360) ["images/image4.jpg"]=> int(768) ["images/image5.jpg"]=> int(330) ["images/image6.jpg"]=> int(360) ["images/image7.jpg"]=> int(338) ["images/image8.jpg"]=> int(600) ["images/image9.jpg"]=> int(391) } total heights: 5400 

Затем мы shfuffle массив изображений, чтобы получить случайное расположение изображений. Нам нужно сохранить ключи, а shffle – нет, поэтому нам нужно немного обмануть.

 // Shuffle image array of files preserving keys to get random image disposition $keys = array_keys($images); shuffle($keys); $images = array_merge(array_flip($keys), $images); // Separate image names and heights, will simplify our future work $heights = array_values($images); $images = array_keys($images); echo "image list:\n"; var_dump($images); echo "image heights:\n"; var_dump($heights); 

Дает нам :

 image list: array(12) { [0]=> string(17) "images/image6.jpg" [1]=> string(17) "images/image5.jpg" [2]=> string(18) "images/image10.jpg" [3]=> string(17) "images/image2.jpg" [4]=> string(18) "images/image12.jpg" [5]=> string(17) "images/image3.jpg" [6]=> string(17) "images/image4.jpg" [7]=> string(17) "images/image1.jpg" [8]=> string(17) "images/image8.jpg" [9]=> string(17) "images/image9.jpg" [10]=> string(18) "images/image11.jpg" [11]=> string(17) "images/image7.jpg" } image heights: array(12) { [0]=> int(360) [1]=> int(330) [2]=> int(640) [3]=> int(533) [4]=> int(324) [5]=> int(360) [6]=> int(768) [7]=> int(392) [8]=> int(600) [9]=> int(391) [10]=> int(364) [11]=> int(338) } 

Здесь важно проверить, сохранили ли мы связь изображения / высоты.

Теперь нам нужно преобразовать высоту изображения в проценты: так что если у вас есть 2 изображения, то на 50% выше второго, так что у вас будет 66% общей высоты для вашего первого изображения, а 33% для второго один. Эта виртуальная высота будет использоваться как высота на нашей сетке.

 $count = count($heights); for ($i = 0; ($i < $count); $i++) { $heights[$i] = ($heights[$i] * 100) / $totalHeight } echo "image heights in percents\n"; var_dump($heights); echo "check : " . array_sum($heights) . " = 100\n"; 

Результат в :

 Image heights in percents array(12) { [0]=> float(6.6666666666667) [1]=> float(6.1111111111111) [2]=> float(11.851851851852) [3]=> float(9.8703703703704) [4]=> int(6) [5]=> float(6.6666666666667) [6]=> float(14.222222222222) [7]=> float(7.2592592592593) [8]=> float(11.111111111111) [9]=> float(7.2407407407407) [10]=> float(6.7407407407407) [11]=> float(6.2592592592593) } check : 100 = 100 

Теперь мы создаем массив строк, чтобы увидеть, сколько изображений мы будем помещать на строки. Для этого примера мы хотим от 1 до 4 изображений в строке. Измените здесь rand() % 4 + 1 тем, что вы хотите получить столько изображений, сколько хотите в каждой строке. Пример: rand() % 3 + 2 даст вам от 2 до 5 изображений.

 $lines = array (); while ($count > 0) { $nbImages = rand() % 4 + 1; if (($count - $nbImages) < 0) { $nbImages = $count; } $lines[] = $nbImages; $count -= $nbImages; } echo "Number of lines : " . count($lines) . "\n"; echo "images per line disposition :\n"; var_dump($lines); 

Результат в :

 Number of lines : 5 images per line disposition : array(5) { [0]=> int(3) [1]=> int(1) [2]=> int(1) [3]=> int(4) [4]=> int(3) } 

Нам нужно связать изображение с линией и с позицией в строке. Это поможет нам получить позицию нашего изображения в нашей сетке.

 $imageLines = array(); foreach ($lines as $key => $numberImg) { while ($numberImg--) { $imageLines[] = $key; } } echo "image / line association:\n"; var_dump($imageLines); $imagePositions = array(); foreach ($lines as $numberImg) { for ($i = 0; ($i < $numberImg); $i++) { $imagePositions[] = $i; } } echo "image / position in a line association:\n"; var_dump($imagePositions); 

Результат в :

 image / line association: array(12) { [0]=> int(0) [1]=> int(0) [2]=> int(0) [3]=> int(1) [4]=> int(2) [5]=> int(3) [6]=> int(3) [7]=> int(3) [8]=> int(3) [9]=> int(4) [10]=> int(4) [11]=> int(4) } image / position in a line association: array(12) { [0]=> int(0) [1]=> int(1) [2]=> int(2) [3]=> int(0) [4]=> int(0) [5]=> int(0) [6]=> int(1) [7]=> int(2) [8]=> int(3) [9]=> int(0) [10]=> int(1) [11]=> int(2) } 

Теперь нам нужно получить полную ширину нашего изображения. У нас есть от 1 до 4 изображений, поэтому для получения целого размера каждого изображения независимо от количества изображений в каждой строке мы умножаем 4 (максимальные значения) на все значения от 4 до 1. В этом случае: 4 * 3 * 2 * 1 = 24, поэтому, если у нас есть 1 изображение / строка, ширина будет 24, 2 изображения / строка: 24/2 = 12, 3 изображения / строка: 24/3 = 8, 4 изображения / строка: 24 / 4 = 6. Все являются действительными целыми числами.

 $i = 4; $virtualWidth = 1; while ($i) { $virtualWidth *= $i--; } echo "virtual width: {$virtualWidth}\n"; 

Здесь нет ничего сложного, это приводит к:

 virtual width: 24 

Нам нужно определить высоту каждой строки, в соответствии с самым высоким изображением на строку. Мы также можем вывести нашу высоту сетки в этом расчете.

 // Determine the virtual height needed for each line and for the whole grid $imageHeights = array(); $index = 0; foreach ($lines as $key => $numberImages) { $slice = array_slice($heights, $index, $numberImages); echo "at line {$key}, images heights are:\n"; var_dump($slice); $imageHeights[] = max($slice); $index += $numberImages; } $virtualHeight = array_sum($imageHeights); echo "heights for each line:\n"; var_dump($imageHeights); echo "total height = {$virtualHeight}\n"; 

Это приводит к:

 at line 0, images heights are: array(3) { [0]=> float(6.6666666666667) [1]=> float(6.1111111111111) [2]=> float(11.851851851852) } at line 1, images heights are: array(1) { [0]=> float(9.8703703703704) } at line 2, images heights are: array(1) { [0]=> int(6) } at line 3, images heights are: array(4) { [0]=> float(6.6666666666667) [1]=> float(14.222222222222) [2]=> float(7.2592592592593) [3]=> float(11.111111111111) } at line 4, images heights are: array(3) { [0]=> float(7.2407407407407) [1]=> float(6.7407407407407) [2]=> float(6.2592592592593) } heights for each line: array(5) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) [3]=> float(14.222222222222) [4]=> float(7.2407407407407) } total height = 49.185185185185 

Мы проверяем этот результат, если у нас есть наибольшее значение для каждой строки, и если сумма действительна.

Наконец, у нас есть вся информация, необходимая для отображения нашей сетки случайных изображений.

 $imageGrid = new imageGrid(800, 800, $virtualWidth, $virtualHeight); foreach (glob("images/*.jpg") as $jpg) { $img = imagecreatefromjpeg($jpg); $index = array_search($jpg, $images); echo "image {$index}:\n"; $line = $imageLines[$index]; echo "image is at line {$line}\n"; $sizeW = ($virtualWidth / $lines[$line]); echo "width = {$virtualWidth} / {$lines[$line]} = {$sizeW}\n"; $sizeH = $imageHeights[$line]; echo "height = {$imageHeights[$line]}\n"; $posX = $imagePositions[$index] * ($virtualWidth / $lines[$line]); echo "pos X = {$imagePositions[$index]} * ({$virtualWidth} / {$lines[$line]}) = {$posX}\n"; $slice = array_slice($imageHeights, 0, $line); echo "Slice to calc Y:\n"; var_dump($slice); $posY = array_sum($slice); echo "pos Y = {$posY}\n"; echo "\n"; $imageGrid->putImage($img, $sizeW, $sizeH, $posX, $posY); imagedestroy($img); } 

Это приводит к:

 image 7: image is at line 3 width = 24 / 4 = 6 height = 14.222222222222 pos X = 2 * (24 / 4) = 12 Slice to calc Y: array(3) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) } pos Y = 27.722222222222 image 2: image is at line 0 width = 24 / 3 = 8 height = 11.851851851852 pos X = 2 * (24 / 3) = 16 Slice to calc Y: array(0) { } pos Y = 0 image 10: image is at line 4 width = 24 / 3 = 8 height = 7.2407407407407 pos X = 1 * (24 / 3) = 8 Slice to calc Y: array(4) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) [3]=> float(14.222222222222) } pos Y = 41.944444444444 image 4: image is at line 2 width = 24 / 1 = 24 height = 6 pos X = 0 * (24 / 1) = 0 Slice to calc Y: array(2) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) } pos Y = 21.722222222222 image 3: image is at line 1 width = 24 / 1 = 24 height = 9.8703703703704 pos X = 0 * (24 / 1) = 0 Slice to calc Y: array(1) { [0]=> float(11.851851851852) } pos Y = 11.851851851852 image 5: image is at line 3 width = 24 / 4 = 6 height = 14.222222222222 pos X = 0 * (24 / 4) = 0 Slice to calc Y: array(3) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) } pos Y = 27.722222222222 image 6: image is at line 3 width = 24 / 4 = 6 height = 14.222222222222 pos X = 1 * (24 / 4) = 6 Slice to calc Y: array(3) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) } pos Y = 27.722222222222 image 1: image is at line 0 width = 24 / 3 = 8 height = 11.851851851852 pos X = 1 * (24 / 3) = 8 Slice to calc Y: array(0) { } pos Y = 0 image 0: image is at line 0 width = 24 / 3 = 8 height = 11.851851851852 pos X = 0 * (24 / 3) = 0 Slice to calc Y: array(0) { } pos Y = 0 image 11: image is at line 4 width = 24 / 3 = 8 height = 7.2407407407407 pos X = 2 * (24 / 3) = 16 Slice to calc Y: array(4) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) [3]=> float(14.222222222222) } pos Y = 41.944444444444 image 8: image is at line 3 width = 24 / 4 = 6 height = 14.222222222222 pos X = 3 * (24 / 4) = 18 Slice to calc Y: array(3) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) } pos Y = 27.722222222222 image 9: image is at line 4 width = 24 / 3 = 8 height = 7.2407407407407 pos X = 0 * (24 / 3) = 0 Slice to calc Y: array(4) { [0]=> float(11.851851851852) [1]=> float(9.8703703703704) [2]=> int(6) [3]=> float(14.222222222222) } pos Y = 41.944444444444 

Чтобы отладить наш код, мы заканчиваем его:

 $debug = true; if ($debug) { echo ob_get_clean(); } else { ob_clean(); $imageGrid->display(); } 

Okey, у вас есть все шаги здесь. Как насчет результата?

введите описание изображения здесь

F5 …

введите описание изображения здесь

F5 …

введите описание изображения здесь

Итоговый код:

 ob_start(); echo '<pre>'; // Get height of all images $images = array (); $totalHeight = 0; foreach (glob("images/*.jpg") as $jpg) { $img = imagecreatefromjpeg($jpg); $images[$jpg] = imagesy($img); $totalHeight += $images[$jpg]; imagedestroy($img); } echo "image list with heights:\n"; var_dump($images); // Shuffle image array of files preserving keys to get random image disposition $keys = array_keys($images); shuffle($keys); $images = array_merge(array_flip($keys), $images); // Separate image names and heights, will simplify our future work $heights = array_values($images); $images = array_keys($images); echo "image list:\n"; var_dump($images); echo "total heights: {$totalHeight}\n"; echo "image heights:\n"; var_dump($heights); // Get percentage of image height compared to the total height $count = count($heights); for ($i = 0; ($i < $count); $i++) { $heights[$i] = ($heights[$i] * 100) / $totalHeight; // becomes virtual height in a x100 grid } echo "image heights in percents\n"; var_dump($heights); echo "check : " . array_sum($heights) . " = 100\n"; // Get random number of images per line and number of lines // Between 1 to 4 images/line until there is no more image. $lines = array (); while ($count > 0) { $nbImages = rand() % 4 + 1; if (($count - $nbImages) < 0) { $nbImages = $count; } $lines[] = $nbImages; $count -= $nbImages; } echo "Number of lines : " . count($lines) . "\n"; echo "images per line disposition :\n"; var_dump($lines); // Associate an image with a line $imageLines = array(); foreach ($lines as $key => $numberImg) { while ($numberImg--) { $imageLines[] = $key; } } echo "image / line association:\n"; var_dump($imageLines); // Associate an image with a position in a line $imagePositions = array(); foreach ($lines as $numberImg) { for ($i = 0; ($i < $numberImg); $i++) { $imagePositions[] = $i; } } echo "image / position in a line association:\n"; var_dump($imagePositions); // We have from 1 to 4 images/line so we create a grid with a virtual width of 1*2*3*4. // In this case, 1 image/line = 24, 2/line =24/2=12, 3/line=24/3=8, all are valid integers. $i = 4; $virtualWidth = 1; while ($i) { $virtualWidth *= $i--; } echo "virtual width: {$virtualWidth}\n"; // Determine the virtual height needed for each line and for the whole grid $imageHeights = array(); $index = 0; foreach ($lines as $key => $numberImages) { $slice = array_slice($heights, $index, $numberImages); echo "at line {$key}, images heights are:\n"; var_dump($slice); $imageHeights[] = max($slice); $index += $numberImages; } $virtualHeight = array_sum($imageHeights); echo "heights for each line:\n"; var_dump($imageHeights); echo "total height = {$virtualHeight}\n"; // Create a grid and place logically all images in the virtual area $imageGrid = new imageGrid(800, 800, $virtualWidth, $virtualHeight); foreach (glob("images/*.jpg") as $jpg) { $img = imagecreatefromjpeg($jpg); // Determine position $index = array_search($jpg, $images); echo "image {$index}:\n"; $line = $imageLines[$index]; echo "image is at line {$line}\n"; $sizeW = ($virtualWidth / $lines[$line]); echo "width = {$virtualWidth} / {$lines[$line]} = {$sizeW}\n"; $sizeH = $imageHeights[$line]; echo "height = {$imageHeights[$line]}\n"; $posX = $imagePositions[$index] * ($virtualWidth / $lines[$line]); echo "pos X = {$imagePositions[$index]} * ({$virtualWidth} / {$lines[$line]}) = {$posX}\n"; $slice = array_slice($imageHeights, 0, $line); echo "Slice to calc Y:\n"; var_dump($slice); $posY = array_sum($slice); echo "pos Y = {$posY}\n"; echo "\n"; $imageGrid->putImage($img, $sizeW, $sizeH, $posX, $posY); imagedestroy($img); } $debug = false; if ($debug) { echo ob_get_clean(); } else { ob_clean(); $imageGrid->display(); } 

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

Обеспечить прозрачность

Сначала по методу __construct замените:

  $white = imagecolorallocate($this->image, 255, 255, 255); imagefill($this->image, 0, 0, $white); 

От :

  $transparent = imagecolorallocate($this->image, 255, 0, 255); imagefill($this->image, 0, 0, $transparent); imagecolortransparent($this->image, $transparent); 

Затем, в режиме resizePreservingAspectRatio , добавьте сразу после:

  $targetImg = imagecreatetruecolor($targetWidth, $targetHeight); 

Следующие строки:

  $targetTransparent = imagecolorallocate($targetImg, 255, 0, 255); imagefill($targetImg, 0, 0, $targetTransparent); imagecolortransparent($targetImg, $targetTransparent); 

И здесь мы идем.

введите описание изображения здесь