3

GD库画图的典型流程

  1. 创建画布

  2. 创建各种颜料

  3. 绘画(如,写字,画线,画矩形等形状)

  4. 保存成图片

  5. 清理画布

<meta charset="UTF-8"/>
<?php
    
    $file = './123.jpg';
    
    $im = imagecreatefromjpeg($file);
    
//    var_dump($im);

    // color
    $red = imagecolorallocate($im, 255, 0, 0);
    $blue = imagecolorallocate($im, 0, 0, 255);
        
    // 画线    
    imageline($im, 0, 0, 1024, 768, $red);
    imageline($im, 0, 768, 1024, 0, $blue);
//        imageellipse($im, 200, 200, 100, 100, $red);
    
    
    // 保存图片
//    if ( imagejpeg($im, './ellipse.jpeg') ) {
//        echo '保存成功';
//    } else {
//        echo '保存失败';
//    };    

    // 输出图片
    header("Content-type: image/png");
    imagepng($im);
    
    imagedestroy($im);
    
?>

字母数字验证码

<?php

    // 画布
    $im = imagecreatetruecolor(80, 20);
    
    $red = imagecolorallocate($im, 200, 2, 2);
    
    $str = 'abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789';
    
    $str = substr(str_shuffle($str), 0, 4);
    
//    imagestring($im, 5, 20, 0, 'HELLO WORLD!', $red);
    imagestring($im, 5, 20, 0, $str, $red);

    header("Content-type: image/png");
    
    imagepng($im);
    
    imagedestroy($cat);

?>

中文验证码

<?php
    /**
     * 中文验证码
     * 
     * 0x4E00-0x9FA0
     * 
     * 实际项目中:抽取几百个,几千个常用汉字,放数组里,随机选取.
     */
    
    $ch_str = '的一是在了不和有大这主中人上为们地个用工时要动国产以我到他会作来分生对于学下级就年阶义发成部民可出能方进同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批如应形想制心样干都向变关点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫康遵牧遭幅园腔订香肉弟屋敏恢忘衣孙龄岭骗休借丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩';
    $len = mb_strlen($ch_str, 'utf-8'); // 1500
    $str = array();
     
    for ( $i=0; $i<4; $i++ ) {
        $pos = mt_rand(0, $len-5); // 开始位置
        $str[] = mb_substr($ch_str, $pos, 1, 'utf-8');
    }     

//    $ch_char = array('嘻', '哈', '的', '一', '是', '在');
//    shuffle($ch_char);
//    $code = implode('', array_slice($ch_char, 0, 4));

    $code = implode('', $str);

    $im = imagecreatetruecolor(100, 33);
    
    $color = imagecolorallocate($im, 100, 200, 140);
    $gary = imagecolorallocate($im, 130, 130, 130);
    
    imagefill($im, 0, 0, $gary);
    
    $font = './fang.TTF';
    $angle = mt_rand(0, 5);
    imagettftext($im, 16, $angle, 10, 22, $color, $font, $code);

    header('Content-Type: image/png');
    imagepng($im);
    
    imagedestroy($im);            
        
?>

扭曲验证码

<?php

    /**
     * 扭曲验证码
     */
    
    /**
     * 思路:
     * 建立一个与原始验证码一样大小的画布
     * 
     * 原画布 A
     * 另一个画布 B
     * 
     * A 每一个像素的竖条, 复制到B上
     * 每一个竖条  在上下有波动。
     */
     
    // 普通验证码 -> 扭曲验证码
    
    class Image {
        public static function code() {
            
            $str = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz23456789';
            $text = substr(str_shuffle($str), 0, 4);
            
            $src = imagecreatetruecolor(50, 25);
            $dst = imagecreatetruecolor(50, 25);
            
            $src_gray = imagecolorallocate($src, 200, 200, 200);
            $dst_gray = imagecolorallocate($dst, 200, 200, 200);
            
            imagefill($src, 0, 0, $src_gray);
            imagefill($dst, 0, 0, $dst_gray);
            
            $color = imagecolorallocate($src, mt_rand(50, 255), mt_rand(50, 150), mt_rand(50, 200));
            
            imagestring($src, 6, 7, 5, $text, $color);
            
            // 扭曲
            for ( $i=0; $i<60; $i++ ) {
                
                $offsetY = 3; // 最大波动像素  (px)
                $round = 2; // 2个周期  即 (4π)
                $posY = round(sin( ($round * 2 * M_PI / 60) * $i ) * $offsetY); // 根据正选曲线计算上下波动的 posY 
                
                imagecopy($dst, $src, $i, $posY, $i, 0, 1, 25);
                
            }
            
            // 显示
            header('Content-type: image/png');
            imagepng($dst);
            
            imagedestroy($src);
            imagedestroy($dst);
            
        } 
    }      
    
    echo Image::code();        

