imagecopymerge

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

imagecopymerge复制和合并图像的一部分

说明

imagecopymerge(
    GdImage $dst_image,
    GdImage $src_image,
    int $dst_x,
    int $dst_y,
    int $src_x,
    int $src_y,
    int $src_width,
    int $src_height,
    int $pct
): bool

src_image 的一部分复制到 dst_image 上,从 x、y 坐标 src_xsrc_y 开始,宽度为 src_width,高度为 src_height。定义的部分将被复制到 x、y 坐标 dst_xdst_y 上。

参数

dst_image

目标图像资源。

src_image

源图像资源。

dst_x

目标点的 x 坐标。

dst_y

目标点的 y 坐标。

src_x

源点的 x 坐标。

src_y

源点的 y 坐标。

src_width

源宽度。

src_height

源高度。

pct

两张图像将根据 pct 合并,其取值范围为 0 到 100。当 pct = 0 时,不执行任何操作,当为 100 时,此函数的行为与 imagecopy() 相同,用于调色板图像,除了忽略 alpha 成分,而对于真彩色图像,它实现了 alpha 透明度。

返回值

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

变更日志

版本 说明
8.0.0 dst_imagesrc_image 现在期望 GdImage 实例;以前,期望的是 resource

范例

范例 #1 以 75% 的透明度合并两个 PHP.net 徽标副本

<?php
// 创建图像实例
$dest = imagecreatefromgif('php.gif');
$src = imagecreatefromgif('php.gif');

// 复制和合并
imagecopymerge($dest, $src, 10, 10, 0, 0, 100, 47, 75);

// 输出并从内存中释放
header('Content-Type: image/gif');
imagegif($dest);

imagedestroy($dest);
imagedestroy($src);
?>

添加注释

用户贡献的注释 22 个注释

Sina Salek
15 年前
我刚刚检查了 PHP 的问题跟踪器,一个核心开发人员说这个函数从来就不是为了支持 alpha 通道而设计的!并且他们拒绝提交提供的补丁!太荒谬了
无论如何,我尝试了 Rodrigo 的解决方法,效果很好,感谢 Rodrigo 分享它。
我想出了另一个想法,它比他的解决方案快得多(可能需要稍微多一点内存)。

希望对某些人有所帮助。

<?php
/**
* PNG ALPHA CHANNEL SUPPORT for imagecopymerge();
* by Sina Salek
*
* Bugfix by Ralph Voigt (bug which causes it
* to work only for $src_x = $src_y = 0.
* Also, inverting opacity is not necessary.)
* 08-JAN-2011
*
**/
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);

// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);

// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);

// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}

?>
Leo
12 年前
imagecopymerge PHP 函数帮助我创建了一种快速方法,可以在真彩色图像中用另一种颜色替换一种颜色。

在此之前,为了实现这个目的,我必须遍历图像的所有像素,并使用 imagecolorat 和 imagesetpixel 像素级地替换颜色;对于大型图像来说,这种方法非常慢。

所以,这里就是快速的方法

<?php

function replaceColorInImage ($image, $old_r, $old_g, $old_b, $new_r, $new_g, $new_b)
{
imagecolortransparent ($image, imagecolorallocate ($image, $old_r, $old_g, $old_b));

$w = imagesx ($image);
$h = imagesy ($image);

$resImage = imagecreatetruecolor ($w, $h);

imagefill ($resImage, 0, 0, imagecolorallocate ($resImage, $new_r, $new_g, $new_b));

imagecopymerge ($resImage, $image, 0, 0, 0, 0, $w, $h, 100);

return
$resImage;
}

?>
Steve
19 年前
在 backglancer 和 stefan 帖子基础上,以下脚本将一个 24 位 PNG 水印叠加到任何图像上。

为了准备一个 24 位水印,我建议在 Photoshop 中创建一个带有透明背景的白色徽标或文本。通过“存储为网页...”将其保存为 24 位 PNG。确保在 Photoshop 本身设置徽标图层的透明度。30-40% 是一个不错的设置。

准备完素材后,将完整或相对服务器路径扔到下面的水印函数中

/******************************************************************/

