GD库是PHP中用于处理图像的扩展库,它可以创建、操作、输出各种格式的图像,如JPEG、PNG、GIF、WebP等。
在PHP开发中,GD库的应用非常广泛:
- 生成验证码图片
- 生成缩略图
- 给图片加水印
- 裁剪、缩放、旋转图片
- 生成图表(柱状图、饼图等)
- 给图片添加文字
- 合成多张图片
GD库是PHP的内置扩展,大部分PHP环境都默认开启了GD库。可以用phpinfo()查看GD库是否开启,也可以用extension_loaded('gd')检查。
今天分享PHP GD库图像处理的详解,从基础到进阶,帮你掌握PHP图像处理的各种技巧。
GD库基础
1. 检查GD库是否开启
if (extension_loaded('gd') && function_exists('gd_info')) {
echo "GD库已开启";
$info = gd_info();
print_r($info); // 查看GD库详细信息
} else {
echo "GD库未开启";
}gd_info()返回GD库的详细信息,包括版本、支持的图像格式等。
2. 创建图像
创建空白图像
$width = 400;
$height = 300;
$image = imagecreatetruecolor($width, $height); // 创建真彩色图像imagecreatetruecolor()创建一个真彩色图像,支持24位颜色,推荐使用。
还有imagecreate()创建调色板图像(256色),现在一般不用了。
从文件创建图像
$image = imagecreatefromjpeg('photo.jpg'); // 从JPEG创建
$image = imagecreatefrompng('photo.png'); // 从PNG创建
$image = imagecreatefromgif('photo.gif'); // 从GIF创建
$image = imagecreatefromwebp('photo.webp'); // 从WebP创建(PHP 5.4+)也可以用imagecreatefromstring()从字符串创建:
$data = file_get_contents('photo.jpg');
$image = imagecreatefromstring($data);3. 颜色
GD库中,颜色用imagecolorallocate()分配:
$red = imagecolorallocate($image, 255, 0, 0); // 红色
$green = imagecolorallocate($image, 0, 255, 0); // 绿色
$blue = imagecolorallocate($image, 0, 0, 255); // 蓝色
$white = imagecolorallocate($image, 255, 255, 255); // 白色
$black = imagecolorallocate($image, 0, 0, 0); // 黑色
$transparent = imagecolorallocatealpha($image, 0, 0, 0, 127); // 透明imagecolorallocatealpha()可以设置透明度,0-127,0完全不透明,127完全透明。
4. 填充背景
$image = imagecreatetruecolor(400, 300);
$white = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $white); // 用白色填充整个图像imagefill()从指定坐标开始填充,直到遇到不同颜色的边界。从(0,0)开始填充,就是填充整个背景。
5. 输出图像
header('Content-Type: image/jpeg');
imagejpeg($image); // 输出JPEG到浏览器
imagejpeg($image, 'output.jpg', 80); // 保存为JPEG文件,质量80
imagepng($image); // 输出PNG
imagepng($image, 'output.png'); // 保存为PNG文件
imagegif($image); // 输出GIF
imagewebp($image, 'output.webp', 80); // 保存为WebP(PHP 5.4+)注意:输出图像到浏览器前,要设置正确的Content-Type头,并且不能有任何其他输出(包括空格、换行)。
6. 销毁图像
imagedestroy($image); // 销毁图像,释放内存图像处理完后,要记得销毁图像,释放内存。
基本绘图
1. 画点
$color = imagecolorallocate($image, 255, 0, 0);
imagesetpixel($image, 100, 100, $color); // 在(100,100)画一个红色点2. 画线
$color = imagecolorallocate($image, 255, 0, 0);
imageline($image, 0, 0, 400, 300, $color); // 从(0,0)到(400,300)画一条红线3. 画矩形
$color = imagecolorallocate($image, 255, 0, 0);
imagerectangle($image, 50, 50, 350, 250, $color); // 画矩形边框
imagefilledrectangle($image, 50, 50, 350, 250, $color); // 画填充矩形4. 画椭圆
$color = imagecolorallocate($image, 255, 0, 0);
imageellipse($image, 200, 150, 200, 100, $color); // 画椭圆边框
imagefilledellipse($image, 200, 150, 200, 100, $color); // 画填充椭圆圆心在(200,150),宽200,高100。宽高相等就是圆。
5. 画多边形
$color = imagecolorallocate($image, 255, 0, 0);
$points = [
200, 50, // 点1
350, 250, // 点2
50, 250, // 点3
];
imagepolygon($image, $points, 3, $color); // 画三角形边框
imagefilledpolygon($image, $points, 3, $color); // 画填充三角形6. 画弧线
$color = imagecolorallocate($image, 255, 0, 0);
imagearc($image, 200, 150, 200, 100, 0, 180, $color); // 画弧线
// 圆心(200,150),宽200,高100,起始角度0度,结束角度180度添加文字
1. 用imagestring添加文字
$color = imagecolorallocate($image, 255, 0, 0);
imagestring($image, 5, 100, 100, 'Hello World', $color);
// 字体大小1-5,位置(100,100),文字内容,颜色imagestring()只能用GD内置的5种字体,不支持中文,适合简单的英文文字。
2. 用imagettftext添加TrueType文字(推荐)
$color = imagecolorallocate($image, 255, 0, 0);
$font = 'fonts/msyh.ttf'; // 字体文件路径
imagettftext($image, 20, 0, 100, 100, $color, $font, '你好,世界');
// 图像,字号20,角度0,位置(100,100),颜色,字体文件,文字imagettftext()支持TrueType字体,可以显示中文,字体大小任意,推荐使用。
注意:
- 字体文件路径要正确,建议用绝对路径
- 中文字体文件(如微软雅黑、宋体、黑体)要确保有版权
- 角度0是水平,正数是逆时针旋转
3. 文字居中
$font = 'fonts/msyh.ttf';
$fontSize = 20;
$text = '居中文字';
$bbox = imagettfbbox($fontSize, 0, $font, $text);
$textWidth = $bbox[2] - $bbox[0]; // 文字宽度
$textHeight = $bbox[1] - $bbox[7]; // 文字高度
$x = (imagesx($image) - $textWidth) / 2; // 水平居中
$y = (imagesy($image) + $textHeight) / 2; // 垂直居中
imagettftext($image, $fontSize, 0, $x, $y, $color, $font, $text);图像处理常用操作
1. 生成缩略图
$source = imagecreatefromjpeg('photo.jpg');
$srcWidth = imagesx($source);
$srcHeight = imagesy($source);
$thumbWidth = 200;
$thumbHeight = 200;
$thumb = imagecreatetruecolor($thumbWidth, $thumbHeight);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $srcWidth, $srcHeight);
header('Content-Type: image/jpeg');
imagejpeg($thumb);
imagedestroy($source);
imagedestroy($thumb);imagecopyresampled()是高质量的缩放函数,推荐使用。
2. 等比例缩放
function resizeImage($source, $maxWidth, $maxHeight) {
$srcWidth = imagesx($source);
$srcHeight = imagesy($source);
$scale = min($maxWidth / $srcWidth, $maxHeight / $srcHeight);
$newWidth = (int)($srcWidth * $scale);
$newHeight = (int)($srcHeight * $scale);
$dest = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($dest, $source, 0, 0, 0, 0, $newWidth, $newHeight, $srcWidth, $srcHeight);
return $dest;
}3. 裁剪图片
$source = imagecreatefromjpeg('photo.jpg');
$destWidth = 200;
$destHeight = 200;
$srcX = 100; // 裁剪起始X
$srcY = 100; // 裁剪起始Y
$dest = imagecreatetruecolor($destWidth, $destHeight);
imagecopyresampled($dest, $source, 0, 0, $srcX, $srcY, $destWidth, $destHeight, $destWidth, $destHeight);
imagejpeg($dest, 'cropped.jpg');4. 居中裁剪(生成正方形缩略图)
function squareThumbnail($source, $size) {
$srcWidth = imagesx($source);
$srcHeight = imagesy($source);
// 计算裁剪区域(居中正方形)
if ($srcWidth > $srcHeight) {
$srcSize = $srcHeight;
$srcX = ($srcWidth - $srcHeight) / 2;
$srcY = 0;
} else {
$srcSize = $srcWidth;
$srcX = 0;
$srcY = ($srcHeight - $srcWidth) / 2;
}
$dest = imagecreatetruecolor($size, $size);
imagecopyresampled($dest, $source, 0, 0, $srcX, $srcY, $size, $size, $srcSize, $srcSize);
return $dest;
}5. 添加水印
文字水印
$source = imagecreatefromjpeg('photo.jpg');
$color = imagecolorallocatealpha($source, 255, 255, 255, 50); // 半透明白色
$font = 'fonts/msyh.ttf';
$text = '© 我的博客';
imagettftext($source, 20, 0, 20, imagesy($source) - 20, $color, $font, $text);
imagejpeg($source, 'watermarked.jpg');图片水印
$source = imagecreatefromjpeg('photo.jpg');
$watermark = imagecreatefrompng('watermark.png');
$srcWidth = imagesx($source);
$srcHeight = imagesy($source);
$wmWidth = imagesx($watermark);
$wmHeight = imagesy($watermark);
// 右下角水印
$destX = $srcWidth - $wmWidth - 20;
$destY = $srcHeight - $wmHeight - 20;
imagecopy($source, $watermark, $destX, $destY, 0, 0, $wmWidth, $wmHeight);
imagejpeg($source, 'watermarked.jpg');
imagedestroy($source);
imagedestroy($watermark);6. 旋转图片
$source = imagecreatefromjpeg('photo.jpg');
$rotated = imagerotate($source, 90, 0); // 旋转90度,背景黑色
imagejpeg($rotated, 'rotated.jpg');
imagedestroy($source);
imagedestroy($rotated);7. 翻转图片
function flipImage($source, $mode) {
$width = imagesx($source);
$height = imagesy($source);
$dest = imagecreatetruecolor($width, $height);
if ($mode == 'horizontal') {
// 水平翻转
for ($x = 0; $x < $width; $x++) {
imagecopy($dest, $source, $width - $x - 1, 0, $x, 0, 1, $height);
}
} elseif ($mode == 'vertical') {
// 垂直翻转
for ($y = 0; $y < $height; $y++) {
imagecopy($dest, $source, 0, $height - $y - 1, 0, $y, $width, 1);
}
}
return $dest;
}8. 调整亮度/对比度/灰度
$source = imagecreatefromjpeg('photo.jpg');
imagefilter($source, IMG_FILTER_BRIGHTNESS, 50); // 调整亮度,-255到255
imagefilter($source, IMG_FILTER_CONTRAST, 30); // 调整对比度,-100到100
imagefilter($source, IMG_FILTER_GRAYSCALE); // 灰度化
imagefilter($source, IMG_FILTER_NEGATE); // 反色
imagefilter($source, IMG_FILTER_EMBOSS); // 浮雕效果
imagefilter($source, IMG_FILTER_GAUSSIAN_BLUR); // 高斯模糊
imagefilter($source, IMG_FILTER_SELECTIVE_BLUR); // 模糊
imagefilter($source, IMG_FILTER_MEAN_REMOVAL); // 移除平均
imagefilter($source, IMG_FILTER_SMOOTH, 5); // 平滑
imagefilter($source, IMG_FILTER_PIXELATE, 10); // 像素化
imagefilter($source, IMG_FILTER_COLORIZE, 255, 0, 0, 50); // 着色
imagejpeg($source, 'filtered.jpg');imagefilter()提供了很多滤镜效果,可以方便地处理图片。
实战:生成验证码
session_start();
$width = 120;
$height = 40;
$image = imagecreatetruecolor($width, $height);
// 背景
$bgColor = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $bgColor);
// 生成随机验证码
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$code = '';
for ($i = 0; $i < 4; $i++) {
$code .= $chars[rand(0, strlen($chars) - 1)];
}
$_SESSION['captcha'] = $code;
// 画干扰点
for ($i = 0; $i < 100; $i++) {
$color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
imagesetpixel($image, rand(0, $width), rand(0, $height), $color);
}
// 画干扰线
for ($i = 0; $i < 5; $i++) {
$color = imagecolorallocate($image, rand(0, 200), rand(0, 200), rand(0, 200));
imageline($image, rand(0, $width), rand(0, $height), rand(0, $width), rand(0, $height), $color);
}
// 画验证码文字
$font = 'fonts/arial.ttf';
for ($i = 0; $i < 4; $i++) {
$color = imagecolorallocate($image, rand(0, 150), rand(0, 150), rand(0, 150));
$fontSize = rand(18, 24);
$angle = rand(-15, 15);
$x = 15 + $i * 25;
$y = rand(25, 35);
imagettftext($image, $fontSize, $angle, $x, $y, $color, $font, $code[$i]);
}
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);实战:上传图片生成缩略图
if ($_FILES['image']['error'] == UPLOAD_ERR_OK) {
$tmpName = $_FILES['image']['tmp_name'];
$name = $_FILES['image']['name'];
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
// 创建图像
switch ($ext) {
case 'jpg':
case 'jpeg':
$source = imagecreatefromjpeg($tmpName);
break;
case 'png':
$source = imagecreatefrompng($tmpName);
break;
case 'gif':
$source = imagecreatefromgif($tmpName);
break;
default:
die('不支持的图片格式');
}
// 生成缩略图(最大宽高200)
$thumb = resizeImage($source, 200, 200);
// 保存
$newName = uniqid() . '.jpg';
imagejpeg($source, 'uploads/' . $newName, 80);
imagejpeg($thumb, 'uploads/thumb_' . $newName, 80);
imagedestroy($source);
imagedestroy($thumb);
echo "上传成功:" . $newName;
}最佳实践
- 用完销毁图像:图像处理完后,用
imagedestroy()销毁,释放内存。 - 用imagecopyresampled不用imagecopyresized:前者质量更高。
- 用TrueType字体显示中文:
imagettftext()支持中文,imagestring()不支持。 - 注意内存限制:处理大图片时,GD库会占用大量内存,可能超出PHP内存限制。可以用
iniset('memorylimit', '256M')临时增加内存。 - 图片格式选择:照片用JPEG(有损压缩,文件小),透明图片用PNG,动画用GIF,WebP是新格式,压缩率更高。
- 错误处理:图像处理可能失败(文件不存在、格式不支持、内存不足),要做好错误处理。
- 缓存处理后的图片:如果图片处理比较耗时,可以把处理后的图片缓存起来,下次直接用缓存。
- 安全:用户上传的图片,要验证格式和大小,避免安全风险。不要把用户上传的图片放在可执行目录。
常见问题
1. Call to undefined function imagecreatefromjpeg
原因:GD库没有开启,或者GD库不支持JPEG。 解决:在php.ini中开启extension=gd(PHP 8)或extension=phpgd2.dll(PHP 7),重启服务器。用gdinfo()查看支持的格式。
2. 中文显示乱码或方框
原因:字体不支持中文,或者字体文件路径错误。 解决:用支持中文的TrueType字体(如微软雅黑、宋体),确保字体文件路径正确。
3. 内存溢出
原因:处理大图片时,GD库占用内存超出PHP限制。 解决:用iniset('memorylimit', '256M')增加内存限制,或者先缩小图片再处理。
4. 输出图片时显示乱码
原因:输出图片前有其他输出(空格、换行、BOM头),或者没有设置Content-Type头。 解决:确保输出图片前没有任何输出,设置正确的Content-Type头。PHP文件不要有BOM头。
5. 图片处理后质量变差
原因:JPEG质量设置太低,或者用了imagecopyresized()而不是imagecopyresampled()。 解决:JPEG质量设置80以上,用imagecopyresampled()高质量缩放。
总结
PHP GD库是PHP图像处理的强大工具,掌握它能让你处理各种图片需求。
核心要点:
- 基础操作:创建图像(imagecreatetruecolor/imagecreatefromjpeg)、颜色(imagecolorallocate)、填充(imagefill)、输出(imagejpeg/imagepng)、销毁(imagedestroy)
- 绘图:画点、画线、画矩形、画椭圆、画多边形、画弧线
- 文字:imagestring(简单英文)、imagettftext(TrueType,支持中文)、文字居中
- 常用操作:生成缩略图、等比例缩放、裁剪、居中裁剪、添加水印(文字/图片)、旋转、翻转、滤镜
- 实战:生成验证码、上传图片生成缩略图
- 最佳实践:用完销毁、用高质量函数、TrueType字体、注意内存、选择合适格式、错误处理、缓存、安全
GD库功能强大,能满足大部分图像处理需求。希望这篇文章能帮你掌握PHP GD库图像处理。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录