2012-10-16 44 views
9

Tôi đang tìm một giải pháp finshed hoặc có thể một số toán học/thuật toán để tạo ra một hình ảnh lớn cắt dán ra khỏi hình ảnh sản phẩm nhỏ hơn? Tôi biết cách làm điều đó theo kiểu hình vuông, từ những hình ảnh có kích thước tương tự với gd/imagemagick nhưng tôi muốn có một số biến thể được tích hợp.cắt dán hình ảnh trong PHP

Ví dụ: một số ảnh có thể cao hơn một chút và nếu tất cả đều có cùng kích thước và hình vuông - tôi có thể muốn 1 trong số đó chiếm nhiều không gian hơn, chỉ để trộn thiết kế. giữ nó thú vị.

tôi càng nghĩ về điều này thì càng khó thực hiện với công thức. có "mẫu" được xác định trước cho tất cả các tình huống có thể sẽ không hoạt động vì số lượng ảnh có thể thay đổi chỉ từ 1 (không cần đến công việc) đến 10+.

Tôi không tìm kiếm bất kỳ hiệu ứng quay hoặc hiệu ứng đặc biệt nào, chỉ các hình ảnh trong lưới có thể có khoảng cách giữa các khoảng trống và không chồng chéo.

bất kỳ ý tưởng nào về cách thực hiện việc này và thực sự không có gì sẵn sàng để ra khỏi đó không?

Trả lời

23

Tôi khuyên bạn nên tạo phương pháp tiếp cận trọng lượng và lưới.

Câu trả lời này được chia thành 3 phần:

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

Wow. Có lẽ câu trả lời rộng nhất EVER. Cảm ơn bạn rất, rất nhiều! Điều này chắc chắn sẽ tiết kiệm cho tôi một bó thời gian cho công việc mặt đất trong việc bắt đầu một cái gì đó! Vấn đề chính của tôi bây giờ sẽ là tính toán hình ảnh sẽ được đặt trong lưới như thế nào .. Tôi cần thử và theo dõi các kích thước hình ảnh khác nhau và tự động tính toán bố cục tối ưu nhất để đặt chúng với "$ imageGrid-> putImage ($ blue, 6, 2, 0, 0); " - bất kỳ ý tưởng nào? –

+0

Vui mừng khi thấy câu trả lời này sẽ giúp bạn.Có, bạn có thể xác định trọng số theo cách này: 1) tổng hợp tất cả chiều rộng/chiều cao của hình ảnh, 2) nhận tỷ lệ phần trăm của mỗi chiều rộng/chiều cao của ảnh bằng cách sử dụng tổng này, 3) tạo một mạng lưới 100x100 và sử dụng các tỷ lệ phần trăm đó. Tôi đang làm việc không thể giúp bạn nhiều hơn ngay bây giờ vì vậy hãy cho tôi biết nếu bạn cần một ví dụ, tôi sẽ có thể viết nó tối nay (gmt + 2). –

+0

Xin chào và cảm ơn! Tôi không chắc tôi hiểu làm thế nào mà sẽ giúp xác định vị trí động - vì vậy một ví dụ sẽ là tuyệt vời. Có lẽ tôi chỉ cần suy nghĩ về nó một số chi tiết, và đọc lại tất cả mọi thứ bạn đã viết. Nhưng tôi hơi xấu hổ khi hỏi bạn nhiều hơn sau cuốn tiểu thuyết mà bạn vừa viết cho tôi, haha. Đừng lo, tôi không vội vàng! –

19

Làm việc với một mạng lưới ảo

Tạo một hình ảnh mới, với một thực chiều rộng/chiều cao (ví dụ: 600x800), nhưng cũng có chiều rộng lưới/h tám (ví dụ: 10x10). Sau đó, bạn có thể cho hình ảnh một kích thước ảo và vị trí ảo. Tôi sẽ cố gắng làm cho nó từng bước để làm cho bạn hiểu những gì tôi có ý nghĩa.