function watermark($sourcefile, $watermarkfile) {

#
# $sourcefile = 要加水印图片的文件名。
# $watermarkfile = 24 位 PNG 水印文件的文件名。
#

//获取图片资源 ID
$watermarkfile_id = imagecreatefrompng($watermarkfile);

imageAlphaBlending($watermarkfile_id, false);
imageSaveAlpha($watermarkfile_id, true);

$fileType = strtolower(substr($sourcefile, strlen($sourcefile)-3));

switch($fileType) {
case('gif')
$sourcefile_id = imagecreatefromgif($sourcefile);
break;

case('png')
$sourcefile_id = imagecreatefrompng($sourcefile);
break;

default
$sourcefile_id = imagecreatefromjpeg($sourcefile);
}

//获取两个像素的大小
$sourcefile_width=imageSX($sourcefile_id);
$sourcefile_height=imageSY($sourcefile_id);
$watermarkfile_width=imageSX($watermarkfile_id);
$watermarkfile_height=imageSY($watermarkfile_id);

$dest_x = ( $sourcefile_width / 2 ) - ( $watermarkfile_width / 2 );
$dest_y = ( $sourcefile_height / 2 ) - ( $watermarkfile_height / 2 );

//如果为 gif,则必须将其上采样到真彩色图像
if($fileType == 'gif') {
//创建一个空的真彩色容器
$tempimage = imagecreatetruecolor($sourcefile_width,
$sourcefile_height);

//将 8 位 gif 复制到真彩色图像中
imagecopy($tempimage, $sourcefile_id, 0, 0, 0, 0,
$sourcefile_width, $sourcefile_height);

//将 source_id 复制到
$sourcefile_id = $tempimage;
}

imagecopy($sourcefile_id, $watermarkfile_id, $dest_x, $dest_y, 0, 0,
$watermarkfile_width, $watermarkfile_height);

//从修改后的图片创建 jpeg
switch($fileType) {

//记住我们不再需要 gif,因此我们只使用 png 或 jpeg。
//查看上面的上采样代码,了解如何处理 gif
case('png')
header("Content-type: image/png");
imagepng ($sourcefile_id);
break;

default
header("Content-type: image/jpg");
imagejpeg ($sourcefile_id);
}

imagedestroy($sourcefile_id);
imagedestroy($watermarkfile_id);

}
Leo
12 年前
以下函数为给定颜色创建真彩色图像的蒙版。之前为了创建图像蒙版,我习惯于循环遍历所有图像像素并使用 imagecolorat 检查它们的色彩,并根据图片颜色复制像素。对于大型图像来说,这非常慢,因此以下代码改进了此流程。

<?php

function getOppositeColor ($color)
{
return (
( (
255 - ($color >> 16) & 0xFF) << 16 ) +
( (
255 - ($color >> 8 ) & 0xFF) << 8 ) +
( (
255 - ($color ) & 0xFF) )
);
}

function
createImageMask (&$image, $color)
{
$w = imagesx ($image);
$h = imagesy ($image);

$tmpImage = imagecreatetruecolor ($w, $h);

imagecopy ($tmpImage, $image, 0, 0, 0, 0, $w, $h);

imagefilter ($image, IMG_FILTER_NEGATE);

imagecolortransparent ($image, getOppositeColor ($color));

imagecopymerge ($tmpImage, $image, 0, 0, 0, 0, $w, $h, 50);

imagedestroy ($image);

$image = $tmpImage;
}

?>

例如,如果我们有一张照片并指定颜色 = (255, 0, 0),即红色,则结果将是相同大小的图像,其中原始照片中红色像素的位置都为红色像素,其他位置为灰色像素。
backglancer in the hotmail
19 年前
我快要疯了....
你们中任何试图合并一个半透明 png 的人...
使用 imagecopy :)
<?
$flag = imagecreatefrompng('flags/images/flagWhiteFill.png');
$mask = imagecreatefrompng('flags/images/flag_transparent.png');

imagealphablending($flag, 1);
imagealphablending($mask, 1);

imagecopy($flag, $mask, 0,0,0,0,25,43);

Header("Content-type: image/jpeg");
imagepng($flag);
?>

ImageSaveAlpha(resource, bool); 使透明颜色变为不透明... 不知道为什么 :)
rodrigo dot polo at gmail dot com
15 年前
<?php
/**
* PNG ALPHA 通道支持 imagecopymerge();
* 此函数类似 imagecopymerge,但它可以很好地处理 alpha 通道!
**/

// 修复获取类似 imagecopymerge 的函数,并支持 ALPHA
// 脚本作者:aiden dot mail at freemail dot hu
// 修改为 imagecopymerge_alpha() 的作者:rodrigo dot polo at gmail dot com
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
if(!isset(
$pct)){
return
false;
}
$pct /= 100;
// 获取图像宽度和高度
$w = imagesx( $src_im );
$h = imagesy( $src_im );
// 关闭 alpha 混合
imagealphablending( $src_im, false );
// 找到图像中最不透明的像素(具有最小 alpha 值的像素)
$minalpha = 127;
for(
$x = 0; $x < $w; $x++ )
for(
$y = 0; $y < $h; $y++ ){
$alpha = ( imagecolorat( $src_im, $x, $y ) >> 24 ) & 0xFF;
if(
$alpha < $minalpha ){
$minalpha = $alpha;
}
}
// 循环遍历图像像素并修改每个像素的 alpha 值
for( $x = 0; $x < $w; $x++ ){
for(
$y = 0; $y < $h; $y++ ){
// 获取当前 alpha 值(表示透明度!)
$colorxy = imagecolorat( $src_im, $x, $y );
$alpha = ( $colorxy >> 24 ) & 0xFF;
// 计算新的 alpha 值
if( $minalpha !== 127 ){
$alpha = 127 + 127 * $pct * ( $alpha - 127 ) / ( 127 - $minalpha );
} else {
$alpha += 127 * $pct;
}
// 获取带有新 alpha 值的颜色索引
$alphacolorxy = imagecolorallocatealpha( $src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha );
// 使用新的颜色和透明度设置像素
if( !imagesetpixel( $src_im, $x, $y, $alphacolorxy ) ){
return
false;
}
}
}
// 复制图像
imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
}

