php动图加水印,php+imagemagick给gif动态图片添加水印

favicon.ico摘要:​GD库是php处理图形的扩展库,GD库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片,也可以给图片加水印。但如果用GD库给gif动态图片添加水印,最终动态图片会变成静态的。不过imagemagick可以帮我们解决这个问题。

GD 库是 php 处理图形的扩展库,GD 库提供了一系列用来处理图片的 API,使用 GD 库可以处理图片,或者生成图片,也可以给图片加水印。但如果用 GD 库给 gif 动态图片添加水印,最终动态图片会变成静态的。这是为什么呢?

因为 gif 动态图片和与 jpg、png 图片不一样,gif 动态图片是由一帧一帧的静态图片经过时间轴变化形成的,可以说 gif 是由很多张静态图片组成的。而 GD 库的给图片添加水印的函数 imagecopymerge(),它是对两张图片的处理,即使给的是 gif 动态图片,它也只是从其中拿一帧来操作,所以说 imagecopymerge 处理后得到的是一张图片,即使最后可以将图片保存成 gif 格式,但它只有一帧,所以最后得到的结果是静态图片。

那有什么方法可以给gif动态图片添加水印呢? php+imagemagick 可以给 gif 动态图片添加水印,最后得到的仍然是动态图片。

怎么用 php+imagemagick 给 gif 动态图片添加水印呢?

ImageMagick 是一个免费的创建、编辑、合成图片的软件。php 中要使用它,需要通过 Imagick 扩展来实现。

下面就来说说 php+imagemagick 实现给动态图片添加水印的操作方法。

1、安装 ImageMagick。

在 imageMagick 官网中有提供 Unix 版, Mac OS X 版,IOS 版以及 Windows 版,这里介绍的是 windows 版本的安装。(官网下载地址:https://www.imagemagick.org/script/download.php)

下载最新版的 exe 即可,然后像安装普通程序一样直接安装即可。

20191226_1577348582346587.jpg

正常情况,安装好后会自动将 imageMagick 的安装路径添加到系统环境变量中,当然,你也可以查看下,如果系统环境变量中没有则需要手动添加到系统环境变量。(必需添加到系统环境变量,否则 php 使用不了它)。

20191226_1577348730584997.jpg

2、php 中安装 imagick 扩展。

①下载解压缩

windows 版本 imagick 扩展的下载地址:https://windows.php.net/downloads/pecl/releases/imagick/

,建议选择最新版不带 rc 的,然后找到与 php 版本对应的扩展。

(我们的php版本是 php7.3.4nts vc15-x64:这些信息可以通过 phpinfo 查看,所以应该选择 php_imagick-3.4.4-7.3-nts-vc15-x64.zip 下载)

20191226_1577349315381597.gif

②扩展安装

下载好之后就是安装了,将下载包解压,解压后将 php_imagick.dll 放到 php 的 ext 扩展目录下,将 IM_MOD_*.dll 和 CORE_RL_*.dll 系列的文件全部拷贝到 php 的安装目录下。

20191226_1577349443391054.jpg

③修改配置文件

在 php.ini 中添加如下代码,位置随意[Imagick]

extension=php_imagick.dll

④重启 apache 服务器。

imagick 扩展安装成功,接下来就可以在 php 使用 imagick 扩展来操作哦图片了。

php中使用 imagick 扩展给gif动态图片添加水印

直接上代码吧,然后注释说明://实例化 Imagick ,并传入待添加水印的gif图片路径

$gif  = new Imagick('9.gif');

//实例化 Imagick,传入水印图片路径

$mark = new Imagick('mark.png');

//获取水印图片的尺寸

//返回值是一个包含图片宽度和高度的数组:["width"=> "100", "height"=> "100"]

$markSize = $mark->getImageGeometry();

//这一步是关键,

//返回一个新的Imagick对象,其中序列中的每个图像与第一个图

$gif = $gif->coalesceImages();

foreach ($gif as $img) {

$size = $img->getImageGeometry();

$img->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);

// setImageArtifact 感觉有点像渐变+填充+透明度,具体自己设置不同的值感受下

$img->setImageArtifact('compose:args', "0.5,0.5,0.3,0.3");

$img->compositeImage($mark, Imagick::COMPOSITE_MATHEMATICS, $size['width']-$markSize['width']-5, $size['height']-$markSize['height']-5);

// 变量释放

unset($img);

}