?>

图片处理类

  • 水印 : 把指定的水印复制到目标上,并加透明效果

  • 缩略图 : 把大图片复制到小尺寸画面上

图片信息

通过getimagesize() 获取图片的大小,和后缀名.

  1. 判断图片是否存在

  2. getimagesize() 是否是有解析图片信息

  3. 处理图片的大小和后缀信息.

<?php

    
    /**
     * 分析图片的信息
     * @param {String} $image 图片路径 
     * @return {mixin} Array Boolean
     */
    protected static function imageInfo( $image ) {
        
        // 判断图片是否存在
        if(!file_exists($image)) {
            return false;
        }
        $info = getimagesize($image);
        if($info == false) {
            return false;
        }
        
        // 此时info分析出来,是数组
        $img['width'] = $info[0];
        $img['height'] = $info[1];
        $img['ext'] = substr($info['mime'] ,strpos($info['mime'], '/')+1); // 后缀
        
        return $img;            
    }    

?>    

水印

从一张图片中读取到另一张图片上,通过imagecopymerge()实现

  1. 判断图片是否存在

  2. 水印小图片是否比原始图片大

  3. 水印图的位置

  4. 处理水印图

<?php 

    /**
     * 加水印
     * @param {String} $dst 目标图片
     * @param {String} $water 水印小图片
     * @param {String} $save 存储图片位置   默认替换原始图
     * @param {Int} $alpha 透明度
     * @param {Int} $pos 水印位置
     * @return {Boolean} 添加水印是否成功
     */
    protected static function addWater($dst, $water, $save=NULL, $pos=4, $alpha=50) {
         
        // 保证二个文件是否存在
        if(!file_exists($dst) || !file_exists($water)) {
            return false;
        }
        
        $dstInfo = self::imageInfo($dst); // 读取图片信息
        $waeterInfo = self::imageInfo($water); // 读取图片信息 
        
        // 水印不能比待操作图片大
        if( $waeterInfo['height'] > $dstInfo['height'] || $waeterInfo['width'] > $dstInfo['width'] ) {
            return false;
        }
            
        // 两张图片读取到画布上, 使用处理  动态函数读取
        $dFun = 'imagecreatefrom' . $dstInfo['ext'];
        $wFun = 'imagecreatefrom' . $dstInfo['ext'];
        
        // 是否存在函数
        if ( !function_exists($dFun) || !function_exists($wFun) ) {
            return false;
        }
        
        // 动态加载函数创建画布
        $dIm = $dFun($dst); // 创建待操作的画布
        $wIm = $wFun($water); // 创建水印画布
        
        // 处理水印的位置 计算粘贴的坐标
        switch ($pos) {
            case 0: // 左上角
                $posX = 0;
                $posY = 0;
                break;
            case 1: // 右上角
                $posX = $dstInfo['width'] - $waeterInfo['width'];
                $poxY = 0;
                break;
            case 2: // 居中
                $posX = ($dstInfo['width'] - $waeterInfo['width']) / 2;
                $posY = ($dstInfo['height'] - $waeterInfo['height']) / 2;
                break; 
            case 3: // 左下角
                $posX = 0;
                $posY = $dstInfo['height'] - $waeterInfo['height'];
                break;
            case 4: // 右下角
                $posX = $dstInfo['width'] - $waeterInfo['width'];
                $posY = $dstInfo['height'] - $waeterInfo['height'];
                break;
            
            case 5: // 底部中间
                $posX = ($dstInfo['width'] - $waeterInfo['width']) / 2;
                $posY = $dstInfo['height'] - $waeterInfo['height'];
                break;
        }
                                
        // 加水印
        imagecopymerge($dIm, $wIm, $posX, $posY, 0, 0, $waeterInfo['width'], $waeterInfo['height'], $alpha);
                    
        // 保存
        if (!$save) {
            $save = $dst;
            unlink($dst); // 删除原图片
        }
        
        // 生成水印
        $createFun = 'image' . $dstInfo['ext'];
        $createFun($dIm, $save);
            
        imagedestroy($dIm);
        imagedestroy($wIm);
        
        return true;            
    }    