// 用例:
$img_a = imagecreatefrompng('image1.png');
$img_b = imagecreatefrompng('wm2.png');

// 相同的命令:
imagecopymerge_alpha($img_a, $img_b, 10, 10, 0, 0, imagesx($img_b), imagesy($img_b),50);

// 输出图像:
header("Content-Type: image/png");
imagesavealpha($img_a, true);
imagepng($img_a, NULL);
?>
gigitrix
15 年前
一些非常有趣的东西:这段代码看起来很正常,它可以用来随机地裁剪图像片段。

<?php
header
("Content-Type: image/jpeg");
$width=837;
$height=771;
$origim = imagecreatefromjpeg("theimage.jpeg"); /* 尝试打开 */
$imagetodisplay=imagecreate($width, $height);

for(
$i=0;$i<=100;$i++)
{
$xPos=rand(0,$width-9);
$yPos=rand(0,$height-9);
imagecopy($imagetodisplay, $origim, $xPos, $yPos , $xPos, $yPos , 10 , 10);
}

imagejpeg($imagetodisplay);
imagedestroy($imagetodisplay);
imagedestroy($origim);
?>

但是,尝试运行这段代码会发现,一个被忽略的细节增加了趣味性。由于第一个定义的颜色被认为是背景颜色,因此 $imagetodisplay 的背景颜色是从 $origim 中随机选择的,但这个随机颜色会根据背景图像的权重进行选择。这让我感到意外(我以为背景会是黑色),但我现在保留了它,因为它看起来不错。
jtacon at php dot net
19 年前
此示例演示如何使用 imageCopyMerge 创建一个带有四个随机位置(角落)的水印功能。

<?php
function waterMark($fileInHD, $wmFile, $transparency = 50, $jpegQuality = 90, $margin = 5) {

$wmImg = imageCreateFromGIF($wmFile);
$jpegImg = imageCreateFromJPEG($fileInHD);

// 水印随机位置
$wmX = (bool)rand(0,1) ? $margin : (imageSX($jpegImg) - imageSX($wmImg)) - $margin;
$wmY = (bool)rand(0,1) ? $margin : (imageSY($jpegImg) - imageSY($wmImg)) - $margin;

// 水印处理
imageCopyMerge($jpegImg, $wmImg, $wmX, $wmY, 0, 0, imageSX($wmImg), imageSY($wmImg), $transparency);

// 覆盖图像
ImageJPEG($jpegImg, $fileInHD, $jpegQuality);
}

waterMark('myImage.jpg','waterMark.gif');

?>

希望对您有所帮助。

Javier Tac?n。
stefan dot wehowsky at profilschmiede dot de
23 年前
此函数旨在作为“imageCopyMerge”函数的示例。
我希望它能帮助这里一些经验不足的 php 程序员。
我写这个函数是为了将房地产经纪人的物件标记为“已售出”,方法是将“已售出”图片复制到房屋图片中。

<?php

