PHP图片水印类(GD库)

来源:转载

这几天学习了一下GD扩展库,昨天写了一个图片验证码,今天继续写了一个给图片增加水印的类。

什么是图片水印

先来看一下什么是水印:

水印,是指在造纸过程中形成的,“夹”在纸中而不是在纸的表面,迎光透视时可以清晰看到有明暗纹理的图形、人像或文字,它是纸张在生产过程中用改变纸浆纤维密度的方法而制成的。通常人民币、购物卷、粮票、证劵等等,都采用此方式,以防止造假

类似的,图片水印就是在自己制作的图片或自己网站的图片上贴上一个标签 , 表明作者信息或网站信息,也可以防止别人盗用。
通常水印可以是文字或者另一图片,并且有一定透明度,不影响原图的查看。

PHP生成水印图的步骤

这里的水印可以是文字或者是图片。
1. 打开需要处理的图片
2. 计算水印的位置
3. 增加水印(文字或图片)
4. 保存新图片
5. 释放资源(可以省略,php可以自动释放)

所使用的GD函数

打开和关闭图片就不说了,这里说的是处理图片水印所需要的GD函数

1.计算文本框大小所需要的函数

array imageftbbox ( float $size , float $angle , string $fontfile , string $text [, array $extrainfo ] )

该函数返回文本框四个角的坐标,利用这些坐标就可以计算出文本的宽度和高度了。

2.计算图片大小所需要的函数:

int imagesx ( resource $image )int imagesy ( resource $image )

imagesx 返回图片宽度,imagesy 返回图片高度

3.贴图函数1

bool imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h )

说明:

将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。

4.贴图函数2

bool imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int $pct )

说明:

将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。两图像将根据 pct 来决定合并程度,其值范围从 0 到 100。当 pct = 0 时,实际上什么也没做,当为 100 时对于调色板图像本函数和 imagecopy() 完全一样,它对真彩色图像实现了 alpha 透明。

5.添加文字水印

array imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color , string $fontfile , string $text )

说明:使用 TrueType 字体将 指定的 text 写入图像。

更详细的说明:请戳这里

PHP图片水印类

下面的图片水印类所实现的功能:
1. 增加文字水印
2. 增加图片水印
3. 保存水印后的图片
4. 输出水印后的图片
5. 可以在9个固定位置增加水印:左上、上中、右上、左中、居中、右中、左下、下中、右下

使用时需要注意的问题:
1.水印图片或者文字大小不能超过原图的大小,否则会处理失败。
2.保存图片和输出到浏览器同时使用时,需要先输出到浏览器,不然无法保存。

图片水印类代码:ImageStamp.class.php

