2012-10-16 13 views
9

Szukam rozwiązania finshed lub ewentualnie matematyki/algorytmów do tworzenia dużego kolażu zdjęć z mniejszych zdjęć produktów? Wiem, jak to zrobić w kwadratowej modzie, z tych samych rozmiarów zdjęć z gd/imagemagick, ale chciałbym mieć wbudowaną wariację.Kolaż obrazów w PHP

Na przykład niektóre zdjęcia mogą być nieco wyższe, a jeśli wszystkie są tego samego rozmiaru i kwadratu - mogę chcieć, aby jeden z nich zajmował więcej miejsca, tylko by wymieszać projekt. zachowując to interesująco.

Im więcej o tym myślę, tym trudniej, jak się wydaje, z formułą. posiadanie wstępnie zdefiniowanych "szablonów" dla wszystkich możliwych scenariuszy nie zadziała, ponieważ ilość zdjęć może różnić się od 1 (bez pracy) do 10+.

Nie szukam żadnych efektów rotacyjnych ani specjalnych, tylko obrazy w siatce z możliwością odstępu między nimi i bez nakładania się.

wszelkie pomysły, jak to osiągnąć, i czy naprawdę nic nie jest gotowe, aby tam wyjść?

Odpowiedz

23

Proponuję stworzyć podejście do siatki i ciężaru.

Ta odpowiedź jest podzielony na 3 części:

  1. Working with a virtual grid
  2. Randomly dispose image into that grid
  3. Implement transparency
+0

Wow. Prawdopodobnie najszersza odpowiedź KIEDYKOLWIEK. Dziękuję bardzo, bardzo! To na pewno zaoszczędzi mnóstwa czasu na prace przy ziemi, aby coś się zaczęło! Moim głównym problemem byłoby teraz obliczenie, w jaki sposób obrazy zostaną umieszczone w siatce. Muszę spróbować śledzić różne rozmiary obrazów i dynamicznie obliczyć najbardziej zoptymalizowany układ, aby umieścić je za pomocą "$ imageGrid-> putImage ($ blue, 6, 2, 0, 0); " - jakieś pomysły? –

+0

Cieszę się, że ta odpowiedź pomaga.Tak, możesz dynamicznie określić wagę w ten sposób: 1) zsumuj wszystkie swoje obrazy, szerokość/wysokość, 2) uzyskaj procent każdej szerokości/wysokości obrazu przy użyciu tej sumy, 3) utwórz siatkę o wymiarach 100 x 100 i użyj tych wartości procentowych. Jestem w pracy, nie mogę ci teraz więcej pomóc, więc daj mi znać, jeśli potrzebujesz przykładu, będę mógł napisać to dziś wieczorem (gmt + 2). –

+0

Cześć, i dzięki! Nie jestem pewien, czy rozumiem, w jaki sposób to pomoże w dynamicznym określaniu pozycji - więc przykład byłby świetny. Może po prostu muszę o tym pomyśleć i ponownie przeczytać wszystko, co napisałeś. Ale trochę wstydzę się prosić o więcej z was po tej powieści, którą właśnie napisaliście, haha. Bez obaw, nie spieszę się! –

19

Praca z wirtualną siecią

utworzyć nowy obraz, z prawdziwym szerokość/wysokość (np. 600x800), ale także szerokość siatki/godz osiem (np. 10x10). Następnie możesz dać obrazowi wirtualny rozmiar i wirtualną pozycję. Spróbuję zrobić to krok po kroku, aby zrozumieć, co mam na myśli.

Przede wszystkim potrzebujemy do tego środowiska.

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(); 

To da nam piękny biały kwadrat. Następnie potrzebujemy siatki do wyświetlania obrazów. Ponieważ trudno to sobie wyobrazić, pokażmy to.

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); 
     } 
    } 
} 

pod numerem:

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

Widzimy:

enter image description here

Teraz chcemy wiedzieć, jak napisać prostokąt 3x4, i wklej go do (2 5) w naszych wirtualnych miarach. Musimy szukać, jak uzyskać rzeczywiste rozmiary i pozycje naszego prostokąta.

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); 
} 

pod numerem:

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

Dostajemy kwadrat 3x4 positionned punkcie (2,5) w naszej sieci:

enter image description here

Teraz przejdźmy go bardziej seriousely, mamy dobre środki, abyśmy mogli wkleić obraz.

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)); 
} 

pod numerem:

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

Dostajemy:

enter image description here

ten sposób mamy obraz w dobrym miejscu, ale stracił proporcji. Dodajmy metodę, aby poprawnie zmienić rozmiar naszego obrazu.

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

A tuż przed:

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

Kładziemy:

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

to wyglądać tak:

enter image description here

Teraz mamy pełną functionnal c Lass, aby wykonać swoją pracę.

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

} 

Możemy teraz bawić się z nim, aby sprawdzić, czy to działa:

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

enter image description here