//$sourcefile = 要插入 $insertfile 的图片的文件名。
//$insertfile = 要插入 $sourcefile 的图片的文件名。
//$targetfile = 修改后图片的文件名。
//$transition = 过渡强度(以百分比表示)
//$pos = $insertfile 将在 $sourcefile 中插入的位置
// 0 = 中间
// 1 = 左上角
// 2 = 右上角
// 3 = 右下角
// 4 = 左下角
// 5 = 上中
// 6 = 中右
// 7 = 下中
// 8 = 中左
//
//
function mergePix($sourcefile,$insertfile, $targetfile, $pos=0,$transition=50)
{

// 获取图片的资源 ID?
$insertfile_id = imageCreateFromJPEG($insertfile);
$sourcefile_id = imageCreateFromJPEG($sourcefile);

// 获取两张图片的大小
$sourcefile_width=imageSX($sourcefile_id);
$sourcefile_height=imageSY($sourcefile_id);
$insertfile_width=imageSX($insertfile_id);
$insertfile_height=imageSY($insertfile_id);

// 中间
if( $pos == 0 )
{
$dest_x = ( $sourcefile_width / 2 ) - ( $insertfile_width / 2 );
$dest_y = ( $sourcefile_height / 2 ) - ( $insertfile_height / 2 );
}

// 左上角
if( $pos == 1 )
{
$dest_x = 0;
$dest_y = 0;
}

// 右上角
if( $pos == 2 )
{
$dest_x = $sourcefile_width - $insertfile_width;
$dest_y = 0;
}

// 右下角
if( $pos == 3 )
{
$dest_x = $sourcefile_width - $insertfile_width;
$dest_y = $sourcefile_height - $insertfile_height;
}

// 左下角
if( $pos == 4 )
{
$dest_x = 0;
$dest_y = $sourcefile_height - $insertfile_height;
}

// 上中
if( $pos == 5 )
{
$dest_x = ( ( $sourcefile_width - $insertfile_width ) / 2 );
$dest_y = 0;
}

// 中右
if( $pos == 6 )
{
$dest_x = $sourcefile_width - $insertfile_width;
$dest_y = ( $sourcefile_height / 2 ) - ( $insertfile_height / 2 );
}

// 下中
if( $pos == 7 )
{
$dest_x = ( ( $sourcefile_width - $insertfile_width ) / 2 );
$dest_y = $sourcefile_height - $insertfile_height;
}

// 中左
if( $pos == 8 )
{
$dest_x = 0;
$dest_y = ( $sourcefile_height / 2 ) - ( $insertfile_height / 2 );
}

// 主要内容:合并两张图片
imageCopyMerge($sourcefile_id, $insertfile_id,$dest_x,$dest_y,0,0,$insertfile_width,$insertfile_height,$transition);

// 从修改后的图片创建 jpeg
imagejpeg ($sourcefile_id,"$targetfile");

}
claudio dot gaetani at gdldesign dot it
20 年前
此函数旨在作为“imageCopyMerge” - “ImageCopyResized”、 “ImageColorTransparent” 函数的示例。
我希望它能有所帮助。
此函数选择一张图片,将其方形裁剪,按要求的大小重新采样,最后将其与另一张图片合并,以获得圆形图片结果。 我在获得尊重颜色且同时以圆形形式裁剪的缩略图方面遇到了问题,我希望此解决方案可以为您提供获得自由形式图像的线索,我用它也创建了多裁剪图像。

<?php
$generalsrc
="$image"; //要重采样、调整大小和图标化的图像
$final_thumbwidth ="125";
$final_thumbheight ="125";

$abc = imagecreatefromjpeg("$generalsrc");
$def = imagecreatetruecolor($final_thumbwidth, $final_thumbheight);
$src_mx = round((imagesx($abc) / 2)-"0.1"); //图像的中间x点
$src_my = round((imagesy($abc) / 2)-"0.1"); //图像的中间y点
$src_x = ($src_mx * 2);
$src_y = ($src_my * 2);
$src_sq = ($src_x >= $src_y)?$src_y:$src_x; //用于定义图像正方形裁剪的最佳大小
$pl = ($src_x >= $src_y)?"1":"2"; //定义图像是否为纵向或横向
$strt_pntx = ($pl=="1")?round(($src_my / 2)-"0. 1"):"0"; //定义x起始点
$strt_pnty = ($pl=="2")?round(($src_mx / 2)-"0. 1"):"0"; //定义y起始点

imagecopyresized($def, $abc, 0, 0, $strt_pntx, $strt_pnty, $final_thumbwidth, $final_thumbheight, $src_sq, $src_sq);

$overlay_img = imagecreatefromPNG("circle_125.png"); //注意使用png
$src_w = "ImageSX($overlay_img)";
$src_h = "ImageSY($overlay_img)";

$can_img = imagecreatetruecolor($src_w, $src_h);

$black = ImageColorAllocate ($overlay_img, 0, 0, 0);

ImageColorTransparent($overlay_img , $black);

imagecopy($can_img, $def, 0,0,0,0, $src_w, $src_h);
imagecopymerge($can_img, $overlay_img , 0,0,0,0, ImageSX($overlay_img), ImageSY($overlay_img),100); //Imagecopy 不起作用,您必须使用 imagecopymerge

ImageJPEG($can_img,"merge_$generalsrc",100);

imagedestroy($overlay_img);
imagedestroy($can_img);
ImageDestroy($abc);
ImageDestroy($def);

print
"<HTML><HEAD><TITLE>test</TITLE></HEAD><BODY>
original:<hr><img src=\"
$generalsrc\" width=\"300\"><br><br><br>new:<hr><img src=\"merge_$generalsrc\">
<br>width =
$src_x
<br>height =
$src_y
<br>mdlw =
$src_mx
<br>mdlh =
$src_my
<br>sqr =
$src_sq
<br>pl =
$pl
<br>start point x =
$strt_pntx
<br>start point y =
$strt_pnty
</BODY></HTML>"
;
?>
nick at prient dot co dot uk
18年前
任务:旋转大型图像,然后缩小尺寸并将其放置在较小的背景上(例如,作为内嵌)。