?>

生成缩略图

创建画布生成缩略图,通过imagecopyresampled()

  1. 判断文件是否存在

  2. 图片信息是否为假

  3. 计算缩放比例

  4. 创建画布

  5. 计算留白和宽高

  6. 处理缩略图

    /**
     * thumb 生成缩略图 
     * 等比例缩放,两边留白
     * @param {String} $dst 原始路径
     * @param {String} $save 保存路径
     * @param {Int} $width 缩略图 宽度
     * @param {Int} $height 缩略图 高度
     * @return {Boolen} 生成缩略图是否成功  
     */
    public static function thumb( $dst, $save=NULL, $width=200, $height=200 ) {
        
        // 判断路径是否存在
        if ( !file_exists($dst) ) {
            return false;
        }
        
        $dinfo = self::imageInfo($dst);
        // 图片信息为假
        if ( $dinfo == false ) {
            return false;
        }
        
        // 计算缩放比例
        $calc = min($width / $dinfo['width'], $height / $dinfo['height']);
        
        // 创建原始图画布
        $dfunc = 'imagecreatefrom' . $dinfo['ext'];
        $dim = $dfunc($dst);
        
        // 创建缩略画布
        $tim = imagecreatetruecolor($width, $height);
        
        // 创建白色填充缩略画布
        $while = imagecolorallocate($tim, 255, 255, 255);
        
        imagefill($tim, 0, 0, $while);
        
        // 复制并缩略
        $dwidth = (int)$dinfo['width'] * $calc;
        $dheight = (int)$dinfo['height'] * $calc;
        
        $paddingx = (int)($width - $dwidth) / 2;
        $paddingy = (int)($height - $dheight) / 2 ;
        imagecopyresampled($tim, $dim, $paddingx, $paddingy, 0, 0, $dwidth, $dheight, $width, $height);
        
        // 保存图片
        if ( !$save ) {
            $save = $dst;
            unlink($dst);
        }
        
        $createfun = 'image' . $dinfo['ext'];
        $createfun($tim, $save);
        
        // 销毁
        imagedestroy($dim);
        imagedestroy($tim);
        return true;
        
    }     
?>

ImageTool.class

class ImageTool {
    
    /**
     * 分析图片的信息
     * @param {String} $image 图片路径 
     * @return {mixin} Array Boolean
     */
    protected static function imageInfo( $image ) {
        
        // 判断图片是否存在
        if(!file_exists($image)) {
            return false;
        }
        $info = getimagesize($image);
        if($info == false) {
            return false;
        }
        
        // 此时info分析出来,是数组
        $img['width'] = $info[0];
        $img['height'] = $info[1];
        $img['ext'] = substr($info['mime'] ,strpos($info['mime'], '/')+1); // 后缀
        
        return $img;            
    }    
    
