2012-10-16 43 views
9

我正在尋找一個finshed的解決方案或可能一些數學/算法創建一個大的圖像拼貼出較小的產品圖片? 我知道如何做一個方形的時尚,從gd/imagemagick相同大小的圖片,但我想有一些內置的變化。在PHP中的圖像拼貼

例如,一些圖片可能會稍高,如果所有的都是相同的大小和方形 - 我可能希望其中一個佔用更多的空間,只是混淆了設計。保持有趣。

我越想越想這個,它似乎用一個公式來做就越困難。爲所有可能的場景預定義「模板」並不奏效,因爲圖片的數量可能會從1(不需要工作)變爲10+。

我不是在尋找任何旋轉或特殊效果,只是在網格中的圖像可能有一定的間距,並且沒有重疊。

任何想法如何實現這一點,是否真的沒有準備好去那裏?

回答

23

我建議你創建一個網格和重量的方法。

這個答案分爲3種類型分爲:

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

哇。可能是最廣泛的答案永遠。非常非常感謝你!這一定會爲我節省一大筆時間來開展一些工作。 現在我的主要問題是要計算如何將圖像放置在網格中..我需要嘗試跟蹤不同的圖像大小,並動態計算最優化的佈局,以便如何使用「$ imageGrid-> putImage($ blue,6,2,0,0);「 - 有任何想法嗎? –

+0

很高興看到這個答案可以幫助你。是的,您可以通過以下方式動態確定體重:1)製作所有圖像寬度/高度的總和,2)使用此總和獲取每個圖像寬度/高度的百分比,3)創建一個100x100的網格並使用這些百分比。我現在的工作現在無法幫助你,所以讓我知道如果你需要一個例子,我今晚可以寫下它(gmt + 2)。 –

+0

嗨,謝謝!我不確定我是否理解這將如何動態確定定位 - 所以一個例子會很棒。也許我只需要再想一想,並重新閱讀你寫的所有內容。但是,在你寫給我的那本小說後,我有點慚愧地問你,哈哈。不用擔心,我並不着急! –

19

與虛擬網格

創建一個新的形象的工作,一個真正的寬度/高度(例如:600x800),而且網格寬度/ h八(例如:10x10)。然後,您可以爲圖像提供虛擬尺寸和虛擬位置。我會盡力讓它一步一步地讓你理解我的意思。

首先,我們需要一個環境。

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

我們可以看到:

enter image description here

現在,我們想知道如何編寫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)positionned方:

enter image description here

現在讓我們更seriousely,我們有很好的措施,以便我們可以粘貼圖像。

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

我們得到:

enter image description here

這樣,我們在好地方的圖片,但我們失去的縱橫比。讓我們添加一個方法來正確調整我們的圖像。

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

這是這樣的:

enter image description here

我們現在有一個完整的functionnalÇ做你的工作。

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

enter image description here

Personnally,我更喜歡一個不保留長寬比:-)

enter image description here

乾杯! (!嗯,享受我會說)

+0

謝謝!好的代碼;) –

+0

謝謝!有沒有辦法將拼貼圖像保存爲不同名稱的dir? @Alain Tiemblo –

5

隨機配置的圖像成網格

的方法是:我們會動搖我們的所有圖像,以得到一個隨機排列,並隨機處置他們行: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圖像陣列來獲得圖像的隨機配置。我們需要保存密鑰,並且密碼沒有,所以我們需要一點小技巧。

// 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% %爲第二個。這個虛擬高度將被用作我們網格的高度。

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

歐凱,你在這裏的所有步驟。結果呢?

enter image description here

F5 ......

enter image description here

F5 ......

enter image description here

最終代碼:

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

我的方法可能不是最好的方法,但至少它可以讓您將圖像隨機定位到保留圖像重量的網格中。這個問題很難處理,所以我希望這對你的情況足夠了。

+0

這比我所希望的還要多,簡直太棒了!謝謝。 –

5

實現透明度

首先對__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); 

然後我們開始吧。

enter image description here