Trước hết, chúng tôi cần một môi trường cho việc này.

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

Điều này sẽ cho chúng ta một hình vuông màu trắng tuyệt đẹp. Sau đó, chúng ta cần một lưới để hiển thị hình ảnh. Bởi vì đó có lẽ là khó tưởng tượng, chúng ta hãy hiển thị nó.

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

Bằng cách gọi:

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

Chúng ta có thể thấy:

enter image description here

Bây giờ, chúng tôi muốn biết làm thế nào để viết một hình chữ nhật của 3x4, và dán nó vào (2 , 5) trong các biện pháp ảo của chúng tôi. Chúng ta cần phải tìm cách để có được kích thước và vị trí thực của hình chữ nhật.

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

Bằng cách gọi:

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

Chúng tôi nhận được một hình vuông 3x4 positionned tại (2,5) trong lưới của chúng tôi:

enter image description here

Bây giờ chúng ta hãy làm cho nó seriousely hơn, chúng tôi có các biện pháp tốt để chúng tôi có thể dán hình ảnh.

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

Bằng cách gọi:

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

Chúng tôi nhận được:

enter image description here

Bằng cách đó chúng ta có một bức tranh ở vị trí tốt, nhưng chúng tôi bị mất tỉ lệ khung hình. Hãy thêm một phương thức để thay đổi kích thước chính xác hình ảnh của chúng ta.

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

Và ngay trước khi:

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

Chúng tôi đặt:

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

này trông như thế này:

enter image description here

Bây giờ chúng ta có một functionnal đầy đủ c lass để thực hiện công việc của bạn.

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

} 

Bây giờ chúng ta có thể chơi với nó để xem nếu nó hoạt động:

$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, tôi thích một người mà không giữ gìn tỉ lệ :-)

enter image description here

Chúc mừng! (! Eh, thưởng thức tôi sẽ nói)

+0

Cảm ơn bạn! Mã đẹp;) –

+0

Cảm ơn bạn! Có cách nào để lưu hình ảnh cắt dán vào thư mục với tên khác? @Alain Tiemblo –

5

ngẫu nhiên vứt bỏ hình ảnh vào lưới mà

Phương pháp là: chúng tôi sẽ bắt tất cả hình ảnh của chúng tôi để có được một mảng ngẫu nhiên, và xử lý chúng một cách ngẫu nhiên trên tuyến đường: 1-4 hình ảnh trên mỗi dòng (bạn sẽ có thể thay đổi giá trị này) và sẽ sử dụng hình ảnh cao hơn trong mỗi dòng để xác định chiều cao của mỗi dòng. Vì vậy, nếu một hình ảnh cao hơn 50% so với hình ảnh khác, nếu chúng không nằm trong cùng một dòng, bạn sẽ tiết kiệm được tỷ lệ.

Đó là một chút khó khăn hơn, vì vậy tôi quyết định không bao giờ sử dụng đồ họa trong quá trình phát triển phần này. Đó là lý do tại sao có rất nhiều bước và gỡ lỗi, nhưng điều này giúp rất nhiều để có được từng bước để kết quả cuối cùng.

Chúng tôi nhận được chiều cao của tất cả các hình ảnh của chúng tôi và tổng của chúng:

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

Cung cấp cho chúng tôi:

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 

Sau đó chúng tôi shfuffle mảng hình ảnh để có được một bố trí ngẫu nhiên của hình ảnh. Chúng ta cần phải bảo vệ chìa khóa, và cái xiềng xích thì không, vì vậy chúng ta cần phải lừa một chút.

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

Cung cấp cho chúng tôi:

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

Điều quan trọng ở đây là để kiểm tra xem chúng tôi bảo quản các hiệp hội hình ảnh/chiều cao.

