Tôi đã được đưa vào chủ đề này khi tôi cần kết hợp hai hình ảnh trong GD. Có vẻ như không có mã cụ thể cho điều đó vì vậy tôi sẽ chỉ để lại điều này ở đây cho khách truy cập trong tương lai vào trang này.
Đây là một ngã ba từ câu trả lời của colivier
hỗ trợ nhân hỗn hợp của hai hình ảnh.
Hai hình ảnh không cần phải có cùng kích thước NHƯNG hình ảnh lớp phủ sẽ được thay đổi kích thước và cắt thành kích thước của lớp dưới cùng. Tôi đã thực hiện một hàm trợ giúp fit
để làm điều đó nhưng đừng bận tâm với điều đó.
imagecolorat
trả lại màu cơ bản, ngay cả với PNG có độ trong suốt. Tức là, 50% màu đen (hiển thị là (128, 128, 128)) sẽ được trả về là (0, 0, 0, 64) 64 là giá trị alpha. Mã này xem xét tính mờ và chuyển đổi màu mờ sang các giá trị màu có thể nhìn thấy.
// bottom layer
$img1 = imagecreatefromjpeg(realpath(__DIR__.'/profilePic.jpg'));
// top layer
$img2 = imagecreatefrompng(realpath(__DIR__.'/border2.png'));
imagealphablending($img2, false);
imagesavealpha($img2, true);
$imagex = imagesx($img1);
$imagey = imagesy($img1);
$imagex2 = imagesx($img2);
$imagey2 = imagesy($img2);
// Prereq: Resize img2 to match img1, cropping beyond the aspect ratio
$w1 = max(min($imagex2, $imagex), $imagex);
$h1 = max(min($imagey2, $imagey), $imagey);
$w_using_h1 = round($h1 * $imagex2/$imagey2);
$h_using_w1 = round($w1 * $imagey2/$imagex2);
if ($w_using_h1 > $imagex) {
fit($img2, $imagex, $imagey, 'HEIGHT', true);
}
fit($img2, $imagex, $imagey, 'WIDTH', true);
// Actual multiply filter
for ($x = 0; $x < $imagex; ++$x) {
for ($y = 0; $y < $imagey; ++$y) {
$rgb1 = imagecolorat($img1, $x, $y);
$rgb2 = imagecolorat($img2, $x, $y);
$idx1 = imagecolorsforindex($img1, $rgb1);
$idx2 = imagecolorsforindex($img2, $rgb2);
// Shift left 8, then shift right 7
// same as multiply by 256 then divide by 128
// approximate multiply by 255 then divide by 127
// This is basically multiply by 2 but, expanded to show that
// we are adding a fraction of white to the translucent image
// $adder = ($idx2['alpha'] <<8>> 7);
$adder = ($idx2['alpha'] << 1);
$rmul = min(255, $idx2['red'] + $adder);
$gmul = min(255, $idx2['green'] + $adder);
$bmul = min(255, $idx2['blue'] + $adder);
$color_r = floor($idx1['red'] * $rmul/255);
$color_g = floor($idx1['green'] * $gmul/255);
$color_b = floor($idx1['blue'] * $bmul/255);
$newcol = imagecolorallocatealpha($img1, $color_r, $color_g, $color_b, 0);
imagesetpixel($img1, $x, $y, $newcol);
}
}
imagejpeg($img1, __DIR__.'/out.jpg');
/**
* Fits an image to a $w x $h canvas
*
* @param type $w Target width
* @param type $h Target height
* @param int $fit_which Which dimension to fit
* @param bool $upscale If set to true, will scale a smaller image to fit the given dimensions
* @param bool $padded If set to true, will add padding to achieve given dimensions
*
* @return Image object
*/
function fit(&$img, $w, $h, $fit_which = 'BOTH', $upscale = false, $padded = true) {
if (!in_array($fit_which, array('WIDTH', 'HEIGHT', 'BOTH'))) {
$fit_which = 'BOTH';
}
$w0 = imagesx($img);
$h0 = imagesy($img);
if (!$upscale && $w0 <= $w && $h0 <= $h)
return $this;
if ($padded) {
$w1 = max(min($w0, $w), $w);
$h1 = max(min($h0, $h), $h);
}
else {
$w1 = min($w0, $w);
$h1 = min($h0, $h);
}
$w_using_h1 = round($h1 * $w0/$h0);
$h_using_w1 = round($w1 * $h0/$w0);
// Assume width, crop height
if ($fit_which == 'WIDTH') {
$w2 = $w1;
$h2 = $h_using_w1;
}
// Assume height, crop width
elseif ($fit_which == 'HEIGHT') {
$w2 = $w_using_h1;
$h2 = $h1;
}
elseif ($fit_which == 'BOTH') {
if (!$padded) {
$w2 = $w = min($w, $w_using_h1);
$h2 = $h = min($h, $h_using_w1);
}
else {
// Extend vertically
if ($h_using_w1 <= $h) {
$w2 = $w1;
$h2 = $h_using_w1;
}
// Extend horizontally
else {
$w2 = $w_using_h1;
$h2 = $h1;
}
}
}
$im2 = imagecreatetruecolor($w, $h);
imagealphablending($im2, true);
imagesavealpha($im2, true);
$transparent = imagecolorallocatealpha($im2, 255, 255, 255, 127);
imagefill($im2, 0, 0, $transparent);
imagealphablending($img, true);
imagesavealpha($img, true);
// imagefill($im, 0, 0, $transparent);
imagecopyresampled($im2, $img, ($w - $w2)/2, ($h - $h2)/2, 0, 0, $w2, $h2, $w0, $h0);
$img = $im2;
}
Tuyệt vời, cảm ơn bạn rất nhiều! Điều đó dường như cung cấp chính xác funcionality như bộ lọc nhân của Photoshop. – heintore
Tôi đã sử dụng điều này trong một ví dụ khác, nhưng tôi thấy việc triển khai này thực sự chậm. Cách nhanh hơn là sử dụng bộ lọc hình ảnh với IMG_FILTER_COLORIZE. Đầu tiên, đảo ngược giá trị màu RGB dự định, sau đó đảo ngược hình ảnh bằng bộ lọc hình ảnh ($ image, IMG_FILTER_NEGATE), sau đó áp dụng màu đảo ngược cho hình ảnh ngược, sau đó đảo ngược lại hình ảnh. Xem tại đây http://stackoverflow.com/questions/26005991/php-gd-multiply-image-colors-with-tint-color/26250684#26250684 –
Hoạt động tuyệt vời! Tôi cập nhật nó một chút để nhân hai hình ảnh, không chỉ là một hình ảnh với một màu sắc: http://codepad.org/BSawY5ex –