问题:如果您先调整图像大小,则旋转会产生极大的锯齿状效果...因此,先旋转再缩小更有意义。
不幸的是,当您对图像进行重采样时,您会丢失背景颜色(至少,部分颜色可能会改变),因此您不能再像需要的那样设置透明度。如果您改为调整图像大小(而不是重采样),则锯齿状效果看起来很糟糕。

解决方案:调整背景大小 - 使其更大。然后添加原始(大型)内嵌,并将整个图像调整回正常大小。

<?php
/* 我们将内嵌缩小到 25% */
$resizePercentage = 0.25;

/* 加载源图像和背景 */
$iSource = ImageCreateFromJpeg($source_file);
$iBackground = ImageCreateFromJpeg($background_file);

/* 在这里执行一些操作,例如旋转、倾斜等 */
...
/* 假设 $iSource 仍然是我们要插入到背景中的图像 */

/* 将背景颜色设置为透明 */
$cBackground = ImageColorClosest($iSource, 255, 0, 255);
ImageColorTransparent($iSource, $cBackground);

/* 调整背景大小 - 使其变大 */
$iBackground = ImageResize($iTemplate, ImageSX($iBackground ) / $resizePercentage, ImageSY($iBackground ) / $resizePercentage);
/* 将图像放置在背景上 - 全尺寸,因此没有混叠问题 */
ImageCopyMerge($iBackground , $iSource,
((
ImageSX($iBackground ) - ImageSX($iSource)) / 2),
((
ImageSY($iBackground ) - ImageSY($iSource)) / 2) - 25, 0, 0, ImageSX($iWorking), ImageSY($iSource), 100);
/* 缩小组合图像... 透明度没有问题! */
$iBackground = ImageResize($iTemplate, ImageSX($iBackground ) * $resizePercentage, ImageSY($iBackground ) * $resizePercentage);

/* 输出图像为 PNG */
header("Content-Type: image/png");
ImagePng($iBackground);
exit();

function
ImageResize($pImage, $t_width, $t_height) {
// 目标图像
$iCanvas = @ImageCreateTrueColor($t_width, $t_height);
// 源尺寸
$s_width = ImageSX($pImage);
$s_height = ImageSY($pImage);
// 复制图像
ImageCopyResampled($iCanvas, $pImage, 0, 0, 0, 0, $t_width, $t_height, $s_width, $s_height);
// 返回图像
return $iCanvas;
}
?>
barbarina_sv at libero dot it
19 年前
我需要在地图上绘制一个“指针”图像,但在 png 图像透明度方面遇到了一些问题。
所以我创建了一个白色背景(不透明)的 png 图像,并在定义白色为透明后将其合并到我的地图上

<?php

$src_file
= 'source.jpg';
list(
$src_w, $src_h, $src_t, $src_a) = getimagesize($src_file);

$ptr_file = 'pointer.png'; // 必须没有透明度,但有白色背景
list($ptr_w, $ptr_h, $ptr_t, $ptr_a) = getimagesize($ptr_file);

// 目标图像尺寸:
$dst_w = 400;
$dst_h = 200;

// 指针位置:
$ptr_x = 195;
$ptr_y = 70;

$srcImage = imageCreateFromJpeg($src_file) or die ('failed imageCreateFromJpg');
$dstImage = imageCreateTrueColor($dst_w, $dst_h) or die ('failed imageCreateTrueColor');

imageCopyResampled($dstImage, $srcImage, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h) or die ('failed imageCopyResampled');

$ptrImage = imageCreateFromPng($ptr_file) or die ('failed imageCreateFromPng');

$ptr_white = imageColorAllocate($ptrImage,255,255,255);
imageColorTransparent($ptrImage,$ptr_white);

imageCopyMerge($dstImage, $ptrImage, $ptr_x, $ptr_y, 0, 0, $ptr_w, $ptr_h, 100) or die ('failed imageCopyMerge');

imageJpeg($dstImage,'',100) or die ('failed imageJpeg');

imageDestroy($srcImage) or die ('failed imageDestroy(1)');
imageDestroy($dstImage) or die ('failed imageDestroy(2)');
imageDestroy($ptrImage) or die ('failed imageDestroy(3)');

?>
jonny at sanriowasteland dot net
21 年前
如果您需要将两个 png(或可能是两个 gif)合并,并且它们具有不同的调色板,我发现可以使用此函数。只需将 pct 设置为 99,您就可以运行了。如果将 pct 设置为 100,或者使用 imagecopy,调色板似乎会出错。(它可能只是使用了源图像的调色板。但不要引用我的说法)。
Al
17 年前
检查您的标题... 他是错误的...

