PHP 日本研討會 2024

imagealphablending

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

imagealphablending設定影像的混合模式

說明

imagealphablending(GdImage $image, bool $enable): bool

imagealphablending() 允許在真彩色影像上使用兩種不同的繪圖模式。在混合模式下,提供給所有繪圖函式的顏色之 alpha 通道分量(例如 imagesetpixel())會決定應允許多少底層顏色透出。因此,gd 會自動將該點的現有顏色與繪圖顏色混合,並將結果儲存在影像中。產生的像素是不透明的。在非混合模式下,繪圖顏色會連同其 alpha 通道資訊一起直接複製,取代目標像素。在調色盤影像上繪圖時,無法使用混合模式。

參數

image

一個 GdImage 物件,由其中一個影像建立函式(例如 imagecreatetruecolor())傳回。

enable

是否啟用混合模式。在真彩色影像上,預設值為 true,否則預設值為 false

回傳值

成功時回傳 true,失敗時回傳 false

變更日誌

版本 說明
8.0.0 image 現在預期一個 GdImage 實例;先前,預期一個有效的 gd resource

範例

範例 1 imagealphablending() 使用範例

<?php
// 建立影像
$im = imagecreatetruecolor(100, 100);

// 開啟 alpha 混合
imagealphablending($im, true);

// 繪製一個正方形
imagefilledrectangle($im, 30, 30, 70, 70, imagecolorallocate($im, 255, 0, 0));

// 輸出
header('Content-Type: image/png');

imagepng($im);
imagedestroy($im);
?>
新增註解

使用者貢獻註解 14 則註解

barnabas at kendall dot NOSPAM dot net
23 年前
如果您嘗試將透明影像複製到另一個影像上,您可能會以為應該將 ImageAlphaBlending 函式應用到具有透明度的影像,即來源影像。實際上,您必須將 ImageAlphaBlending 函式應用到目標影像。基本上,它是在說:「讓指定的影像尊重透明度」。

這是一個實際範例。假設您想要將您的標誌放在相片的左上角。您的標誌是具有透明度的 PNG 檔案,而相片是 JPEG 檔案。以下是您會執行的操作:

<?php
$photoImage
= ImageCreateFromJPEG('photo.jpg');
ImageAlphaBlending($photoImage, true);

$logoImage = ImageCreateFromPNG('logo.png');
$logoW = ImageSX($logoImage);
$logoH = ImageSY($logoImage);

ImageCopy($photoImage, $logoImage, 0, 0, 0, 0, $logoW, $logoH);

ImageJPEG($photoImage); // 輸出至瀏覽器

ImageDestroy($photoImage);
ImageDestroy($logoImage);
?>
Jakub Argasi?ski
19 年前
我一直在尋找一個腳本,該腳本可以執行以下操作:使用指定的字型和給定的顏色產生具有文字的影像,但具有完全透明的背景(透過 alpha 通道,而不是透過顏色透明度)。最後,我自行建立了這個腳本。這只是一個如何做到這一點的粗略概念。

<?php
$tekst
= "This is a test message\nza???? g??l? ja??!\nZA?ӣ? GʦL? JA???";

$h = 9;

$size = imageTTFBBox($h, 0, "arial.ttf", $tekst);
$image = imageCreateTrueColor(abs($size[2]) + abs($size[0]), abs($size[7]) + abs($size[1]));
imageSaveAlpha($image, true);
ImageAlphaBlending($image, false);

$tlo = imagecolorallocatealpha($image, 220, 220, 220, 127);
imagefill($image, 0, 0, $tlo);

$napis = imagecolorallocate($image, 220, 220, 220);
imagettftext($image, $h, 0, 0, abs($size[5]), $napis, "arial.ttf", $tekst);
imagepng($image, "output.png");
imagedestroy($image);

?>
<html>
<head>
</head>
<body bgcolor="#808080">
<img src="output.png" alt="">
</body>
</html>
luke dot stanley at gmail dot com
18 年前
「如果將 imagealphablending 設定為 true,而您想要合併兩個圖片,將會沒有透明度。如果設定為 false,則只會考慮第二張圖片的透明度,導致第一張圖片沒有任何部分顯示出來。要解決這個問題,請使用以下函式:」

dscharrer at gmail dot com 提供了這個函式,但沒有使用範例,所以這裡有一個:

<?

$flag = imagecreatefrompng('a.png');
$mask = imagecreatefrompng('b.png');

imagealphablending($flag, 1);
imagealphablending($mask, 1);
$i= array($flag, $mask); // 這裡是一個圖片陣列,使用上面指定的 $flag 和 $mask 圖片

$s = imagemergealpha($i);

header("Content-type: image/png");
imagepng($s);

//合併多個圖片並保留透明度

