PHP Conference Japan 2024

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时,不执行任何操作;pct = 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
/**
* imagecopymerge() 的 PNG ALPHA 通道支持;
* Sina Salek 编制
*
* Ralph Voigt 修复的错误(导致它
* 仅适用于 $src_x = $src_y = 0 的错误。
* 此外,反转不透明度是不必要的。)
* 2011年1月8日
*
**/
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
// 创建剪切资源
$cut = imagecreatetruecolor($src_w, $src_h);

// 将背景的相关部分复制到剪切资源
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);

// 将水印的相关部分复制到剪切资源
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);

// 将剪切资源插入到目标图像
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 int
$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 检查其颜色,如果颜色与 imagesetpixel 匹配则复制。对于大型图像,这非常慢,因此以下代码改进了此过程。

<?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;
}

?>

例如,如果我们有一张照片,我们指定 color = (255, 0, 0),即红色,结果将是相同大小的图像,在原始照片为红色的所有位置都有红色像素,在其他所有位置都有灰色像素。
hotmail上的backglancer
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); 使透明颜色不透明……不知道为什么 :)
[email protected]
15年前
<?php
/**
* PNG图片支持Alpha通道的imagecopymerge()函数;
* 此函数类似于imagecopymerge,但它能很好地处理Alpha通道!
**/

// 修复imagecopymerge函数,使其支持ALPHA通道
// 主要脚本作者:aiden dot mail at freemail dot hu
// 由rodrigo dot polo at gmail dot com 改写为imagecopymerge_alpha()
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
16年前
一些非常有趣的东西:这段代码看起来很正常,它是一种随机裁剪图像片段的方法。

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

然而,尝试运行这段代码后,一个被忽略的细节增加了趣味性。由于第一个定义的颜色被视为背景色,我们从$origim中随机选择了一种颜色作为$imagetodisplay的背景色,但这种随机颜色根据背景图像的权重进行选择。这让我很惊讶(我以为背景会是黑色),但我现在保留了它,因为它看起来不错。
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>
原图:<hr><img src=\"
$generalsrc\" width=\"300\"><br><br><br>新图:<hr><img src=\"merge_$generalsrc\">
<br>宽度 =
$src_x
<br>高度 =
$src_y
<br>中间宽度 =
$src_mx
<br>中间高度 =
$src_my
<br>正方形边长 =
$src_sq
<br>方向 =
$pl
<br>起始点 x =
$strt_pntx
<br>起始点 y =
$strt_pnty
</BODY></HTML>"
;
?>
nick at prient dot co dot uk
19年前
任务:旋转一张大图像,然后缩小它并将其放置在一个小的背景上(例如,作为内嵌图像)。

问题:如果先调整图像大小,则旋转会产生严重的锯齿……因此,最好先旋转,然后再缩小。
不幸的是,当重新采样图像时,会丢失背景颜色(至少某些颜色可能会改变),因此无法按照要求设置透明度。如果改为调整图像大小(而不是重新采样),则锯齿看起来仍然很糟糕。

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

<?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;
}
?>
libero.it的barbarina_sv
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 ('imageCreateFromJpg失败');
$dstImage = imageCreateTrueColor($dst_w, $dst_h) or die ('imageCreateTrueColor失败');

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

$ptrImage = imageCreateFromPng($ptr_file) or die ('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 ('imageCopyMerge失败');

imageJpeg($dstImage,'',100) or die ('imageJpeg失败');

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

?>
sanriowasteland.net的jonny
22年前
如果您需要合并两个具有不同调色板的 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的帖子之外

我发现如果使用imagecopymerge处理带有alpha通道的png-24文件,它不起作用,请改用imagecopy。
看起来imagecopymerge没有按预期那样处理alpha通道(一个bug??)。

这里有一些示例代码,用于将图像(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;

}
// 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 by 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
$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