GD库使用小结---2
接着上一篇。GD库可以折腾很多用法出来,当然得跟画图相关,除了前面的验证码、水印外,还可以进行图片的缩放,裁剪、旋转等操作,这在很多应用中可以见到。
1. 加水印
前面已经知道,我们可以使用imagechar或者imagestring等将字符或字符串(甚至中文字符)绘制到图像上,以达到水印的目的,还有个更好的方式,不仅能加字符水印,还能加图片水印:imagecopy。
原型: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),看名字知道这是复制,第1、2个参数分别是目标图像句柄、源文件句柄,加水印时,如果水印图片是一张小图,加在一张大图上面,那么第一个参数就是大图句柄,第二个参数就是小图句柄。第3、4个参数是水印在目标图像上的x、y坐标值,第5、6个参数是水印图片上开始的x、y坐标值,第7、8个参数是水印图片即将要作为水印的宽和高,因此这个方法的意思就是,将水印图像src_im上左上角顶点坐标为(src_x, src_y)处,宽和高分别为src_w、src_h的部分复制到图像dst_im上,再将这个dst_im图像画到画布上保存或输出,即为加过水印后的图片了,代码:
<?php date_default_timezone_set('Asia/Shanghai');
define('DS', DIRECTORY_SEPARATOR);
// 加水印,文字、图片水印,以图片为例
function watermark($srcFile = '', $markFile = '', $dstFile = '')
{
if(!file_exists($srcFile) || !file_exists($markFile))
{
echo 'file not exists!<br/>';
return false;
}
// 获取原始图片与水印图片的宽高
list($srcWidth, $srcHeight) = getimagesize($srcFile);
list($markWidth, $markHeight) = getimagesize($markFile);
// 水印图片不能比原始图片像素还大
if($markWidth > $srcWidth || $markHeight > $srcHeight)
{
return false;
}
// 获取即将被加水印的原始图片句柄、水印图片句柄
$dstImg = imagecreatefromjpeg($srcFile);
$markImg = imagecreatefrompng($markFile);
// 加水印的位置,简单放在右下角
$dst_x = $srcWidth - $markWidth;
$dst_y = $srcHeight - $markHeight;
// 获取文件信息
$fileinfo = pathinfo($srcFile);
if(empty($dstFile))
{
$dstFile = rtrim($fileinfo['dirname'], DS).DS.'mark_'.$fileinfo['filename'].date('YmdHis').mt_rand(1, 1000).'.jpeg';
}
// 将水印图片复制到已有图片上
imagecopy($dstImg, $markImg, $dst_x, $dst_y, 0, 0, $srcWidth, $srcHeight);
// 将新加完水印的图片保存起来
imagejpeg($dstImg, $dstFile);
imagedestroy($dstImg);
imagedestroy($markImg);
return true;
} $srcFile = 'G:\wamp\www\html\image\p125.jpg'; // 原图片
$markFile = 'G:\wamp\www\html\image\ooopic_5.png'; // 水印图片
watermark($srcFile, $markFile);
效果:
在这里,简单将水印图片放在图片右下角,所以放在图片的右下角要一个简单的计算,调用imagecopy时,从水印图片的左上角顶点(坐标0,0)开始全部(宽高传入水印图片宽高)复制到待加水印图片上,然后imagejpeg绘制图像并保存,注意类似imagejpeg(这里简单使用它)等绘图函数传入第二个参数时是保存图片为一个文件,而不是输出到浏览器,所以也不需调header函数发送头信息。
当然还要搞清楚哪是源文件(src),哪是目标文件(dst),把一张小图加水印到一张大图上时,源文件是小图水印,把它复制到大图上,大图就是目标。
能用图片作为水印,在于imagecopy的第二个参数是图像句柄,所以可以从现有图片来创建一个(如imagecreatefromjpeg),当然也能从现有的字符创建一个字符图像句柄变量---使用imagecreatefromstring方法,所以这个更通用。
2. 图片缩放
很多应用,图片列表是小图,当你点击某一个时,才会展现完整大图,这涉及到一个图片收缩的处理。有两个方法可供使用:imagecopyresized和imagecopyresampled,几乎一样,不同的是后者对图片进行重采样(貌似是我专业的词),所以成图质量更好(重采样的话也得看采取哪种方法,有的会变得更渣),挑一个说:
bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
第一、二个参数与上面相似,如何做到缩放?比如这里,是将原图像上左上角顶点处,坐标为(src_x, src_y),宽高为src_w、src_h的部分图片,画到目标图像上坐标为(dst_x, dst_y),宽高为dst_w、dst_h的地方,所以如果目标图片上的宽高比原图上选取部分的宽高小的话,就成了缩小版了,当然还需要两个左上角顶点的坐标值相同,以jpg类型为例:
<?php
date_default_timezone_set('Asia/Shanghai');
define('DS', DIRECTORY_SEPARATOR);
// 缩小图片
/**
* @param src 原图像路径
* @param percent 缩小比例
* @param dstFile 保存图片的路径
*/
function zoomPic($srcFile = '', $percent = 0.5, $dstFile = '')
{
if(!file_exists($srcFile))
{
return false;
} list($width, $height) = getimagesize($srcFile); // 获取宽高
($percent <= 0 || $percent > 1) && $percent = 0.5;
$newWidth = floor($width * $percent); // 缩小后的宽高
$newHeight = floor($height * $percent); $dstImg = imagecreatetruecolor($newWidth, $newHeight); // 创建新图像宽高的画布
$srcImg = imagecreatefromjpeg($srcFile); // 从原图像文件创建画布 $pathinfo = pathinfo($srcFile);
if(!$dstFile) $dstFile = rtrim($pathinfo['dirname'], DS).DS.'zoom_'.$pathinfo['filename'].date('YmdHis').mt_rand(1, 1000).".jpeg";
// 从源文件左上角顶点开始进行缩小
//imagecopyresized($dstImg, $srcImg, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
// 绘制且保存图像
imagejpeg($dstImg, $dstFile);
// 销毁资源
imagedestroy($dstImg);
imagedestroy($srcImg);
return true;
}
// 测试
$srcFile = 'G:\wamp\www\html\image\p179.jpg';
zoomPic($srcFile);
效果:
在这里,我们可以将原图与小图分两套存放,列表展示小图,低级查就展示原图。
3. 图片裁剪
考虑上面的imagecopyresampled方法,如果不从原图像的左上角开始,而是左上角偏右下某一点开始,切图的宽高也再等于源文件完整的宽高,而是部分宽高,那么新的重采样的图片,就是源图片的一部分,就达到了裁剪的效果,所以裁剪与缩放使用的方法一样
<?php
date_default_timezone_set('Asia/Shanghai');
define('DS', DIRECTORY_SEPARATOR);
// cut a picture
function cutPic($srcFile = '', $x = 0, $y = 0, $width = 16, $height = 16, $dstFile = '')
{
if(!file_exists($srcFile))
{
return false;
}
list($srcWidth, $srcHeight, $type) = getimagesize($srcFile);
$x < 0 && $x = 0;
$y < 0 && $y = 0;
// 宽高设置
(($width + $x) > $srcWidth) && $width = $srcWidth;
(($height + $y) > $srcHeight) && $height = $srcHeight;
($width <= 0) && $width = $srcWidth;
($height <= 0) && $height = $srcHeight; $dstImg = imagecreatetruecolor($width, $height); // 目标文件资源
switch($type)
{
case IMG_GIF:
$srcImg = imagecreatefromgif($srcFile); // 获取源文件资源句柄及扩展名处理,以使用合适的函数和扩展
$ext = 'gif';
$imagefun = 'imagegif';
break;
case IMG_JPG:
$srcImg = imagecreatefromjpeg($srcFile);
$ext = 'jpeg';
$imagefun = 'imagejpeg';
break;
default:
$srcImg = imagecreatefrompng($srcFile);
$ext = 'png';
$imagefun = 'imagepng';
break;
}
// 设置保存剪切后的文件路径
$fileinfo = pathinfo($srcFile);
if(empty($dstFile))
{
$dstFile = rtrim($fileinfo['dirname'], DS).DS.'cut_'.$fileinfo['filename'].date('YmdHis').mt_rand(1, 1000).".{$ext}";
}
// 执行剪切操作
imagecopyresampled($dstImg, $srcImg, 0, 0, $x, $y, $width, $height, $width, $height);
// 画于画布并保存文件
$imagefun($dstImg, $dstFile);
imagedestroy($dstImg);
imagedestroy($srcImg);
return true;
}
// 测试
$srcFile = 'G:\wamp\www\html\image\p221.jpg';
cutPic($srcFile, 50, 50, 50, 50);
效果:
常见的应用是,我们在给自己的某个应用换头像时,头像太大,就会用到裁剪,用这就可以做一个模拟实现。
4. 图片旋转
图片旋转也十分常见,主要用到函数imagerotate,原型:resource imagerotate ( resource $image , float $angle , int $bgd_color [, int $ignore_transparent = 0 ] ),第一个参数是待旋转图像句柄,第二个参数angle 是旋转的角度数值,第三个参数指定一个颜色,即当旋转后出现空的地方是使用哪种颜色填充,第四个参数是指定一个透明色,默认0表示保留透明色。该方法返回一个新的图像句柄,就是经过旋转后的图像资源变量,将它绘制保存即可。还要注意的是,旋转的角度可以指定0到360之间,为逆时针旋转,以jpg为例:
<?php date_default_timezone_set('Asia/Shanghai');
define('DS', DIRECTORY_SEPARATOR);
/**
* 图片旋转
* @param angular 旋转角度值 0-360
*/
function rotatePic($srcFile = '', $angular = 0, $dstFile = '')
{
if(!file_exists($srcFile))
{
echo 'file not exists<br/>';
return false;
} $srcImg = imagecreatefromjpeg($srcFile);
// 处理保存文件地址
$fileinfo = pathinfo($srcFile);
if(empty($dstFile))
{
$dstFile = rtrim($fileinfo['dirname'], DS).DS.'rotate_'.$fileinfo['filename'].date('YmdHis').mt_rand(1, 1000).'.jpeg';
} $white = imagecolorallocate($srcImg, 0xff, 0xff, 0xf1);
// 执行旋转,注意是逆时针方向
$dstImg = imagerotate($srcImg, $angular, $white);
// 画到画布,保存文件
imagejpeg($dstImg, $dstFile);
imagedestroy($dstImg);
imagedestroy($srcImg);
return true;
}
// 测试
$srcFile = 'G:\wamp\www\html\image\p219.jpg';
rotatePic($srcFile, 220);
效果:原图 旋转后
5. 图片翻转
这个在应用中不那么常见。所谓翻转,就是对图像进行镜面翻转,比如以图片中间竖直线为轴线,左边换到右边,右边换到左边,对调一下位置,就是左右翻转。想象一下,以中间竖直线为对称轴的情况,Y轴像素点不变,X轴上的像素点左右对调,仍可以使用imagecopy方法,对于源文件,在复制到目标图像时,进行这个操作,以绕Y轴旋转,jpg类型图片为例
<?php
// 图片翻转
date_default_timezone_set('Asia/Shanghai');
define('DS', DIRECTORY_SEPARATOR);
// 沿Y轴翻转,x坐标值对调
function turnY($srcFile = '', $dstFile = '')
{
if(!file_exists($srcFile))
{
return false;
}
// 原图像句柄和宽高获取
$srcImg = imagecreatefromjpeg($srcFile);
$srcWidth = imagesx($srcImg);
$srcHeight = imagesy($srcImg); $dstImg = imagecreatetruecolor($srcWidth, $srcHeight);
// 沿Y轴翻转,x轴上的像素点左右对调
for($i = 0; $i < $srcWidth; $i++)
{
imagecopy($dstImg, $srcImg, $srcWidth-$i-1, 0, $i, 0, 1, $srcHeight);
}
// 画像保存路径处理
$fileinfo = pathinfo($srcFile);
if(empty($dstFile))
{
$dstFile = rtrim($fileinfo['dirname'], DS).DS.'turnx_'.$fileinfo['filename'].date('YmdHis').mt_rand(1, 1000).'.jpeg';
}
// 绘制图像,保存文件
imagejpeg($dstImg, $dstFile);
imagedestroy($dstImg);
imagedestroy($srcImg);
return false;
}
// 测试
$srcFile = 'G:\wamp\www\html\image\p311.jpg';
turnY($srcFile);
效果: 翻转前 翻转后
主要就是for循环那儿,得到源文件的宽度$srcWidth后,如果源文件上坐标是($i, 0)则对应目标图像上坐标($srcWidth-$i-1, 0),然后将宽度为1个像素,高为源文件整个高度$srcHeight的资源复制过去,循环完成后就全部复制到一个图片上了,相当于是一条一条线的画过去的。
无意浏览手册感觉被坑,看到imageflip函数猜到是这个功能,一看果然是的,可是看的书已经落后几年了,原型:bool imageflip ( resource $image , int $mode ),第一个参数是目标图像资源,第二个参数是翻转的方式,使用php自带的枚举变量即可,有IMG_FLIP_HORIZONTAL(水平)、IMG_FLIP_HORIZONTAL(竖直)、IMG_FLIP_BOTH(水平竖直)三种方式,一个函数即可实现。
反正都挺简单,不如练练手玩玩 :-D
GD库使用小结---2的更多相关文章
- GD库使用小结---1
因为一开始,“大家”都说一般任务中,用php操作图片不常见,像我们这种基本业务型的,就更用不到了,所以先别看,偶就没有看.现在有机会了自然要来玩一把. 以前学过C#的GDI+,交了课程设计后忘得一干二 ...
- php 简单的学习GD库绘制图片并传回给前端实现方式
1.基本的GD库绘制图片汇总 2.后台实现小案例 <?php // $img = imagecreatetruecolor(200,40); // var_dump($img); // 利用GD ...
- PHP的GD库
GD库 PHP通过GD库,可以对JPG.PNG.GIF.SWF等图片进行处理.GD库常用在图片加水印,验证码生成等方面. 绘制线条 要对图形进行操作,首先要新建一个画布,通过imagecreatetr ...
- gd库
1.开启GD库扩展 去掉注释: extension=php_gd2.dll extension_dir='ext目录所在位置' 2.检测GD库是否开启 phpinfo(); //检测扩展是够开启 ex ...
- 已安装php 编译安装 gd库拓展模块
参考资料:http://wenku.baidu.com/link?url=EgXFShYxeJOZSYNQ_7RCBC-6X8OcRRCqVm4qCv49uBk57d6vLBoUpfYdQ-KqJRs ...
- Mac php使用gd库出错 Call to undefined function imagettftext()
第一次在Mac下使用ThinkPHP,用到验证码功能时报如题的错误: Call to undefined function Think\imagettftext() 然后检查自己的GD库,发现安装上了 ...
- scikit-learn 支持向量机算法库使用小结
之前通过一个系列对支持向量机(以下简称SVM)算法的原理做了一个总结,本文从实践的角度对scikit-learn SVM算法库的使用做一个小结.scikit-learn SVM算法库封装了libsvm ...
- GD库处理图像
在PHP5中,动态图象的处理要比以前容易得多.PHP5在php.ini文件中包含了GD扩展包,只需去掉GD扩展包的相应注释就可以正常使用了.PHP5包含的GD库正是升级的GD2库,其中包含支持真彩图像 ...
- 烂泥:centos单独编译安装gd库
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 这几天一直在弄一个商城系统,该系统的源码及数据库都已经上传并创建完毕.但是在安装该系统时,却提示缺少gd库.如下: 使用php探针查看,发现php确实没 ...
随机推荐
- jQuery基础学习8——层次选择器next()和prev()方法
$('.one + div').css("background","#bbffaa"); //和next()方法是等价的,前后关系,和prev()方法是对立的 ...
- CentOS_6.5 64位系统,安装git服务器+客户端
================ git服务器安装 ==================== CentOS安装Git服务器 Centos 6.4 + Git 1.8.2.2 + gitosis## . ...
- java命令行运行jar里的main类
一般运行包含manifest的jar包,可以使用 java -jar <jar-file-name>.jar 如果jar里没有 manifest,则可以使用 java -cp foo.ja ...
- android Studio gradle so的加载
最近在使用Android Studio开发android项目,我的项目是由gradle构建的,gradle的优势文档上有说明,当你不断使用中,我越来越发现,太TMD方便啦,优势大大的明显. 打包,功能 ...
- 定义文档兼容性,让IE按指定的版本解析我们的页面
作为开发人员,特别是作为Web的前端开发人员 ,最悲催的莫过于要不断的,不断的去调试各种浏览器的显示效果,而这其中最让人头痛的莫过于MS下的IE系列浏览器,在IE系列中的调试我们将会发现没有一个是好伺 ...
- mysql 内外链接
外联结:分为外左联结和外右联结. 左联结A.B表的意思就是将表A中的全部记录和表B中联结的字段与表A的联结字段符合联结条件的那些记录形成的记录集的联结,这里注意的是最后出来的记录集会包括表A的全部记录 ...
- SSL协议与数字证书原理
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- BZOJ 4236: JOIOJI MAP
4236: JOIOJI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.ph ...
- Android腾讯微博开发之随机字符串与签名实现
Android腾讯微博开发入门之随机字符串与签名实现 直接上代码 1.Utils类,包括签名和随机字符串 import java.util.Random; import javax.cry ...
- memset用法详解(转)
问题描述: int * cow = new int[n+1]; memset(cow,0,(n+1)*4); 将N+1个元素置成0,为什么不行 memset是对一个字节的int4个字节,因此*4 但是 ...