PHP面向对象(OOP)——用GD库实现图片水印和缩略图

今天的实现目标就是使用GD库完成对图片加水印和图片缩略图两个功能

动身前逻辑准备

属性:
    路径

功能:
  构造方法

  生成水印的方法
  获取图片信息
  获取位置信息(123 456 789)
  创建图片资源
  合并图片资源
  重新命名
  保存图片
  生成缩略图的方法
  获取图片信息
  获取需要缩放的图片大小
  创建图片资源
  处理一下可能出现的黑边问题
  重新命名
  保存图片

接下来将文字描述转换为代码

首先,创建一个Image类,包含属性和构造方法

class Image()
  {
    //定义图片路径
    static $path = '/';
    //构造方法
    public function __construct($path = '/') {
      $this->path = rtrim($path,'').'/';
    }
  }

接下来完善类中的方法

  • 获取图片信息
static private function getImageInfo($imgPath)
  {
    $info = getimagesize($imgPath);
    return array(
            'width' => $info[0],
            'height'=> $info[1],
            'mime'  => $info['mime'],
            'name'  => basename($imgPath)
    );
  }
  • 检查目标图片与水印图片大小是不是匹配
static private function checksize($dstImgInfo,$waterImgInfo)
 {
   if($waterImgInfo['width'] > $dstImgInfo['width'] || $waterImgInfo['height'] > $dstImgInfo['height'])
     {
       return false;
     } else {
       return true;
     }
 }
  • 根据需要确定水印的位置

    这里将图片分成九宫格

    1 2 3

    4 5 6

    7 8 9

static private function getPosition($dstImgInfo,$waterImgInfo,$postion)
  {
    switch ($position) {
      case 1:
        $x = 0;
        $y = 0;
        break;
      case 2:
        $x = ceil(($desImgInfo['width'] - $waterImgInfo['width']) / 2);
        $y = 0;
        break;
    case 3:
        $x = $dstImgInfo['width'] - $waterImgInfo['width'];
        $y = 0;
    case 4:
        $x = 0;
        $y = ceil(($dstImgInfo['height'] - $waterImgInfo['height']) / 2);
        break;
    case 5:
        $x = ceil(($desImgInfo['width'] -$waterImgInfo['width']) / 2);
        $y = ceil(($dstImgInfo['height'] - $waterImgInfo['height']) / 2);
        break;
    case 6:
        $x = $dstImgInfo['width'] - $waterImgInfo['width'];
        $y = ceil(($dstImgInfo['height'] - $waterImgInfo['height']) / 2);
        break;
    case 7:
        $x = 0;
        $y = $dstImgInfo['height'] - $waterImgInfo['height'];
        break;
    case 8:
        $x = ceil(($desImgInfo['width'] - $waterImgInfo['width']) / 2);
        $y = $dstImgInfo['height'] - $waterImgInfo['height'];
        break;
    case 9:
        $x = $dstImgInfo['width'] - $waterImgInfo['width'];
        $y = $dstImgInfo['height'] - $waterImgInfo['height'];
    }
    return [
                'x' => $x,
                'y' => $y
        ];
  }
  • 根据图片的mime类型创建图片资源
static private function createImgRes($imgPath,$imgInfo)
  {
    switch ($imgInfo['mime']) {
      case 'image/jpg':
      case 'image/jpeg':
      case 'image/pjpeg':
        $res = imagecreatefromjpeg($imgPath);
        break;
      case 'image/png':
      case 'image/x-png':
        $res = imagecreatefrompng($imgPath);
        break;
      case 'image/gif':
        $res = imagecreatefromgif($imgPath);
        break;
      case 'image/bmp':
      case 'image/wbmp':
        $res = imagecreatefromwbmp($imgPath);
        break;
      default:
        exit('图片我们不支持!');
        break;
        }
        return $res;
  }
  • 给原图加上水印
static private function merge($dstImgRes,$waterImgRes,$waterImgInfo,$pos,$opacity)
    {
        imagecopymerge($dstImgRes, $waterImgRes, $pos['x'], $pos['y'], 0, 0, $waterImgInfo['width'], $waterImgInfo['height'], $opacity);

        return $dstImgRes;
    }
    
  • 保存图片
static private function saveImg($newImgRes,$newPath,$dstImgInfo)
    {
  switch ($dstImgInfo['mime']) {
    case 'image/jpg':
    case 'image/jpeg':
    case 'image/pjpeg':
      $res = imagejpeg($newImgRes,$newPath);
      break;
    case 'image/png':
    case 'image/x-png':
      $res = imagepng($newImgRes,$newPath);
      break;
    case 'image/gif':
      $res = imagegif($imgPath);
      break;
    case 'image/bmp':
    case 'image/wbmp':
      $res = imagewbmp($newImgRes,$newPath);
      break;
    default:
      exit('您的破图片我们不支持!');
      break;
    }
}
  • 完成水印生成的公共方法

 *$dstImg:原图像
 *$waterImg:水印图片
 *$postion:水印的位置
 *$prefix:最终生成水印的图片名称前缀
 *$opacity:水印透明度
 */
