PS:原创文章,如需转载,请注明出处,谢谢!
本文地址:http://flyer0126.iteye.com/blog/1662162
之前项目中应用到根据用户情况,及时生成对应个人信息的附带图片,利用到图片水印问题,今天特意封装了一个操作类,特此记录一下,以备今后之需!
/** * 水印操作类 * * 使用说明: * $wm = new WaterMark(); $wm->setImSrc('./images/123.jpg'); // 设置背景图 $wm->setImWater("./images/456.jpg"); // 设置水印图 $wm->setFont('simhei.ttf', '我就测试一下', 12, '255,0,0'); // 设置水印文字相关(字体库、文本、字体大小、颜色) $wm->mark(1, 2, 1, 9); // 设置是否打印图、位置;是否打印字体、位置 * * @author flyer0126 * @since 2012/08/24 * */ class WaterMark { // 背景图 private $im_src; // 背景图文件 private $im_src_width; // 背景图宽度 private $im_src_height; // 背景图高度 private $src_im; // 由背景图创建的新图 // 水印图 private $im_water; // 水印图文件 private $im_water_width; // 水印图宽度 private $im_water_height; // 水印图高度 private $water_im; // 由水印图创建的新图 // 字体 private $font; // 字体库 private $font_text; // 文本 private $font_size; // 字体大小 private $font_color; // 字体颜色 /** * 设置背景图 * @param $img */ function setImSrc($img) { $this->im_src = $img; //读取背景图片文件 $srcInfo = @getimagesize($this->im_src); $this->im_src_width = $srcInfo[0]; $this->im_src_height = $srcInfo[1]; //取得背景图片 $this->src_im = $this->getType($this->im_src, $srcInfo[2]); } /** * 设置水印图 * @param $img */ function setImWater($img) { $this->im_water = $img; //读取水印图片文件 $waterInfo = @getimagesize($this->im_water); $this->im_water_width = $waterInfo[0]; $this->im_water_height = $waterInfo[1]; //取得水印图片 $this->water_im = $this->getType($this->im_water, $waterInfo[2]); } /** * 设置字体 * @param $font */ function setFont($font, $text, $size, $color) { $this->font = $font; $this->font_text = $text; $this->font_size = $size; //水印文字颜色('255,255,255') $this->font_color = $color; } /** * 根据文件或URL创建一个新图象 * @param $img * @param $type * @return resource */ function getType($img, $type) { switch($type){ case 1:$im = imagecreatefromgif($img);break; case 2:$im = imagecreatefromjpeg($img);break; case 3:$im = imagecreatefrompng($img);break; default:break; } return $im; } /** * 根据位置及水印宽高,获取打印的x/y坐标 * @param $pos * @param $w * @param $h */ function getPos($pos, $w, $h) { switch($pos){ case 0://随机 $posX = rand(0, ($this->im_src_width - $w)); $posY = rand(0, ($this->im_src_height - $h)); break; case 1://1为顶端居左 $posX = 0; $posY = 0; break; case 2://2为顶端居中 $posX = ceil($this->im_src_width - $w) / 2; $posY = 0; break; case 3://3为顶端居右 $posX = $this->im_src_width - $w; $posY = 0; break; case 4://4为中部居左 $posX = 0; $posY = ceil($this->im_src_height - $h) / 2; break; case 5://5为中部居中 $posX = ceil($this->im_src_width - $w) / 2; $posY = ceil($this->im_src_height - $h) / 2; break; case 6://6为中部居右 $posX = $this->im_src_width - $w; $posY = ceil($this->im_src_height - $h) / 2; break; case 7://7为底端居左 $posX = 0; $posY = $this->im_src_height - $h; break; case 8://8为底端居中 $posX = ceil($this->im_src_width - $w) / 2; $posY = $this->im_src_height - $h; break; case 9://9为底端居右 $posX = $this->im_src_width - $w; $posY = $this->im_src_height - $h; break; default://随机 $posX = rand(0,($this->im_src_width - $w)); $posY = rand(0,($this->im_src_height - $h)); break; } return array($posX, $posY); } /** * 校验尺寸 * @param $w * @param $h * @return boolean */ function check_range($w, $h) { // 校验 if( ($this->im_src_width < $w) || ($this->im_src_height < $h) ){ return false; } return true; } /** * 打水印操作 * @param $is_image 是1否0水印图片 * @param $image_pos 水印图片位置(0~9) * @param $is_text 是1否0水印文字 * @param $text_pos 水印文字位置(0~9) * 位置:0-随机位置 * 1为顶端居左,2为顶端居中,3为顶端居右; * 4为中部居左,5为中部居中,6为中部居右; * 7为底端居左,8为底端居中,9为底端居右; */ function mark($is_image=0, $image_pos=0, $is_text=0, $text_pos=0) { // 水印图片情况 if ($is_image) { $label = '图片的'; if (!$this->check_range($this->im_water_width, $this->im_water_height)) { echo "需要加水印的图片的长度或宽度比水印".$label."还小,无法生成水印!"; return; } $posArr = $this->getPos($image_pos, $this->im_water_width, $this->im_water_height); $posX = $posArr[0]; $posY = $posArr[1]; // 拷贝水印到目标文件 imagecopy($this->src_im, $this->water_im, $posX, $posY, 0, 0, $this->im_water_width, $this->im_water_height); } // 水印文字情况 if ($is_text) { $label = '文字区域'; //取得此字体的文本的范围 $temp = imagettfbbox($this->font_size, 0, $this->font, $this->font_text); $w = $temp[2] - $temp[0]; $h = $temp[1] - $temp[7]; unset($temp); // 校验 if (!$this->check_range($w, $h)) { echo "需要加水印的图片的长度或宽度比水印".$label."还小,无法生成水印!"; return; } $posArr = $this->getPos($text_pos, $w, $h); $posX = $posArr[0]; $posY = $posArr[1]; // 打印文本 $red = imagecolorallocate($this->src_im, 255, 0, 0); imagettftext($this->src_im, $this->font_size, 0, $posX, $posY, $this->font_color, $this->font, $this->font_text); } // 输出 $this->show(); // 清理 $this->clean(); } /** * 输出图像 */ function show() { header("Content-type: image/png; charset=UTF-8"); imagepng($this->src_im); } /** * 清理 */ function clean() { imagedestroy($this->water_im); imagedestroy($this->src_im); } }
PS:最后特意申明一下,使用汉字打印的话,需要注意以下两点:
1、字体库的选择,可以是 simhei.ttf(黑体) , SIMKAI.TTF(楷体) , SIMFANG.TTF(仿宋) ,SIMSUN.TTC(宋体&新宋体) 等 GD 支持的中文字体。
之前我就是使用simsunb.ttf(简体字),song.TTF(宋体)试了很长时间,发现打印的汉字总是方框,请谨以为戒。
2、 文本编码,需要注意文本编码是否与输出一致,如不一致,请iconv 转换。