PHP Conference Japan 2024

imagealphablending

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

imagealphablending设置图像的混合模式

描述

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

imagealphablending() 允许在真彩色图像上进行两种不同的绘制模式。在混合模式下,提供给所有绘图函数(例如 imagesetpixel())的颜色中的 alpha 通道分量决定了应该允许多少底层颜色透射。因此,gd 会自动将该点的现有颜色与绘图颜色混合,并将结果存储在图像中。生成的像素是不透明的。在非混合模式下,绘图颜色及其 alpha 通道信息将逐字复制,替换目标像素。在绘制调色板图像时,混合模式不可用。

参数

image

一个 GdImage 对象,由图像创建函数(如 imagecreatetruecolor())返回。

enable

是否启用混合模式。在真彩色图像上,默认值为 true,否则默认值为 false

返回值

成功时返回 true,失败时返回 false

变更日志

版本 描述
8.0.0 image 现在期望一个 GdImage 实例;之前,期望一个有效的 gd resource

示例

示例 #1 imagealphablending() 用法示例

<?php
// 创建图像
$im = imagecreatetruecolor(100, 100);

// 将 alphablending 设置为开启
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
= "这是一条测试信息\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] 将覆盖在 $i[1] 上
// ...

// 该函数返回准备保存的结果图像

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年前
我重写了下面给出的代码,以便在不需要时(完全不透明或完全透明的像素)跳过计算和像素设置,因为我的叠加内容通常大多是透明的。将 216x145px 图像的处理时间从约 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”提供的非常简洁的示例所示:在 .jpg 照片上使用 Alpha 混合的 .png 徽标。问题是……这里根本不起作用(为什么?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 位 alpha 值转换为 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;

## 源像素完全不透明 (alpha == 0)
if ($a_s == 0) {
$r_d = $r_s; $g_d = $g_s; $b_d = $b_s;
}
## 源像素完全透明 (alpha == 255)
else if ($a_s > 253) {
## 仅使用源 alpha 值,我们需要混合 (100-"some")% 的源像素与 "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');

## 将 $source 图像 alpha 混合到 $dest 图像中,起始位置为 (10, 5)。
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”的第一条消息中所描述的那样。虽然,它并没有完全奏效,而不是使用 imageAlphaBlending,您必须使用 imageSaveAlpha。

因此,我发现更正后的代码更简洁,如下所示

<?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] 将覆盖在 $i[1] 上
// ...

// 该函数返回准备保存的结果图像

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