Personnally, wolę jeden bez zachowania proporcji :-)

enter image description here

Pozdrawiam! (! Eh, cieszyć Powiedziałbym)

+0

Dziękujemy! Nice code;) –

+0

Dziękujemy! Czy istnieje sposób na zapisanie obrazu kolażu w katalogu z inną nazwą? @Alain Tiemblo –

5

Losowo dysponowania obraz do tej siatki

Podejście jest: będziemy trząść wszystkie obrazy, aby uzyskać losowy tablicę i usuwać je losowo na liniach: 1 do 4 zdjęć na linię (będziesz mógł zmienić tę wartość) i użyje wyższego obrazu w każdej linii do określenia wysokości każdej linii. Jeśli więc obraz jest o 50% wyższy niż inny, jeśli nie znajduje się w tej samej linii, zachowasz proporcje.

To trochę trudniejsze, więc postanowiłem nigdy nie używać grafiki podczas opracowywania tej części. Dlatego jest wiele kroków i debugowania, ale to bardzo pomaga krok po kroku osiągnąć końcowy wynik.

Dostajemy wysokość wszystkich naszych zdjęć i sumę nich:

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

daje nam:

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 

Potem shfuffle tablicę obrazu, aby uzyskać losowe rozmieszczenie obrazów. Musimy zachować klucze, a shffle nie, więc musimy trochę oszukać.

// 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); 

daje nam:

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) 
} 

Ważną rzeczą jest to, aby sprawdzić, czy mamy zachowane stowarzyszenie image/wysokość.

Teraz musimy przekonwertować wysokość obrazu na wartość procentową: więc jeśli masz 2 obrazy, jeden jest o 50% wyższy niż drugi, więc będziesz mieć 66% całkowitej wysokości dla pierwszego obrazu, a 33 % dla drugiego. Ta wirtualna wysokość będzie używana jako wysokość na naszej siatce.

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

spowodować:

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 

Teraz wygenerować tablicę wierszy, aby zobaczyć, ile obrazów stawiamy na linie. W tym przykładzie potrzebujemy od 1 do 4 obrazów na linię. Zmień tutaj rand() % 4 + 1 według tego, co chcesz, aby uzyskać dowolną liczbę obrazów w linii. Przykład: rand() % 3 + 2 dostarczy Ci od 2 do 5 zdjęć.

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

spowodować:

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) 
} 

Musimy skojarzyć obraz z linii iz pozycji w kolejce. To pomoże nam uzyskać pozycję naszego obrazu w naszej sieci.

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

spowodować:

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) 
} 

Teraz musimy uzyskać całkowitą szerokość naszego wizerunku. Mamy od 1 do 4 zdjęć, więc aby uzyskać liczbę całkowitą każdego obrazu, niezależnie od liczby obrazów na linię mamy, mnożymy 4 (wartości maksymalne) przez wszystkie wartości od 4 do 1. W tym przypadku: 4 * 3 * 2 * 1 = 24, więc jeśli mamy 1 obraz/linię, jego szerokość będzie wynosić 24, 2 obrazy/linia: 24/2 = 12, 3 obrazy/linia: 24/3 = 8, 4 obrazy/linia: 24/4 = 6. Wszystkie są poprawnymi liczbami całkowitymi.

$i = 4; 
$virtualWidth = 1; 
while ($i) 
{ 
    $virtualWidth *= $i--; 
} 

echo "virtual width: {$virtualWidth}\n"; 

Nic nie trudno tutaj, skutkuje:

virtual width: 24 

Musimy teraz ustalić wysokość każdej linii, zgodnie z najwyższym obrazem na linii. Możemy również wywnioskować naszą wysokość siatki w tych obliczeniach.

// 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"; 

Wynika to z:

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 

Sprawdzimy w ten wynik, jeśli mamy najwyższą wartość dla każdej linii, a jeśli suma jest ważna.

W końcu mamy wszystkie informacje, których potrzebujemy, aby wyświetlić naszą siatkę losowo ustawionych obrazów.

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

To skutkuje:

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 

Do debugowania kodu, kończymy go z:

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

Okey, masz tu wszystkie kroki. A co z wynikiem?

enter image description here

F5 ...

enter image description here

F5 ...

enter image description here

kod końcowa:

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(); 
} 

Moje podejście prawdopodobnie nie jest najlepsze, ale przynajmniej daje losowe pozycjonowanie obrazów w siatkę, zachowując wagę obrazów. Temat jest dość trudny w obsłudze, więc mam nadzieję, że będzie to wystarczające dla twojej sprawy.

+0

To więcej niż kiedykolwiek miałem nadzieję, po prostu niesamowite! Dziękuję Ci. –

5

realizacji przejrzystości

najpierw na metodzie __construct wymienić:

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

przez:

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

Następnie na metodzie resizePreservingAspectRatio, dodać tylko po:

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

W następujących wierszach:

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

I oto idziemy.

enter image description here