<?php
header
("Content-Type: image/png");
?>
thciobanu
13 年前
这是我用来合并两个图像同时尊重 alpha 通道的方法(公式来自维基百科关于 alpha 合成的文章;它们并不漂亮,因为我没有真正尝试使它们看起来如此,而是仅仅让它们工作并在几个月后检查时有意义),带有一个怪癖 - 一个额外的参数(默认情况下为 NULL 以被忽略)用于手动指定一个“透明”颜色,该颜色不会从源复制到目标。与这里其他实现相比,只对 $src_im 进行了一次遍历,但执行了更多的计算。

<?php
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct, $trans = NULL)
{
$dst_w = imagesx($dst_im);
$dst_h = imagesy($dst_im);

// 边界检查
$src_x = max($src_x, 0);
$src_y = max($src_y, 0);
$dst_x = max($dst_x, 0);
$dst_y = max($dst_y, 0);
if (
$dst_x + $src_w > $dst_w)
$src_w = $dst_w - $dst_x;
if (
$dst_y + $src_h > $dst_h)
$src_h = $dst_h - $dst_y;

for(
$x_offset = 0; $x_offset < $src_w; $x_offset++)
for(
$y_offset = 0; $y_offset < $src_h; $y_offset++)
{
// 获取源和目标颜色
$srccolor = imagecolorsforindex($src_im, imagecolorat($src_im, $src_x + $x_offset, $src_y + $y_offset));
$dstcolor = imagecolorsforindex($dst_im, imagecolorat($dst_im, $dst_x + $x_offset, $dst_y + $y_offset));

// 应用透明度
if (is_null($trans) || ($srccolor !== $trans))
{
$src_a = $srccolor['alpha'] * $pct / 100;
// 混合
$src_a = 127 - $src_a;
$dst_a = 127 - $dstcolor['alpha'];
$dst_r = ($srccolor['red'] * $src_a + $dstcolor['red'] * $dst_a * (127 - $src_a) / 127) / 127;
$dst_g = ($srccolor['green'] * $src_a + $dstcolor['green'] * $dst_a * (127 - $src_a) / 127) / 127;
$dst_b = ($srccolor['blue'] * $src_a + $dstcolor['blue'] * $dst_a * (127 - $src_a) / 127) / 127;
$dst_a = 127 - ($src_a + $dst_a * (127 - $src_a) / 127);
$color = imagecolorallocatealpha($dst_im, $dst_r, $dst_g, $dst_b, $dst_a);
// 绘制
if (!imagesetpixel($dst_im, $dst_x + $x_offset, $dst_y + $y_offset, $color))
return
false;
imagecolordeallocate($dst_im, $color);
}
}
return
true;
}

// 像这样使用(与 imagecopymerge 相同)
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct)
// 或者这样
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct, array('red' => 1, 'green' => 2, 'blue' => 3, 'alpha' =>4))
?>
santin1991[at]gmail[dot]com
15 年前
在图像脚本上添加 logo。
<?php
/**
* 将 logo 放置在右下角的 jpeg 图像上
* 使用 stefan 的脚本定位
**/
$logo_file = "logo.png";
$image_file = "img.jpg";
$targetfile = "img2.jpg";
$photo = imagecreatefromjpeg($image_file);
$fotoW = imagesx($photo);
$fotoH = imagesy($photo);
$logoImage = imagecreatefrompng($logo_file);
$logoW = imagesx($logoImage);
$logoH = imagesy($logoImage);
$photoFrame = imagecreatetruecolor($fotoW,$fotoH);
$dest_x = $fotoW - $logoW;
$dest_y = $fotoH - $logoH;
imagecopyresampled($photoFrame, $photo, 0, 0, 0, 0, $fotoW, $fotoH, $fotoW, $fotoH);
imagecopy($photoFrame, $logoImage, $dest_x, $dest_y, 0, 0, $logoW, $logoH);
imagejpeg($photoFrame, $targetfile);
echo
'<img src="'.$targetfile.'" />';
?>
bjorn AT smokingmedia DOT com
21 年前
除了 stefan 的帖子

我发现,如果你使用带有 alpha 通道的 png-24 文件的 imagecopymerge,它不起作用,请使用 imagecopy。
看起来 imagecopymerge 没有像预期的那样尊重 alpha 通道(错误?)。

这里有一些示例代码,用于将图像 (image.png) 放置在背景色或背景图像上。

<?php

$im
= "image.png";
$bg = "ffddee"; // 十六进制颜色表示(例如,#ffffff 表示白色)
$out = "png"; // 或者“jpg”用于输出 jpg 文件
// $backgroundfile = ""; // 可选的背景文件,如果您不想使用颜色

//
// 函数将十六进制颜色代码转换为十进制
//

function colordecode($hex){

$code[r] = hexdec(substr($hex, 0 ,2));
$code[g] = hexdec(substr($hex, 2 ,2));
$code[b] = hexdec(substr($hex, 4 ,2));

return
$code;

}
// end func colordecode

// 创建资源 ID
$image_id = imageCreateFromPNG($im);

// 获取图像大小
$im_X = ImageSX($image_id);
$im_Y = ImageSY($image_id);

