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

// 将 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 notes

www.deebster.com
20 年前
如果您想使用混合,目标图像资源不必是调色板。

这意味着使用 ImageCreateTrueColor() 而不是 ImageCreate()。

(如果您的源是例如 jpeg,并且您使用了 ImageCreateFromJPEG(),则上述内容无关。)
barnabas at kendall dot NOSPAM dot net
22 年前
如果您尝试将透明图像复制到另一个图像上,您可能会认为应该将 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
17 年前
"如果 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;
}

?>
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.17s 减少到 ~0.06s。

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
17 年前
Roy Conejo 说

我必须将图像“按像素 alpha 混合”到纯色背景中,如“barnabas at kendall dot NOSPAM dot net”的简洁示例所示:在 .jpg 照片上使用 alpha 混合的 .png logo。问题是……它根本没有在这里奏效(为什么?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" % 的目标像素.
} 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 图像混合到 $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
17 年前
在上一条消息中,我发现它工作完美。但是,它可以更容易地完成,正如 "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