Bây giờ, chúng tôi cần chuyển đổi chiều cao hình ảnh thành phần trăm: vì vậy nếu bạn có 2 hình ảnh, cao hơn 50% so với giây, vì vậy bạn sẽ có 66% tổng chiều cao cho hình ảnh đầu tiên và 33 % cho phần thứ hai. Chiều cao ảo này sẽ được sử dụng làm chiều cao trên lưới của chúng tôi.

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

quả trong:

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 

Bây giờ chúng ta tạo ra một loạt các dòng, để xem có bao nhiêu hình ảnh chúng tôi sẽ đưa cho mỗi dòng. Đối với ví dụ này, chúng tôi muốn từ 1 đến 4 hình ảnh trên mỗi dòng. Thay đổi tại đây rand() % 4 + 1 bằng những gì bạn muốn nhận được bao nhiêu hình ảnh tùy thích trên mỗi dòng. Ví dụ: rand() % 3 + 2 sẽ cung cấp cho bạn từ 2 đến 5 hình ảnh.

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

quả trong:

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

Chúng tôi cần phải kết hợp một hình ảnh với một dòng, và với một vị trí trong một dòng. Điều này sẽ giúp chúng tôi có được vị trí của hình ảnh trong lưới của chúng tôi.

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

quả trong:

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

Bây giờ, chúng ta cần phải nhận được tổng chiều rộng của hình ảnh của chúng tôi. Chúng tôi có từ 1 đến 4 hình ảnh, do đó, để có kích thước nguyên của mỗi hình ảnh bất kể số lượng hình ảnh trên mỗi dòng chúng tôi có, chúng tôi nhân 4 (giá trị tối đa) cho tất cả các giá trị từ 4 đến 1. Trong trường hợp này: 4 * 3 * 2 * 1 = 24, vì vậy nếu chúng ta có 1 hình ảnh/dòng, chiều rộng của nó sẽ là 24, 2 hình ảnh/dòng: 24/2 = 12, 3 hình ảnh/dòng: 24/3 = 8, 4 hình ảnh/dòng: 24/4 = 6. Tất cả đều là số nguyên hợp lệ.

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

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

Không có gì khó khăn ở đây, điều này dẫn đến:

virtual width: 24 

Chúng tôi cần bây giờ để xác định chiều cao của mỗi dòng, theo hình ảnh cao nhất trên mỗi dòng. Chúng ta cũng có thể suy ra chiều cao lưới của chúng ta trong phép tính này.

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

Điều này dẫn đế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 

Chúng tôi kiểm tra trong kết quả này nếu chúng ta có giá trị cao nhất cho mỗi dòng, và nếu tổng là hợp lệ.

Cuối cùng, chúng tôi có tất cả thông tin chúng tôi cần để hiển thị lưới hình ảnh được định vị ngẫu nhiên của chúng tôi.

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

này kết quả trong:

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 

Để gỡ lỗi mã của chúng tôi, chúng tôi kết thúc nó với:

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

Okey, bạn có tất cả các bước ở đây. Điều gì về kết quả?

enter image description here

F5 ...

enter image description here

F5 ...

enter image description here

mã cuối cùng:

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

Phương pháp tiếp cận của tôi có lẽ không phải là tốt nhất, nhưng ít nhất, nó cho phép bạn định vị ngẫu nhiên các hình ảnh của mình thành trọng lượng bảo toàn lưới của hình ảnh. Chủ đề khá khó xử lý vì vậy tôi hy vọng điều này sẽ đủ làm việc cho trường hợp của bạn.

+0

Đó là nhiều hơn tôi từng hy vọng, chỉ đơn giản là tuyệt vời! Cảm ơn bạn. –

5

Thực hiện minh bạch

lần thứ nhất về phương pháp __construct, thay thế:

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

bởi:

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

Sau đó, vào phương pháp resizePreservingAspectRatio, thêm chỉ sau:

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

Các dòng sau:

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

Và ở đây chúng tôi đi.

enter image description here