//将添加水印后的动态图片返回

$gif = $gif->deconstructImages();

//输出图片/保存添加水印后的gif动态图片

$gif->writeImages("new7.gif",true);

unset($gif);

unset($mark);

给gif动态图片添加水印就完成了,看看效果图

20191226_1577352895941170.gif

【注意】

1、使用 imagick 扩展在操作动态图片的过程中会产生 imagick 对象缓存文件,而且缓存文件非常大,我在测试过程中用的是一张 接近 1M 的图片,有209帧,在不释放变量前添加水印后生成了 200多个缓存文件,每一个都 超过 10M 。所以,在最后一定要释放所有与 imagick 相关的对象变量。

2、另外,imagick 给gif动态图片添加水印的原理,近似给每一帧图片都加水印,在加上上面所说的产生缓存文件,所以在运行效率比较慢,特别是帧数较多的动图。imagick 还有很大的优化空间。

3、添加水印前,gif动图不到 1M,压缩后接近 3M 。不过静态图片添加水印后大小似乎会变小,75k 的 jpg,添加水印后 70k。

<?php /** *图片水印 *@param $srcImg 原 *@param $waterImg 水印图片 *@param $savepath 保存路径 *@param $savename 保存名字 *@param $position 水印位置 *1:左上 2:右上 3:居中 4:左下 5:右下 *@param $opacity 透明度 *0:全透明 100:完全不透明 *@return 成功 -- 水印后的新图片地址 * 失败 -- -1:源文件不存在,-2:水印不存在,-3源文件图片对象建立失败,-4:水印文件像对象建立失败,-5:水印后的新图片保存失败 * 获取源文件路径、宽高等信息,得出保存后文件保存路径、水印放置位置->建立源文件和水印图片对象->合并图片对象(imagecopymerge)->销毁图片对象 */ function img_create_from_ext($imgfile){ $info = getimagesize($imgfile); $im = null; switch ($info[2]) { case 1: $im = imagecreatefromgif($imgfile); break; case 2: $im = imagecreatefromjpeg($imgfile); break; case 3: $im = imagecreatefrompng($imgfile); break; } return $im; } function img_water_mark($srcImg, $waterImg, $savepath=null, $savename=null, $position=5, $opacity=50){ $temp = pathinfo($srcImg); $name = $temp['basename']; $path = $temp['dirname']; $exte = $temp['extension']; $savename = $savename ? $savename : $name; $savepath = $savepath ? $savepath : $path; $savefile = $savepath.'/'.$savename; $srcinfo = @getimagesize($srcImg); if(!$srcinfo){ return -1; } $waterinfo = @getimagesize($waterImg); if(!$waterinfo){ return -2; } $srcImgObj = img_create_from_ext($srcImg); if(!$srcImgObj){ return -3; } $waterImgObj = img_create_from_ext($waterImg); if(!$waterImgObj){ return -4; } switch ($position) { case 1: $x=$y=0; break; case 2: $x=$srcinfo[0] - $waterinfo[0]; $y=0; break; case 3: $x=($srcinfo[0] - $waterinfo[0])/2; $y=($srcinfo[1] - $waterinfo[1])/2; break; case 4: $x=0; $y=$srcinfo[1] - $waterinfo[1]; break; case 5: $x=$srcinfo[0] - $waterinfo[0]; $y=$srcinfo[1] - $waterinfo[1]; break; } // 合并图片+水印 imagecopymerge($srcImgObj, $waterImgObj, $x, $y, 0, 0, $waterinfo[0], $waterinfo[1], $opacity); switch ($srcinfo[2]) { case 1: imagegif($srcImgObj, $savefile); break; case 2: imagejpeg($srcImgObj, $savefile); break; case 3: imagepng($srcImgObj, $savefile); break; default: return -5; } imagedestroy($srcImgObj); imagedestroy($waterImgObj); return $savefile; } ?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值