//$i 是要合併的圖片陣列
// $i[1] 將覆蓋在 $i[0] 之上
// $i[2] 將覆蓋在那之上
// ...

//此函式會回傳準備好儲存的結果圖片

function imagemergealpha($i) {

//建立新的圖片
$s = imagecreatetruecolor(imagesx($i[0]),imagesy($i[1]));

//合併所有圖片
imagealphablending($s,true);
$z = $i;
while($d = each($z)) {
imagecopy($s,$d[1],0,0,0,0,imagesx($d[1]),imagesy($d[1]));
}

//還原透明度
imagealphablending($s,false);
$w = imagesx($s);
$h = imagesy($s);
for($x=0;$x<$w;$x++) {
for($y=0;$y<$h;$y++) {
$c = imagecolorat($s,$x,$y);
$c = imagecolorsforindex($s,$c);
$z = $i;
$t = 0;
while($d = each($z)) {
$ta = imagecolorat($d[1],$x,$y);
$ta = imagecolorsforindex($d[1],$ta);
$t += 127-$ta['alpha'];
}
$t = ($t > 127) ? 127 : $t;
$t = 127-$t;
$c = imagecolorallocatealpha($s,$c['red'],$c['green'],$c['blue'],$t);
imagesetpixel($s,$x,$y,$c);
}
}
imagesavealpha($s,true);
return $s;
}

?>
www.deebster.com
21 年前
如果想要使用混合,目標圖片資源不能是調色盤模式。

這表示要使用 ImageCreateTrueColor() 而不是 ImageCreate()。

(如果您的來源是例如 jpeg,而您已經使用 ImageCreateFromJPEG(),則以上內容無關緊要。)
jeppe dot dyrby at gmail dot com
17 年前
我建立了一個小函式,用於在任何圖片上放置浮水印。
浮水印可以是帶有透明度的 png,並且可以使用簡單的字串(例如 'bottom-left' 或 'center')將浮水印放置在圖片的任何位置。

<?
function imagelogo (&$dst_image, $src_image, $dst_w, $dst_h, $src_w, $src_h, $position='bottom-left') {
imagealphablending($dst_image,true);
imagealphablending($src_image,true);
if ($position == 'random') {
$position = rand(1,8);
}
switch ($position) {
case 'top-right'
case 'right-top'
case 1
imagecopy($dst_image, $src_image, ($dst_w-$src_w), 0, 0, 0, $src_w, $src_h);
break;
case 'top-left'
case 'left-top'
case 2
imagecopy($dst_image, $src_image, 0, 0, 0, 0, $src_w, $src_h);
break;
case 'bottom-right'
case 'right-bottom'
case 3
imagecopy($dst_image, $src_image, ($dst_w-$src_w), ($dst_h-$src_h), 0, 0, $src_w, $src_h);
break;
case 'bottom-left'
case 'left-bottom'
case 4
imagecopy($dst_image, $src_image, 0 , ($dst_h-$src_h), 0, 0, $src_w, $src_h);
break;
case 'center'
case 5
imagecopy($dst_image, $src_image, (($dst_w/2)-($src_w/2)), (($dst_h/2)-($src_h/2)), 0, 0, $src_w, $src_h);
break;
case 'top'
case 6
imagecopy($dst_image, $src_image, (($dst_w/2)-($src_w/2)), 0, 0, 0, $src_w, $src_h);
break;
case 'bottom'
case 7
imagecopy($dst_image, $src_image, (($dst_w/2)-($src_w/2)), ($dst_h-$src_h), 0, 0, $src_w, $src_h);
break;
case 'left'
case 8
imagecopy($dst_image, $src_image, 0, (($dst_h/2)-($src_h/2)), 0, 0, $src_w, $src_h);
break;
case 'right'
case 9
imagecopy($dst_image, $src_image, ($dst_w-$src_w), (($dst_h/2)-($src_h/2)), 0, 0, $src_w, $src_h);
break;
}
}

// 範例

imagelogo($image, $watermark, imagesx($image), imagesy($image), imagesx($watermark), imagesy($watermark), 'random');
?>
JAYPEEsorenATgeeMail
17 年前
我重寫了下面給出的程式碼,以在不需要時(完全不透明或完全透明的像素)跳過計算和像素設定,因為我的覆蓋圖的內容通常大部分是透明的。在 216x145 像素的圖片上,處理時間從 ~0.17 秒減少到 ~0.06 秒。

function alphaOverlay($destImg, $overlayImg, $imgW, $imgH)
{
for($y=0;$y<$imgH;$y++)
{
for($x=0;$x<$imgW;$x++)
{
$ovrARGB = imagecolorat($overlayImg, $x, $y);
$ovrA = ($ovrARGB >> 24) << 1;
$ovrR = $ovrARGB >> 16 & 0xFF;
$ovrG = $ovrARGB >> 8 & 0xFF;
$ovrB = $ovrARGB & 0xFF;

$change = false;
if($ovrA == 0)
{
$dstR = $ovrR;
$dstG = $ovrG;
$dstB = $ovrB;
$change = true;
}
elseif($ovrA < 254)
{
$dstARGB = imagecolorat($destImg, $x, $y);
$dstR = $dstARGB >> 16 & 0xFF;
$dstG = $dstARGB >> 8 & 0xFF;
$dstB = $dstARGB & 0xFF;

$dstR = (($ovrR * (0xFF-$ovrA)) >> 8) + (($dstR * $ovrA) >> 8);
$dstG = (($ovrG * (0xFF-$ovrA)) >> 8) + (($dstG * $ovrA) >> 8);
$dstB = (($ovrB * (0xFF-$ovrA)) >> 8) + (($dstB * $ovrA) >> 8);
$change = true;
}
if($change)
{
$dstRGB = imagecolorallocatealpha($destImg, $dstR, $dstG, $dstB, 0);
imagesetpixel($destImg, $x, $y, $dstRGB);
}

}
}
return $destImg;
}
joe AT cerberon DOT net
20 年前
請注意,必須啟用 alpha 混合才能在全彩模式中渲染反鋸齒文字。

對於舊版的 PHP 和/或 GD(例如,Debian woody 隨附的版本),alpha 混合預設為停用,而新版本則為啟用。
roONLYycoLOWERCAneSEjo at gmail dot com
18 年前
Roy Conejo 說

我必須將一張圖片「逐像素 alpha 混合」到純色背景中,如「barnabas at kendall dot NOSPAM dot net」的簡潔範例中所見:一個 alpha 混合的 .png 標誌在 .jpg 照片上。問題是...它在這裡根本不起作用(為什麼?T_T)。

請注意,我只使用來源 alpha 來決定最終像素上將會出現多少來源和目標的顏色...而且我必須將 alpha 值(0 - 127)乘以 2,因為我需要它是 8 位元才能進行計算。

我認為程式碼相當快,沒有小數、沒有捨入、沒有不必要的編碼。如果您真的需要,可以實作邊界檢查或裁剪。

我希望它能幫助到處於相同情況的其他人 ^.^

<?php

## alpha_blending 函數開始 -------------------------------------------
function
alpha_blending ($dest, $source, $dest_x, $dest_y) {

## 讓來源像素與其 alpha 值混合到目標圖像中 =)
for ($y = 0; $y < imagesy($source); $y++) {
for (
$x = 0; $x < imagesx($source); $x++) {

$argb_s = imagecolorat ($source ,$x ,$y);
$argb_d = imagecolorat ($dest ,$x+$dest_x ,$y+$dest_y);

$a_s = ($argb_s >> 24) << 1; ## 7 位元轉為 8 位元。
$r_s = $argb_s >> 16 & 0xFF;
$g_s = $argb_s >> 8 & 0xFF;
$b_s = $argb_s & 0xFF;

$r_d = $argb_d >> 16 & 0xFF;
$g_d = $argb_d >> 8 & 0xFF;
$b_d = $argb_d & 0xFF;

## 來源像素 100% 不透明 (alpha == 0)
if ($a_s == 0) {
$r_d = $r_s; $g_d = $g_s; $b_d = $b_s;
}
## 來源像素 100% 透明 (alpha == 255)
else if ($a_s > 253) {
## 僅使用來源 alpha 值,我們必須混合 (100-"some") 百分比的來源與 "some" 百分比的目標。
} else {
$r_d = (($r_s * (0xFF-$a_s)) >> 8) + (($r_d * $a_s) >> 8);
$g_d = (($g_s * (0xFF-$a_s)) >> 8) + (($g_d * $a_s) >> 8);
$b_d = (($b_s * (0xFF-$a_s)) >> 8) + (($b_d * $a_s) >> 8);
}

$rgb_d = imagecolorallocatealpha ($dest, $r_d, $g_d, $b_d, 0);
imagesetpixel ($dest, $x, $y, $rgb_d);
}
}
}
## alpha_blending 函數結束 -------------------------------------------



## 讓我們像平常一樣開始載入圖片...
$source = imagecreatefrompng ('logo.png');
$dest = imagecreatefromjpg ('photo.jpg');

## 從 10, 5 的位置開始將 $source alpha 混合到 $dest 中。
alpha_blending ($dest, $source, 10, 5);

## 在這裡你必須儲存 "$dest" 或將它傳送到瀏覽器...
##

imagedestroy ($source);
imagedestroy ($dest);

?>