<?php/** * 图片水印类 * 支持文字水印和图片水印, 支持水印透明度设置 * 支持的图片类型: 'jpg', 'png', 'gif' * @author luoluolzb 2017/6/17 */class ImageStamp{ /** * 确定水印位置的常量 * @var const */ const STAMP_TOP = 1, STAMP_BOTTOM = 2, STAMP_LEFT = 4, STAMP_RIGHT = 8, STAMP_CENTER = 16; /** * 水印距离图片边缘的距离(非居中时)常量 * @var const */ const STAMP_SIDE = 10; /** * 水印默认位置 * @var const */ const STAMP_DEFAULT_LOC = 10; //STAMP_BOTTOM | STAMP_RIGHT /** * @var private */ private $fileName, $mimeString, $imgRes; private $imgWidth, $imgHeight; /** * 打开需要加水印的图片 * 此函数可以多次使用, 第二次会覆盖第一次 * @param string $fileName 图片文件 * @return bool 操作结果 */ public function Open($fileName){ if(!file_exists($fileName)){ return false; } if($this->imgRes){ imagedestroy($this->imgRes); } $this->fileName = $fileName; $this->mimeString = self::GetImageMime($fileName); $this->imgRes = self::ImageCreate($fileName, $this->mimeString); if(! $this->imgRes){ return false; } $this->imgWidth = imagesx($this->imgRes); $this->imgHeight = imagesy($this->imgRes); return true; } function __destruct(){ if($this->imgRes){ imagedestroy($this->imgRes); } } /** * 发送图片到浏览器 * @return bool 操作结果 */ public function Send(){ if(! $this->imgRes){ return false; } header('Content-Type: '.$this->mimeString); if($this->mimeString === 'image/jpeg'){ return imagejpeg($this->imgRes); } else if($this->mimeString === 'image/png'){ return imagepng($this->imgRes); } else if($this->mimeString === 'image/gif'){ return imagegif($this->imgRes); } return false; } /** * 保存图片(文件后缀名决定保存类型, 只能是:jpg, png, gif) * @return bool 操作结果 */ public function Save($fileName){ if(! $this->imgRes){ return false; } $t = explode('.', $fileName); $ext = end($t); if($ext === 'jpg'){ return imagejpeg($this->imgRes, $fileName); } else if($ext === 'png'){ return imagepng($this->imgRes, $fileName); } else if($ext === 'gif'){ return imagegif($this->imgRes, $fileName); } return false; } /** * 给图片添加文字水印 * @param string $text 文字 * @param integer $fontSize 字体大小 * @param string $fontFile 字体文件 * @param array $rgba 颜色(rgb+alpha格式, alpha:0-127, 0完全不透明, 127完全透明) * @param integer $location 水印位置(水印位置常量组合而成,使用'|'运算符) * @return bool 操作结果 */ public function AddTextStamp($text, $fontSize, $fontFile, $rgba, $location = self::STAMP_DEFAULT_LOC){ if(! $this->imgRes){ return false; } $color = imagecolorallocatealpha($this->imgRes, $rgba[0], $rgba[1], $rgba[2], $rgba[3]); $box = imagettfbbox($fontSize, 0, $fontFile, $text); $stampWidth = abs($box[2] - $box[0]); $stampHeight = abs($box[7] - $box[1]); if($stampWidth >= $this->imgWidth || $stampHeight >= $this->imgHeight){ return false; } $loc = $this->StampLocation(true, $stampWidth, $stampHeight, $location); return imagettftext($this->imgRes, $fontSize, 0, $loc['x'], $loc['y'], $color, $fontFile, $text); } /** * 给图片添加图片水印 * @param string $stampFile 图片文件 * @param $integer $alpha 水印图的透明度(0~100, 0完全透明, 100完全不透明) * @param string $location 水印位置(水印位置常量组合而成,使用'|'运算符) * @return bool 操作结果 */ public function AddImageStamp($stampFile, $alpha, $location = self::STAMP_DEFAULT_LOC){ if(! $this->imgRes){ return false; } $stampMimeString = self::GetImageMime($stampFile); $stampRes = self::ImageCreate($stampFile, $stampMimeString); if(! $stampRes){ return false; } $stampWidth = imagesx($stampRes); $stampHeight = imagesy($stampRes); if($stampWidth >= $this->imgWidth || $stampHeight >= $this->imgHeight){ return false; } $loc = $this->StampLocation(false, imagesx($stampRes), imagesy($stampRes), $location); return self::imagecopymerge_alpha($this->imgRes, $stampRes, $loc['x'], $loc['y'], 0, 0, $stampWidth, $stampHeight, $alpha); } /** * 私有工具函数: 计算水印位置 * @return array ['x' => , 'y' => ] */ private function StampLocation($isTextStamp, $stampWidth, $stampHeight, $location){ $ret = array( 'x' => self::STAMP_SIDE, 'y' =>self::STAMP_SIDE ); if($location & self::STAMP_LEFT){ $ret['x'] = self::STAMP_SIDE; } else if($location & self::STAMP_RIGHT){ $ret['x'] = $this->imgWidth - $stampWidth - self::STAMP_SIDE; } if($location & self::STAMP_TOP){ if($isTextStamp){ $ret['y'] = $stampHeight + self::STAMP_SIDE; }else{ $ret['y'] = self::STAMP_SIDE; } } else if($location & self::STAMP_BOTTOM){ if($isTextStamp){ $ret['y'] = $this->imgHeight - self::STAMP_SIDE; }else{ $ret['y'] = $this->imgHeight - $stampHeight - self::STAMP_SIDE; } } if($location & self::STAMP_CENTER){ /*竖直方向上的居中*/ if(($location & self::STAMP_LEFT) || ($location & self::STAMP_RIGHT)){ if($isTextStamp){ $ret['y'] = ($this->imgHeight - $stampHeight) / 2 + $stampHeight; }else{ $ret['y'] = ($this->imgHeight - $stampHeight) / 2; } } /*水平方向上的居中*/ else if(($location & self::STAMP_TOP) || ($location & self::STAMP_BOTTOM)){ $ret['x'] = ($this->imgWidth - $stampWidth) / 2; } /*水平和竖直都居中*/ else{ if($isTextStamp){ $ret['y'] = ($this->imgHeight - $stampHeight) / 2 + $stampHeight; }else{ $ret['y'] = ($this->imgHeight - $stampHeight) / 2; } $ret['x'] = ($this->imgWidth - $stampWidth) / 2; } } return $ret; } /** * 通用工具函数: 贴图函数, 并可以设置贴图的alpha透明 * 参数同 imagecopymerge */ public static 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); } /** * 通用工具函数: 获取图片mime类型 * @param string $fileName 图片文件 * @return false 失败, string mime串 */ public static function GetImageMime($fileName){ $fhanle = fopen($fileName,'rb'); if ($fhanle) { $bytes6 = fread($fhanle, 6); fclose($fhanle); if ($bytes6 === false) return false; if (substr($bytes6,0,3) == "/xff/xd8/xff") return 'image/jpeg'; if ($bytes6 == "/x89PNG/x0d/x0a") return 'image/png'; if ($bytes6 == "GIF87a" || $bytes6 == "GIF89a") return 'image/gif'; } return false; } /** * 通用工具函数: 使用gd库打开图片 * @param string $fileName 图片文件 * @return false 操作失败, string $mimeString 图片mime串 */ public static function ImageCreate($fileName, $mimeString){ switch ($mimeString) { case 'image/jpeg': return imagecreatefromjpeg($fileName); break; case 'image/png': return imagecreatefrompng($fileName); break; case 'image/gif': return imagecreatefromgif($fileName); break; default: return false; break; } }}?>

使用方法:(test-ImageStamp.php

<?phprequire 'ImageStamp.class.php';$imgStamp = new ImageStamp();/* 增加文字水印 */$imgStamp->open('3.jpg'); //打开所要处理的图片$text = 'luoluolzb.cn'; //水印文字$fontSize = 16; //文字大小$fontFile = 'Monaco.ttf'; //字体文件$rgba = array(200, 200, 228, 64); //文字颜色(rgb+alpha格式)//左上$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_TOP | ImageStamp::STAMP_LEFT);//上中$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_TOP | ImageStamp::STAMP_CENTER);//右上$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_TOP | ImageStamp::STAMP_RIGHT);//左中$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_LEFT | ImageStamp::STAMP_CENTER);//居中$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_CENTER);//右中$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_RIGHT | ImageStamp::STAMP_CENTER);//左下$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_BOTTOM | ImageStamp::STAMP_LEFT);//下中$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_BOTTOM | ImageStamp::STAMP_CENTER);//右下$imgStamp->AddTextStamp($text, $fontSize, $fontFile, $rgba, ImageStamp::STAMP_BOTTOM | ImageStamp::STAMP_RIGHT);$imgStamp->Save('3stamp.jpg');/* 增加图片水印 */$imgStamp->open('3.jpg'); //打开所要处理的图片$alpha = 70; //水印透明度$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_TOP | ImageStamp::STAMP_LEFT); //左上$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_TOP | ImageStamp::STAMP_CENTER); //上中$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_TOP | ImageStamp::STAMP_RIGHT); //右上$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_LEFT | ImageStamp::STAMP_CENTER); //左中$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_CENTER); //居中$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_RIGHT | ImageStamp::STAMP_CENTER); //右中$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_BOTTOM | ImageStamp::STAMP_LEFT); //左下$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_BOTTOM | ImageStamp::STAMP_CENTER); //下中$imgStamp->AddImageStamp('stamp.png', $alpha, ImageStamp::STAMP_BOTTOM | ImageStamp::STAMP_RIGHT); //右下$imgStamp->Send();?>

原图:

增加文字水印后:

增加图片水印后:

代码下载

最后附上完整代码(带有字体文件和例子图片):
百度云盘链接:http://pan.baidu.com/s/1qYI1JTq
提取密码:0eq1

分享给朋友:
您可能感兴趣的文章:
随机阅读: