php实现给一张图片加上水印效果


Posted in PHP onJanuary 02, 2016

php实现给一张图片加上水印效果

<?php
/**
 * 功能:给一张图片加上水印效果
 *      $i 要加水印效果的图片
 *      $t 水印文字
 *      $size 文字大小
 *      $pos 水印的位置
 *      $color 文字的颜色
 *      $flag 是布尔值,主要用来区分是不是原图上加水印
 *      $type 如果$flag等于false 则新图上加上水印 新文件名为 原名_txt.jpg
 */
function txt($i,$t='版权所有',$size=25,$pos=5,$color='rand',$flag=true,$type='_txt'){
  $img = imagecreatefromjpeg($i);
  $w = imagesx($img);
  $h = imagesy($img);
  $font = dirname(__FILE__).'/font/ls.ttf';
  $ps = imagettfbbox($size,0,$font,$t);
  $tw = $ps[4];
  $th = abs($ps[5]);
  switch($pos){
    case 1:break;  
    case 2:break;  
    case 3:break;  
    case 4:break;  
    case 5:$x=($w-$tw)/2;$y=($h-$th)/2+$th;break;  
    case 6:break;  
    case 7:break;  
    case 8:break;  
    case 9:break;  
    default:break;
  }
  $c = getcolor($img,$color);
  imagettftext($img,$size,0,$x,$y,$c,$font,$t);
  if($flag){
    imagejpeg($img,$i); 
  }else{
    $ext = ext($i);
    $ppp = rtrim($i,'.'.$ext);
    $ppp = $ppp.$type.'.'.$ext;
    imagejpeg($img,$ppp);
  }
}
 
function getcolor($i,$c='rand',$a=50){
  $cc = '';
  switch($c){
    case 'white':$cc=imagecolorallocatealpha($i,255,255,255,$a);break;
    case 'black':$cc=imagecolorallocatealpha($i,0,0,0,$a);break;
    case 'red':$cc=imagecolorallocatealpha($i,255,0,0,$a);break;
    case 'green':$cc=imagecolorallocatealpha($i,0,255,0,$a);break;
    case 'blue':$cc=imagecolorallocatealpha($i,0,0,255,$a);break;
    case 'orange':$cc=imagecolorallocatealpha($i,0xff,0x66,0x33,$a);break;
    case 'yellow':$cc=imagecolorallocatealpha($i,255,255,0,$a);break;
    case 'rand':$cc=imagecolorallocatealpha($i,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255),$a);break;
    default:
      $cs = substr($c,1);
      $ok = str_split($cs,2);
      $cc = imagecolorallocatealpha($i,hexdec($ok[0]),hexdec($ok[1]),hexdec($ok[2]),$a);
    break;   
  }
  return $cc;
}
 
 
/**
 * 功能是:返回扩展名
 */
 
function ext($f){
  $exts = explode('.',$f);
  return end($exts);
}
 
/**
 * 功能是:返回文件名,不含扩展名
 */
function name($f){
  $s = explode('/',$f);
  $fn = end($s);
  return rtrim($fn,'.'.ext($f));
}

我们再来看一个支持以图片和文字两种方式给图片添加水印。图片支持GIF,PNG,JPG三种格式,水印图片支持PNG和GIF

