生成水印是整个技术里面最简单的一步。定位水印位置的时候涉及到一点点、最初浅的几何知识。 而上一章我们学习了图片的裁剪技术。水印只不过是图片裁剪技术的一点点的小变形的体现。 一点点几何上的重点知识: 1. 图片大小 2. 图片放在哪个坐标上 3. 图片的宽高 图片水印技术的核心相当于是两张图片:一张大图;一张小图。将小图放置在大图的某个位置上。 水印技术是这个里面最为简单的一个技术,实现方式: 1. 打开原图(也叫操作的目标图片) 2. 打开水印图(也叫水印来源图片) 3. 使用 imagecopymerge 将小图合并至大图的指定位置 4. 输出图片 5. 销毁资源 ##一、简单图片水印 需要加水印的目标图片(假设存储在我电脑的d:/www/img/meinv.jpg),图片如下: ![document/2015-09-22/5600d61ee6dfc](http://box.kancloud.cn/document_2015-09-22_5600d61ee6dfc.png) 需要加上的logo图片(假设存储在我电脑的d:/www/img/logo.png),图片如下: ![document/2015-09-22/5600ed86f1a65](http://box.kancloud.cn/document_2015-09-22_5600ed86f1a65.png) 最主要的是要使用这个函数: > bool imagecopymerge ( resource $目标图片 , resource $来源图片, int $目标开始的x , int $目标开始的y, int $来源的x , int $来源的y , int $来源的宽 , int $来源的高 , int $透明度) 注意: 透明度的值为0-100的整数。imagecopy和imagecopymerge的区别在于一个有透明度,一个没有透明度。 按照总结的步骤,做一个简单的方法: ~~~ <?php //打开目标图片 $dst = imagecreatefrompng('d:/www/img/meinv.jpg'); //打开Logo来源图片 $src = imagecreatefrompng('d:/www/img/logo.png'); //得到目标图片的宽高 $dst_info = getimagesize('fbb.png'); //得到logo图片的宽高 $src_info = getimagesize('logo.png'); //放到最右下脚可得出图片水印图片需要开始的位置即: //x点位置:需要大图的宽 - 小图的宽; //y点位置:放大图的高 - 小图的高 $dst_x = $dst_info[0] - $src_info[0]; $dst_y = $dst_info[1] - $src_info[1]; //要将图片加在右下脚 imagecopymerge($dst, $src, $dst_x, $dst_y, 0, 0, $src_info[0], $src_info[1], 100); header('Content-type:image/png'); imagepng($dst); imagedestroy($dst); imagedestroy($src); ?> ~~~ **我们看看最终的效果如下:** ![document/2015-09-22/5600ee0269dbf](http://box.kancloud.cn/document_2015-09-22_5600ee0269dbf.png) ##二、做一个智能的图片水印函数 一、 我们可以做一个自动化打开图片的函数 之前创建图片或者打开图片的函数我们都学习过: 1. imagecreate 2. imagecreatetruecolor 3. imagecreatefromjpeg等 我们来推理下下。我们如果能够想办法得到图片的MIME类型,根据MIME类型找到打开该文件的函数就行了。 因此,做这一步分为两块来完成: 1. 得到文件MIME类型,返回类型。 2. 传入路径,打开函数,返回资源。 因此,上面两块,我们都可以做成两个函数。 传入图片的路径,将图片的宽、高、图片的MIME类型全部返回一个数组,需要的时候使用对应的参数即可。 我们可以将mime类型传到到$data当中的type关联数组中。代码如下: ~~~ function getImageInfo($path) { $info = getimagesize($path); $data['width'] = $info[0]; $data['height'] = $info[1]; $data['type'] = $info['mime']; return $data; } ~~~ 打开文件的函数,传入一个图片的类型,传入一个图片的路径就打开了图片,返回成了资源类型。 下面的例子中,$type使用swithc...case进行判断,如果是imagejpeg就使用imagecreatefromjpeg来打开$path中路径指定的文件。最后,返回一个资源类型。 ~~~ function openImg($path, $type) { switch ($type) { case 'image/jpeg': case 'image/jpg': case 'image/pjpeg': $img = imagecreatefromjpeg($path); break; case 'image/png': case 'image/x-png': $img = imagecreatefrompng($path); break; case 'image/gif': $img = imagecreatefromgif($path); break; case 'image/wbmp': $img = imagecreatefromwbmp($path); break; default: exit('图片类型不支持'); } return $img; } ~~~ 自动计算位置: 我们可将位置分为10个值,分别为0-9。 我们用画图来表示位置: ![document/2015-09-22/5600ef919671d](http://box.kancloud.cn/document_2015-09-22_5600ef919671d.png) 注: 0为随机位置,可出现在页面中的任意处。但是不能超过图片的范围。 0的位置为: x = 0 至 (大图宽 - 小图宽) y = 0 至 (大图高 - 小图高) 1的位置为: x = 0 y = 0 2的位置为: x = (大图宽 - 小图宽) /2 y = 0 3的位置为: x = 大图宽 - 小图宽 y = 0 4的位置为: x = 0 y = (大图高 - 小图高) / 2 ... ....依此类推。 我们来推理0-9的实现代码: ~~~ switch($pos){ case 1: $x=0; $y=0; break; case 2: $x=ceil(($info['width']-$logo['width'])/2); $y=0; break; case 3: $x=$info['width']-$logo['width']; $y=0; break; case 4: $x=0; $y=ceil(($info['height']-$logo['height'])/2); break; case 5: $x=ceil(($info['width']-$logo['width'])/2); $y=ceil(($info['height']-$logo['height'])/2); break; case 6: $x=$info['width']-$logo['width']; $y=ceil(($info['height']-$logo['height'])/2); break; case 7: $x=0; $y=$info['height']-$logo['height']; break; case 8: $x=ceil(($info['width']-$logo['width'])/2); $y=$info['height']-$logo['height']; break; case 9: $x=$info['width']-$logo['width']; $y=$info['height']-$logo['height']; break; case 0: default: $x=mt_rand(0,$info['width']-$logo['width']); $y=mt_rand(0,$y=$info['height']-$logo['height']); break; } ~~~ 最后调用一下图片的合并、输出和销毁代码即可: > imagecopymerge($dst,$src,$x,$y,0,0,$logo['width'],$logo['height'],$tm); 我们将最终的代码整合好后给大家实验看效果: ~~~ <?php water('zxy.jpg','logo.gif',0,50); function water($img,$water,$pos=9,$tm=100){ $info=getImageInfo($img); $logo=getImageInfo($water); $dst=openImg($img,$info['type']); $src=openImg($water,$logo['type']); switch($pos){ case 1: $x=0; $y=0; break; case 2: $x=ceil(($info['width']-$logo['width'])/2); $y=0; break; case 3: $x=$info['width']-$logo['width']; $y=0; break; case 4: $x=0; $y=ceil(($info['height']-$logo['height'])/2); break; case 5: $x=ceil(($info['width']-$logo['width'])/2); $y=ceil(($info['height']-$logo['height'])/2); break; case 6: $x=$info['width']-$logo['width']; $y=ceil(($info['height']-$logo['height'])/2); break; case 7: $x=0; $y=$info['height']-$logo['height']; break; case 8: $x=ceil(($info['width']-$logo['width'])/2); $y=$info['height']-$logo['height']; break; case 9: $x=$info['width']-$logo['width']; $y=$info['height']-$logo['height']; break; case 0: default: $x=mt_rand(0,$info['width']-$logo['width']); $y=mt_rand(0,$y=$info['height']-$logo['height']); break; } imagecopymerge($dst,$src,$x,$y,0,0,$logo['width'],$logo['height'],$tm); imagejpeg($dst); imagedestory($dst); imagedestory($src); } function openImg($path,$type){ switch($type){ case 'image/jpeg': case 'image/jpg': case 'image/pjpeg': $img=imagecreatefromjpeg($path); break; case 'image/png': case 'image/x-png': $img=imagecreatefrompng($path); break; case 'image/gif': $img=imagecreatefromgif($path); break; case 'image/wbmp': $img=imagecreatefromwbmp($path); break; default: exit('图片类型不支持'); } return $img; } ?> ~~~ *** 本文仅为技术人员交流学习、交流技术使用。 本文中所使用到的图像: 1. 范冰冰女士的形象照片不可用于商业使用。所有权均为范冰冰女士及相关机构所有。 2. 本文中所使用到的logo归百度公司所有。 特此声明!