// 创建正确大小的真彩色背景图像
// 或使用像这样的背景图像
// $backgroundimage = imageCreateFromPNG($backgroundfile);
$backgroundimage = imagecreatetruecolor($im_X, $im_Y);

// 获取所需的背景色:
// 如果要使用背景图像,请不要使用此选项
$code = colordecode($bg);
$backgroundcolor = ImageColorAllocate($backgroundimage, $code[r], $code[g], $code[b]);
ImageFilledRectangle($backgroundimage, 0, 0, $im_X, $im_Y, $backgroundcolor);

// 将两者合并在一起,并开启 alpha 混合!
ImageAlphaBlending($backgroundimage, true);
imagecopy($backgroundimage, $image_id, 0, 0, 0, 0, $im_X, $im_Y);

// 输出图像:
if($output == "jpg"){
Header( "Content-type: image/jpeg");
ImageJPEG($backgroundimage);
}
else{
Header( "Content-type: image/png");
ImagePNG($backgroundimage);
}

// 销毁内存
ImageDestroy($backgroundimage);
ImageDestroy($image_id);
?>
jylyn at hotmail dot com
18年前
对 nick at prient 提供的代码进行了一些修正

$iTemplate 应该改为 $iBackground
$iWorking 应该改为 $iSource

修正这两个问题后,我发现这个脚本非常有用,谢谢!
Ascent [at] WebAQ.com
19 年前
首先,您需要制作 0 到 9 的 gif 格式图像和背景图像。

<?php
/*
制作随机图像数字校验
20050524 ascent WebAQ.com
*/

$rands = rand(1000,9999);

session_start();
$_SESSION['random_image_number_check'] = $rands;

$bg = './random_image_bg.jpg';
$numimgp = './random_image_number_%d.gif';

$numimg1 = sprintf($numimgp,substr($rands,0,1));
$numimg2 = sprintf($numimgp,substr($rands,1,1));
$numimg3 = sprintf($numimgp,substr($rands,2,1));
$numimg4 = sprintf($numimgp,substr($rands,3,1));
$ys1 = rand(-4,4);
$ys2 = rand(-4,4);
$ys3 = rand(-4,4);
$ys4 = rand(-4,4);

$bgImg = imageCreateFromJPEG($bg);
$nmImg1 = imageCreateFromGIF($numimg1);
$nmImg2 = imageCreateFromGIF($numimg2);
$nmImg3 = imageCreateFromGIF($numimg3);
$nmImg4 = imageCreateFromGIF($numimg4);
imageCopyMerge($bgImg, $nmImg1, 10, $ys1, 0, 0, 20, 30, 50);
imageCopyMerge($bgImg, $nmImg2, 30, $ys2, 0, 0, 20, 30, 50);
imageCopyMerge($bgImg, $nmImg3, 50, $ys3, 0, 0, 20, 30, 50);
imageCopyMerge($bgImg, $nmImg4, 70, $ys4, 0, 0, 20, 30, 50);
header("Content-type: image/jpg");
ImageJPEG($bgImg,"",100);
imagedestroy($bgImg);
imagedestroy($nmImg1);
imagedestroy($nmImg2);
imagedestroy($nmImg3);
imagedestroy($nmImg4);
?>

尽情享受!
killing_wombles0000 at hotmail dot com
13 年前
任何想要创建图像镜像的人。一个简单的过程,从图像底部逐行复制给定数量的像素。每行逐渐变得更加透明。输出 PNG 到屏幕。

这段代码相当硬编码 - 所有四个输入变量(输入图像、镜像高度、起始透明度、图像和镜像之间的间隙)都在这里手动设置。

<?php
$in
= imagecreatefromjpeg('C:\test.jpg');
$reflection_strength = 120; // 开始透明度 (0-127, 0 为不透明)
$reflection_height = 40; // 反射高度,以像素为单位
$gap = 10; // 图片和反射之间的间隙

$orig_height = imagesy($in); // 存储原始图像的高度
$orig_width = imagesx($in); // 存储原始图像的高度
$output_height = $orig_height + $reflection_height + $gap; // 计算输出图像的高度

// 创建新图像以用于输出。 填充透明度。 ALPHA BLENDING 必须为 FALSE
$out = imagecreatetruecolor($orig_width, $output_height);
imagealphablending($out, false);
$bg = imagecolortransparent($out, imagecolorallocatealpha($out, 255, 255, 255, 127));
imagefill($out, 0, 0, $bg);
imagefilledrectangle($out, 0, 0, imagesx($in), imagesy($in), $bg1);

// 将原始图像复制到新图像上,在下方留出用于反射和“间隙”的空间
imagecopyresampled ( $out , $in , 0, 0, 0, 0, imagesx($in), imagesy($in), imagesx($in), imagesy($in));

// 创建新的单行图像,用作应用透明度时的缓冲区
$reflection_section = imagecreatetruecolor(imagesx($in), 1);
imagealphablending($reflection_section, false);
$bg1 = imagecolortransparent($reflection_section, imagecolorallocatealpha($reflection_section, 255, 255, 255, 127));
imagefill($reflection_section, 0, 0, $bg1);

// 1. 逐行复制,从图像的“底部”开始,向上移动。
// 2. 将透明度设置为在 reflection_strength 和 127 之间变化
// 3. 将行复制回原始图像的镜像位置
for ($y = 0; $y<$reflection_height;$y++)
{
$t = ((127-$reflection_strength) + ($reflection_strength*($y/$reflection_height)));
imagecopy($reflection_section, $out, 0, 0, 0, imagesy($in) - $y, imagesx($in), 1);
imagefilter($reflection_section, IMG_FILTER_COLORIZE, 0, 0, 0, $t);
imagecopyresized($out, $reflection_section, $a, imagesy($in) + $y + $gap, 0, 0, imagesx($in) - (2*$a), 1, imagesx($in), 1);
}

// 输出图像以供查看
header('Content-type: image/png');
imagesavealpha($out,true);
imagepng($out);
?>
highton ridley
5 年前
killing_wombles0000 提供了一个几乎可以工作的代码片段,用于镜像图像并增加透明度。 在 stackexchange 上 showdev 的帮助下,以下是经过修正并完全可工作的代码
<?php
$in
= imagecreatefromjpeg('https://picsum.photos/id/1084/536/354?grayscale');
$reflection_strength = 120; // 反射透明度初始值 (0-127,0 表示不透明)
$reflection_height = 40; // 反射高度 (像素)
$gap = 0; // 图片与反射之间的间隙

$orig_height = imagesy($in); // 存储原始图片的高度
$orig_width = imagesx($in); // 存储原始图片的宽度
$output_height = $orig_height + $reflection_height + $gap; // 计算输出图片的高度

// 创建新的输出图片,填充黑色。
$out = imagecreatetruecolor($orig_width, $output_height);
//imagealphablending($out, false);
//$bg = imagecolortransparent($out, imagecolorallocatealpha($out, 255, 255, 255, 127));
$bg = imagecolorallocatealpha($out, 0,0,0,0);
imagefill($out, 0, 0, $bg);
imagefilledrectangle($out, 0, 0, imagesx($in), imagesy($in), $bg);

// 将原始图片复制到新图片上,在下方留出反射和间隙
imagecopyresampled ( $out , $in , 0, 0, 0, 0, imagesx($in), imagesy($in), imagesx($in), imagesy($in));

// 创建新的单行图片作为缓冲区,用于应用透明度
$reflection_section = imagecreatetruecolor(imagesx($in), 1);
imagealphablending($reflection_section, false);
$bg1 = imagecolortransparent($reflection_section, imagecolorallocatealpha($reflection_section, 255, 255, 255, 127));
imagefill($reflection_section, 0, 0, $bg1);

// 1. 逐行复制,从图片底部开始,向上移动。
// 2. 设置透明度,在 reflection_strength 和 127 之间变化。
// 3. 将复制的行放回原始图片中的镜像位置。
for ($y = 0; $y<$reflection_height;$y++)
{
$t = ((127-$reflection_strength) + ($reflection_strength*($y/$reflection_height)));
imagecopy($reflection_section, $out, 0, 0, 0, imagesy($in) - $y, imagesx($in), 1);
imagefilter($reflection_section, IMG_FILTER_COLORIZE, 0, 0, 0, $t);
imagecopyresized($out, $reflection_section, 0, imagesy($in) + $y + $gap, 0, 0, imagesx($in) - 0, 1, imagesx($in), 1);
}

// 输出图片以供查看
header('Content-type: image/png');
imagesavealpha($out,true);
imagepng($out);
?>
jay at zylex dot net dot nz
17 年前
你好
我写了这个脚本,将水印图片添加到更大图片的右下角。我知道它非常基础,但目前对我来说足够了。它也是一个适合新手理解的简单函数。它只需要两个图片类型作为参数。

例如
$image = imagecreatefromjpeg("FILELOCATION");
$insert = imagecreatefrompng("WATERMARKFILELOCATION");
$image = image_overlap($image, $insert);

function image_overlap($background, $foreground){
$insertWidth = imagesx($foreground);
$insertHeight = imagesy($foreground);

$imageWidth = imagesx($background);
$imageHeight = imagesy($background);

$overlapX = $imageWidth-$insertWidth-5;
$overlapY = $imageHeight-$insertHeight-5;
imagecolortransparent($foreground,
imagecolorat($foreground,0,0)); imagecopymerge($background,$foreground,
$overlapX,$overlapY,0,0,$insertWidth,$insertHeight,100); return $background;
}

它没有平滑两个图片之间的边缘,但它很容易使用。
To Top