function setWater($imgSrc,$markImg,$markText,$TextColor,$markPos,$fontType,$markType)
{

  $srcInfo = @getimagesize($imgSrc);
  $srcImg_w  = $srcInfo[0];
  $srcImg_h  = $srcInfo[1];
    
  switch ($srcInfo[2]) 
  { 
    case 1: 
      $srcim =imagecreatefromgif($imgSrc); 
      break; 
    case 2: 
      $srcim =imagecreatefromjpeg($imgSrc); 
      break; 
    case 3: 
      $srcim =imagecreatefrompng($imgSrc); 
      break; 
    default: 
      die("不支持的图片文件类型"); 
      exit; 
  }
    
  if(!strcmp($markType,"img"))
  {
    if(!file_exists($markImg) || empty($markImg))
    {
      return;
    }
      
    $markImgInfo = @getimagesize($markImg);
    $markImg_w  = $markImgInfo[0];
    $markImg_h  = $markImgInfo[1];
      
    if($srcImg_w < $markImg_w || $srcImg_h < $markImg_h)
    {
      return;
    }
      
    switch ($markImgInfo[2]) 
    { 
      case 1: 
        $markim =imagecreatefromgif($markImg); 
        break; 
      case 2: 
        $markim =imagecreatefromjpeg($markImg); 
        break; 
      case 3: 
        $markim =imagecreatefrompng($markImg); 
        break; 
      default: 
        die("不支持的水印图片文件类型"); 
        exit; 
    }
      
    $logow = $markImg_w;
    $logoh = $markImg_h;
  }
    
  if(!strcmp($markType,"text"))
  {
    $fontSize = 16;
    if(!empty($markText))
    {
      if(!file_exists($fontType))
      {
        return;
      }
    }
    else {
      return;
    }
      
    $box = @imagettfbbox($fontSize, 0, $fontType,$markText);
    $logow = max($box[2], $box[4]) - min($box[0], $box[6]);
    $logoh = max($box[1], $box[3]) - min($box[5], $box[7]);
  }
    
  if($markPos == 0)
  {
    $markPos = rand(1, 9);
  }
    
  switch($markPos)
  {
    case 1:
      $x = +5;
      $y = +5;
      break;
    case 2:
      $x = ($srcImg_w - $logow) / 2;
      $y = +5;
      break;
    case 3:
      $x = $srcImg_w - $logow - 5;
      $y = +15;
      break;
    case 4:
      $x = +5;
      $y = ($srcImg_h - $logoh) / 2;
      break;
    case 5:
      $x = ($srcImg_w - $logow) / 2;
      $y = ($srcImg_h - $logoh) / 2;
      break;
    case 6:
      $x = $srcImg_w - $logow - 5;
      $y = ($srcImg_h - $logoh) / 2;
      break;
    case 7:
      $x = +5;
      $y = $srcImg_h - $logoh - 5;
      break;
    case 8:
      $x = ($srcImg_w - $logow) / 2;
      $y = $srcImg_h - $logoh - 5;
      break;
    case 9:
      $x = $srcImg_w - $logow - 5;
      $y = $srcImg_h - $logoh -5;
      break;
    default: 
      die("此位置不支持"); 
      exit;
  }
    
  $dst_img = @imagecreatetruecolor($srcImg_w, $srcImg_h);
    
  imagecopy ( $dst_img, $srcim, 0, 0, 0, 0, $srcImg_w, $srcImg_h);
    
  if(!strcmp($markType,"img"))
  {
    imagecopy($dst_img, $markim, $x, $y, 0, 0, $logow, $logoh);
    imagedestroy($markim);
  }
    
  if(!strcmp($markType,"text"))
  {
    $rgb = explode(',', $TextColor);
      
    $color = imagecolorallocate($dst_img, $rgb[0], $rgb[1], $rgb[2]);
    imagettftext($dst_img, $fontSize, 0, $x, $y, $color, $fontType,$markText);
  }
    
  switch ($srcInfo[2]) 
  { 
    case 1:
      imagegif($dst_img, $imgSrc); 
      break; 
    case 2: 
      imagejpeg($dst_img, $imgSrc); 
      break; 
    case 3: 
      imagepng($dst_img, $imgSrc); 
      break;
    default: 
      die("不支持的水印图片文件类型"); 
      exit; 
  }
    
  imagedestroy($dst_img);
  imagedestroy($srcim);
}

参数说明:

$imgSrc:目标图片,可带相对目录地址,
$markImg:水印图片,可带相对目录地址,支持PNG和GIF两种格式,如水印图片在执行文件mark目录下,可写成:mark/mark.gif
$markText:给图片添加的水印文字
$TextColor:水印文字的字体颜色
$markPos:图片水印添加的位置,取值范围:0~9
0:随机位置,在1~8之间随机选取一个位置
1:顶部居左 2:顶部居中 3:顶部居右 4:左边居中
5:图片中心 6:右边居中 7:底部居左 8:底部居中 9:底部居右
$fontType:具体的字体库,可带相对目录地址
$markType:图片添加水印的方式,img代表以图片方式,text代表以文字方式添加水印

代码注释:

第4~6行:获取目标图片的宽度和高度
第8~22行:根据图片类型调用不同的函数,获得操作图像标识符

GetImageSize函数知识点:GetImageSize不需要安装 GD度就可使用,其返回值数组有四个元素。索引值0是图片高度。索引值1是图片的宽度。索引值2是图片的文件格式,其值1为GIF格式、2为JPEG/JPG格式、3为PNG格式。索引值3为图片的高与宽字符串,height=xxx width=yyy。返回的图片宽度和高度单位都是像素(pixel)

第24~58行:当选择图片方式给目标图片添加水印时,获取水印图片的宽度和高度,通常情况都是网站的logo。如果目标图片比水印图片宽度或者高度小或者水印图片不存在,则跳出这个函数。

return语句知识点:直接return 表示什么都不返回,直接结束这个函数。也可以理解成返回 NULL。

第60~77行:当选择文字方式给目标图片添加水印时,首先设定水印文字的大小,默认我设置为16px,你可以根据需要自行调整字体大小。如果字体文件不存在,跳出函数,最后通过imagettfbbox函数获得此设定格式的文字的虚拟长宽。

imagettfbbox函数知识点:此函数返回一个含有8个单元的数组表示文本外框的四个角,索引值含义:0代表左下角 X 位置,1代表坐下角 Y 位置,2代表右下角 X 位置,3代表右下角 Y 位置,4代表右上角 X 位置,5代表右上角 Y 位置,6代表左上角 X 位置,7代表左上角 Y 位置。此函数同时需要GD 库和FreeType库的支持
max函数返回参数中数值最大的值。