eof =p
boo at php dot net
21 年前
請注意,AlphaBlending 預設為開啟。
所以,如果你不想使用 AlphaBlending,才使用這個函數。
klaproth at creative-mindworks dot de
16 年前
我寫了一個函數,它將圖片作為參數,並回傳一個具有反射效果的相同圖片(常見於 WEB 2.0 網站)。我沒有對大型圖片檔案進行效能測試,它對於縮圖來說運作良好(需要 PHP 4.3.2 或以上版本,或 PHP5)。

<?php
function imagereflection($src_img) {
$src_height = imagesy($src_img);
$src_width = imagesx($src_img);
$dest_height = $src_height + ($src_height / 2);
$dest_width = $src_width;

$reflected = imagecreatetruecolor($dest_width, $dest_height);
imagealphablending($reflected, false);
imagesavealpha($reflected, true);

imagecopy($reflected, $src_img, 0, 0, 0, 0, $src_width, $src_height);
$reflection_height = $src_height / 2;
$alpha_step = 80 / $reflection_height;
for (
$y = 1; $y <= $reflection_height; $y++) {
for (
$x = 0; $x < $dest_width; $x++) {
// 將像素從 x / $src_height - y 複製到 x / $src_height + y
$rgba = imagecolorat($src_img, $x, $src_height - $y);
$alpha = ($rgba & 0x7F000000) >> 24;
$alpha = max($alpha, 47 + ($y * $alpha_step));
$rgba = imagecolorsforindex($src_img, $rgba);
$rgba = imagecolorallocatealpha($reflected, $rgba['red'], $rgba['green'], $rgba['blue'], $alpha);
imagesetpixel($reflected, $x, $src_height + $y - 1, $rgba);
}
}

return
$reflected;
}
?>

這有點硬編碼。你可以繼續將某些數值提取為參數(80 是透明度的起始值,$height / 2 是反射區域...)。

乾杯,
Christian
Raisul Kabir Ruman
18 年前
在前一則訊息中,我發現它運作完美。但是,它可以更簡單地完成,就像「barnabas at kendall dot NOSPAM dot net」的第一則訊息所描述的那樣。雖然,它並非完全有效,你必須使用 imageSaveAlpha,而不是 imageAlphaBlending。

因此,我找到了修正且更精簡的程式碼如下:

<?php
$im_a
= @imagecreatefrompng("a.png");
$im_c = @imagecreatefrompng("c.png");
imageSaveAlpha($im_c, true);

imagecopy($im_c,$im_a,0,0,0,0,200,200);
header("Content-type: image/png");
imagepng($im_c);
?>
dscharrer at gmail dot com
19 年前
如果將 imagealphablending 設定為 true,並且你想要合併兩張圖片,你會失去透明度。如果設定為 false,則只會採用第二張圖片的透明度,導致第一張圖片的任何部分都無法顯示。要解決此問題,請使用以下函式。

<?
//合併多個圖片並保留透明度

//$i 是要合併的圖片陣列
// $i[1] 將覆蓋在 $i[0] 之上
// $i[2] 將覆蓋在那之上
// ...

//此函式會回傳準備好儲存的結果圖片

function imagemergealpha($i) {

//建立新的圖片
$s = imagecreatetruecolor(imagesx($i[0]),imagesy($i[1]));

//合併所有圖片
imagealphablending($s,true);
$z = $i;
while($d = each($z)) {
imagecopy($s,$d[1],0,0,0,0,imagesx($d[1]),imagesy($d[1]));
}

//還原透明度
imagealphablending($s,false);
$w = imagesx($s);
$h = imagesy($s);
for($x=0;$x<$w;$x++) {
for($y=0;$y<$h;$y++) {
$c = imagecolorat($s,$x,$y);
$c = imagecolorsforindex($s,$c);
$z = $i;
$t = 0;
while($d = each($z)) {
$ta = imagecolorat($d[1],$x,$y);
$ta = imagecolorsforindex($d[1],$ta);
$t += 127-$ta['alpha'];
}
$t = ($t > 127) ? 127 : $t;
$t = 127-$t;
$c = imagecolorallocatealpha($s,$c['red'],$c['green'],$c['blue'],$t);
imagesetpixel($s,$x,$y,$c);
}
}
imagesavealpha($s,true);
return $s;
}
?>
webmaster at nweurosport dot com
19 年前
當儲存用於透明疊加的圖片時,例如上面提到的添加標誌,我發現 PNG-24 無法成功,只有 GIF 和 PNG-8 可以。我使用 PNG-8 取得了很大的成功。
tcarter at roundcorners dot com
22 年前
如果您要將具有透明度的圖片另存為 PNG,那麼將其另存為 PNG-8 會使其具有與 GIF 相同方式的透明度,但這不適用於此函式。

為了使此函式運作,圖片需要具有 Alpha 通道(當你仔細思考時,這顯然是必須的),因此請確保您儲存為 PNG-24。
To Top