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:

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:

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:

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:

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

Personnally, tôi thích một người mà không giữ gìn tỉ lệ :-)

Chúc mừng! (! Eh, thưởng thức tôi sẽ nói)
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? –
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). –
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! –