static public function water($dstImg,$waterImg,$position = 9,$prefix = 'water_',$opacity = 50)
{   
    //判断图片是否存在
  $dstImg = self::$path.$dstImg;
  if(!file_exists($dstImg))
    {
      exit('目标图片不存在');
    }
  if(!file_exists($waterImg))
    {
      exit('水印图片不存在');
    }
  
  //通过自己定义的函数来获取图片和水印图片的信息
  $dstImgInfo = self::getImageInfo($dstImg);
  $waterImgInfo = self::getImageInfo($waterImg);
  
  //检查图片大小的函数
  if(!self::checkSize($dstImgInfo,$waterImgInfo))
    {
      exit('水印图片大小不能超过目标图片的大小');
    }
  //获取水印在目标图片的位置
    $pos = self::getPosition($dstImgInfo,$waterImgInfo,$position);

  //创建图片资源,准备合并
    $dstImgRes = self::createImgRes($dstImg,$dstImgInfo);
    $waterImgRes = self::createImgRes($waterImg,$waterImgInfo);
  //合并图片,生成新图片
    $newImgRes = self::merge($dstImgRes,$waterImgRes,$waterImgInfo,$pos,$opacity);
    $newPath = self::$path.$prefix.uniqid().$dstImgInfo['name'];
    imagedestroy($dstImgRes);
    imagedestroy($waterImgRes);
    imagedestroy($newImgRes);
    //生成新图片
    self::saveImg($newImgRes,$newPath,$dstImgInfo);

    return $newPath;
}

上述面是给图片加水印的全部方法,接下来完成图片缩略图

//生成缩略图的方法
    static public function thump($img,$width,$height,$prefix = 'thump_')
    {
        if(!file_exists($img))
        {
            exit('破图片不存在');
        }
        //获取图片的信息
        //getImageInfo()自定义函数
        $imgInfo = self::getImageInfo($img);
        //创建图片资源
        //createImgRes()自定义函数
        $imgRes  = self::createImgRes($img,$imgInfo);
        //获取新的大小
        //getNewSize()自定义函数--->得到最新的大小
        $newSize = self::getNewSize($width,$height,$imgInfo);
        //解决黑边问题
        //kidOfImage()自定义函数
        $newImgRes = self::kidOfImage($imgRes, $newSize, $imgInfo);
        //拼装缩略后的新的图片名字
        $newPath = $prefix.$newSize['width'].'X'.$newSize['height'].$imgInfo['name'];
        //保存图片
        self::saveImg($newImgRes,$newPath,$imgInfo);

        imagedestroy($newImgRes);
        //返回新的路径
        return $newPath;
    }
  • 重新计算缩略后的图成比例的宽高问题

    static private function getNewSize($width,$height,$imgInfo)
    {
        $size = [];

        //判断缩略后的图的宽度,是不是比原图小
        if($imgInfo['width'] > $width)
        {
            $size['width'] = $width;
        }
        //判断缩略图的高度是不是比原图小
        if($imgInfo['height'] > $height)
        {
            $size['height'] = $height;
        }

        //即使小了,但是不成比例也不可以
        //如果缩略后的宽度是合适的,那么按照比例重新设高度
        if($imgInfo['width'] * $size['width'] > $imgInfo['height'] * $imgInfo['height'])
        {
            $size['height'] = $imgInfo['height'] * $size['width'] / $imgInfo['width'];
        }else{
            //缩略后的高度是合适的,按照比例重新设置宽度
            $size['width'] = $imgInfo['width'] * $size['height'] / $imgInfo['height'];
        }
        return $size;
    }
  • 解决可能出现的黑边问题
    static private function kidOfImage($srcImg, $size, $imgInfo)
    {
        $newImg = imagecreatetruecolor($size["width"], $size["height"]);
        $otsc = imagecolortransparent($srcImg);
        if ( $otsc >= 0 && $otsc < imagecolorstotal($srcImg)) {
             $transparentcolor = imagecolorsforindex( $srcImg, $otsc );
                 $newtransparentcolor = imagecolorallocate(
                 $newImg,
                 $transparentcolor['red'],
                 $transparentcolor['green'],
                 $transparentcolor['blue']
             );

             imagefill( $newImg, 0, 0, $newtransparentcolor );
             imagecolortransparent( $newImg, $newtransparentcolor );
        }

        imagecopyresized( $newImg, $srcImg, 0, 0, 0, 0, $size["width"], $size["height"], $imgInfo["width"], $imgInfo["height"] );
        imagedestroy($srcImg);
        return $newImg;
    }
}

使用方式

Image::water('zhyunfe-com.jpg','2.jpg');

Image::thump('./zhyunfe-com.jpg',50,50);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容