第79~125行:根据设定的图片水印位置计算具体坐标值,你可以根据效果具体细化水印的位置。

第127~129行:新建一个和目标图片大小一致的图片。

注:由于imagecreatetruecolor函数范围的是一个黑色图片,所以如果你的目标图片是透明的,则生成的新图将不会是透明色。

第131~162行:根据图片或者文字方式,最终生成添加了水印的图片。

调用说明:

以函数调用方式调用即可,当然你也可以以类的方式封装,或者你也可以根据需要将此函数进一步细分模块也可以。当然你现在这样用也是没有任何问题的,我已测试过,请放心使用。

其他说明:

由于imagettftext和imagettfbbox函数需要GD库和FreeType库的支持,如果你的运行环境不支持GD库和FreeType库则文字方式就无法实现,你可以用imagestring函数实现给图片添加文字水印,同时设定下text方式下的$logow和$logoh值即可。

imagejpeg函数也可以设置合成的图片质量。

PHP 相关文章推荐
Discuz 模板引擎的封装类代码
Jul 18 PHP
php设计模式 Mediator (中介者模式)
Jun 26 PHP
理解和运用PHP中的多态性[译]
Aug 02 PHP
PHP 面向对象程序设计(oop)学习笔记(一) - 抽象类、对象接口、instanceof 和契约式编程
Jun 12 PHP
php实现斐波那契数列的简单写法
Jul 19 PHP
PHP性能分析工具XHProf安装使用教程
May 13 PHP
深入浅出php socket编程
May 13 PHP
10条php编程小技巧
Jul 07 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
Aug 31 PHP
yii2 resetful 授权验证详解
May 18 PHP
搭建自己的PHP MVC框架详解
Aug 16 PHP
Laravel向公共模板赋值方法总结
Jun 25 PHP
前端必学之PHP语法基础
Jan 01 #PHP
WordPress中登陆后关闭登陆页面及设置用户不可见栏目
Dec 31 #PHP
WordPress中获取指定分类及其子分类下的文章数目
Dec 31 #PHP
Swoole-1.7.22 版本已发布,修复PHP7相关问题
Dec 31 #PHP
WordPress中给媒体文件添加分类和标签的PHP功能实现
Dec 31 #PHP
简单了解将WordPress中的工具栏移到底部的小技巧
Dec 31 #PHP
WordPress中获取所使用的模板的页面ID的简单方法
Dec 31 #PHP
You might like
PHP中对数据库操作的封装
2006/10/09 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
php+layui数据表格实现数据分页渲染代码
2019/10/26 PHP
javascript this用法小结
2008/12/19 Javascript
nodejs实现黑名单中间件设计
2014/06/17 NodeJs
小心!AngularJS结合RequireJS做文件合并压缩的那些坑
2016/01/09 Javascript
js+html5实现canvas绘制椭圆形图案的方法
2016/05/21 Javascript
js接收并转化Java中的数组对象的方法
2016/08/11 Javascript
JavaScript基于Dom操作实现查找、修改HTML元素的内容及属性的方法
2017/01/20 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
2017/03/01 Javascript
canvas实现爱心和彩虹雨效果
2017/03/09 Javascript
用最简单的方法判断JavaScript中this的指向(推荐)
2017/09/04 Javascript
vue axios数据请求及vue中使用axios的方法
2018/09/10 Javascript
Vue.set()动态的新增与修改数据,触发视图更新的方法
2018/09/15 Javascript
Element InputNumber计数器的使用方法
2020/07/27 Javascript
[02:23]1个至宝=115个英雄特效 最“绿”至宝拉比克“魔导师密钥”登场
2018/12/29 DOTA
让python的Cookie.py模块支持冒号做key的方法
2010/12/28 Python
Python中的字符串类型基本知识学习教程
2016/02/04 Python
Python随机生成数据后插入到PostgreSQL
2016/07/28 Python
python字符串中的单双引
2017/02/16 Python
使用python绘制cdf的多种实现方法
2020/02/25 Python
Tensorflow之梯度裁剪的实现示例
2020/03/08 Python
美国最大的万圣节服装网站:HalloweenCostumes.com
2017/10/12 全球购物
来自美国主售篮球鞋的零售商店:KICKSUSA
2017/11/28 全球购物
英国太阳镜品牌:Taylor Morris Eyewear
2018/04/18 全球购物
Android面试题附答案
2014/12/08 面试题
Oracle的内存结构(Memory structures)
2015/06/10 面试题
优秀党员获奖感言
2014/02/18 职场文书
企业后勤岗位职责
2014/02/28 职场文书
个人社会实践自我鉴定
2014/03/24 职场文书
信用卡工资证明格式
2014/09/13 职场文书
2014年小学校长工作总结
2014/12/08 职场文书
装饰技术负责人岗位职责
2015/04/13 职场文书
工作会议通知
2015/04/15 职场文书
2015年档案管理员工作总结
2015/05/13 职场文书
JavaScript中的宏任务和微任务详情
2021/11/27 Javascript