    /**
     * 加水印
     * @param {String} $dst 目标图片
     * @param {String} $water 水印小图片
     * @param {String} $save 存储图片位置   默认替换原始图
     * @param {Int} $alpha 透明度
     * @param {Int} $pos 水印位置
     * @return {Boolean} 添加水印是否成功
     */
    public static function addWater($dst, $water, $save=NULL, $pos=4, $alpha=50) {
         
        // 保证二个文件是否存在
        if(!file_exists($dst) || !file_exists($water)) {
            return false;
        }
        
        $dstInfo = self::imageInfo($dst); // 读取图片信息
        $waeterInfo = self::imageInfo($water); // 读取图片信息 
        
        // 水印不能比待操作图片大
        if( $waeterInfo['height'] > $dstInfo['height'] || $waeterInfo['width'] > $dstInfo['width'] ) {
            return false;
        }
            
        // 两张图片读取到画布上, 使用处理  动态函数读取
        $dFun = 'imagecreatefrom' . $dstInfo['ext'];
        $wFun = 'imagecreatefrom' . $dstInfo['ext'];
        
        // 是否存在函数
        if ( !function_exists($dFun) || !function_exists($wFun) ) {
            return false;
        }
        
        // 动态加载函数创建画布
        $dIm = $dFun($dst); // 创建待操作的画布
        $wIm = $wFun($water); // 创建水印画布
        
        // 处理水印的位置 计算粘贴的坐标
        switch ($pos) {
            case 0: // 左上角
                $posX = 0;
                $posY = 0;
                break;
            case 1: // 右上角
                $posX = $dstInfo['width'] - $waeterInfo['width'];
                $poxY = 0;
                break;
            case 2: // 居中
                $posX = ($dstInfo['width'] - $waeterInfo['width']) / 2;
                $posY = ($dstInfo['height'] - $waeterInfo['height']) / 2;
                break; 
            case 3: // 左下角
                $posX = 0;
                $posY = $dstInfo['height'] - $waeterInfo['height'];
                break;
            case 4: // 右下角
                $posX = $dstInfo['width'] - $waeterInfo['width'];
                $posY = $dstInfo['height'] - $waeterInfo['height'];
                break;
            
            case 5: // 底部中间
                $posX = ($dstInfo['width'] - $waeterInfo['width']) / 2;
                $posY = $dstInfo['height'] - $waeterInfo['height'];
                break;
        }
                                
        // 加水印
        imagecopymerge($dIm, $wIm, $posX, $posY, 0, 0, $waeterInfo['width'], $waeterInfo['height'], $alpha);
                    
        // 保存
        if (!$save) {
            $save = $dst;
            unlink($dst); // 删除原图片
        }
        
        // 生成水印
        $createFun = 'image' . $dstInfo['ext'];
        $createFun($dIm, $save);
            
        imagedestroy($dIm);
        imagedestroy($wIm);
        
        return true;            
    }    
    
    /**
     * thumb 生成缩略图 
     * 等比例缩放,两边留白
     * @param {String} $dst 原始路径
     * @param {String} $save 保存路径
     * @param {Int} $width 缩略图 宽度
     * @param {Int} $height 缩略图 高度
     * @return {Boolen} 生成缩略图是否成功  
     */
    public static function thumb( $dst, $save=NULL, $width=200, $height=200 ) {
        
        // 判断路径是否存在
        if ( !file_exists($dst) ) {
            return false;
        }
        
        $dinfo = self::imageInfo($dst);
        // 图片信息为假
        if ( $dinfo == false ) {
            return false;
        }
        
        // 计算缩放比例
        $calc = min($width / $dinfo['width'], $height / $dinfo['height']);
        
        // 创建原始图画布
        $dfunc = 'imagecreatefrom' . $dinfo['ext'];
        $dim = $dfunc($dst);
        
        // 创建缩略画布
        $tim = imagecreatetruecolor($width, $height);
        
        // 创建白色填充缩略画布
        $while = imagecolorallocate($tim, 255, 255, 255);
        
        imagefill($tim, 0, 0, $while);
        
        // 复制并缩略
        $dwidth = (int)$dinfo['width'] * $calc;
        $dheight = (int)$dinfo['height'] * $calc;
        
        $paddingx = (int)($width - $dwidth) / 2;
        $paddingy = (int)($height - $dheight) / 2 ;
        imagecopyresampled($tim, $dim, $paddingx, $paddingy, 0, 0, $dwidth, $dheight, $width, $height);
        
        // 保存图片
        if ( !$save ) {
            $save = $dst;
            unlink($dst);
        }
        
        $createfun = 'image' . $dinfo['ext'];
        $createfun($tim, $save);
        
        // 销毁
        imagedestroy($dim);
        imagedestroy($tim);
        return true;
        
    } 
    
}

alogy
1.3k 声望121 粉丝

// Designer and Developer