GD 图像处理
PHP 的 GD 扩展是最常用的图像处理库,支持 JPEG、PNG、GIF、WebP、AVIF 等格式的创建、编辑和输出。虽然功能不如 ImageMagick 全面,但对于常见的缩略图生成、水印添加、验证码生成等场景完全够用。
基础概念
安装
bash
# 编译安装
./configure --with-gd
# Ubuntu/Debian
sudo apt-get install php-gd
# 检查支持格式
php -r "print_r(gd_info());"创建图像
基本操作
php
<?php
declare(strict_types=1);
// 创建 200x100 的真彩色图像
$image = imagecreatetruecolor(200, 100);
// 分配颜色
$red = imagecolorallocate($image, 255, 0, 0);
$green = imagecolorallocate($image, 0, 255, 0);
$blue = imagecolorallocate($image, 0, 0, 255);
$white = imagecolorallocate($image, 255, 255, 255);
// 填充背景
imagefill($image, 0, 0, $white);
// 绘制矩形
imagerectangle($image, 10, 10, 90, 50, $red);
// 绘制填充矩形
imagefilledrectangle($image, 110, 10, 190, 50, $green);
// 绘制线条
imageline($image, 0, 80, 200, 80, $blue);
// 输出为 PNG
header('Content-Type: image/png');
imagepng($image);
// 释放内存
imagedestroy($image);输出格式
php
<?php
declare(strict_types=1);
$image = imagecreatetruecolor(200, 200);
// 输出为 JPEG(质量 0~100)
header('Content-Type: image/jpeg');
imagejpeg($image, null, 85);
// 输出为 PNG(压缩级别 0~9)
header('Content-Type: image/png');
imagepng($image, null, 6);
// 输出为 GIF
header('Content-Type: image/gif');
imagegif($image);
// 输出为 WebP(PHP 5.5+)
header('Content-Type: image/webp');
imagewebp($image, null, 80);
// 保存到文件
imagepng($image, '/tmp/output.png', 9);
imagejpeg($image, '/tmp/output.jpg', 90);
imagewebp($image, '/tmp/output.webp', 80);
imagedestroy($image);图片处理
缩略图生成
php
<?php
declare(strict_types=1);
/**
* 生成缩略图(保持宽高比)
*/
function createThumbnail(
string $sourcePath,
string $destPath,
int $maxWidth,
int $maxHeight
): bool {
// 获取原图尺寸
[$width, $height, $type] = getimagesize($sourcePath);
if ($width === 0 || $height === 0) {
return false;
}
// 计算缩放比例
$ratio = min($maxWidth / $width, $maxHeight / $height);
$newWidth = (int) ($width * $ratio);
$newHeight = (int) ($height * $ratio);
// 创建目标图像
$thumb = imagecreatetruecolor($newWidth, $newHeight);
// 创建源图像(根据格式)
$source = match ($type) {
IMAGETYPE_JPEG => imagecreatefromjpeg($sourcePath),
IMAGETYPE_PNG => imagecreatefrompng($sourcePath),
IMAGETYPE_GIF => imagecreatefromgif($sourcePath),
IMAGETYPE_WEBP => imagecreatefromwebp($sourcePath),
default => throw new RuntimeException("不支持的图片格式"),
};
// PNG 保留透明通道
if ($type === IMAGETYPE_PNG) {
imagealphablending($thumb, false);
imagesavealpha($thumb, true);
$transparent = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
imagefill($thumb, 0, 0, $transparent);
}
// 缩放复制
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
// 保存
$result = match ($type) {
IMAGETYPE_JPEG => imagejpeg($thumb, $destPath, 85),
IMAGETYPE_PNG => imagepng($thumb, $destPath, 6),
IMAGETYPE_GIF => imagegif($thumb, $destPath),
IMAGETYPE_WEBP => imagewebp($thumb, $destPath, 80),
default => false,
};
imagedestroy($thumb);
imagedestroy($source);
return $result;
}
// 使用示例
// createThumbnail('/path/to/large.jpg', '/path/to/thumb.jpg', 200, 150);水印添加
php
<?php
declare(strict_types=1);
/**
* 添加文字水印
*/
function addTextWatermark(
string $imagePath,
string $text,
string $outputPath,
int $fontSize = 20,
string $fontFile = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
): void {
$image = imagecreatefromstring(file_get_contents($imagePath));
$width = imagesx($image);
$height = imagesy($image);
// 创建半透明白色
$white = imagecolorallocatealpha($image, 255, 255, 255, 60);
// 计算文字位置(右下角)
$bbox = imagettfbbox($fontSize, 0, $fontFile, $text);
$textWidth = $bbox[2] - $bbox[0];
$textHeight = $bbox[1] - $bbox[7];
$x = $width - $textWidth - 10;
$y = $height - 10;
// 添加文字
imagettftext($image, $fontSize, 0, $x, $y, $white, $fontFile, $text);
// 保存
$ext = strtolower(pathinfo($imagePath, PATHINFO_EXTENSION));
match ($ext) {
'jpg', 'jpeg' => imagejpeg($image, $outputPath, 90),
'png' => imagepng($image, $outputPath),
'webp' => imagewebp($image, $outputPath, 80),
default => imagepng($image, $outputPath),
};
imagedestroy($image);
}验证码生成
php
<?php
declare(strict_types=1);
/**
* 生成验证码图片
*/
function generateCaptcha(int $length = 6, int $width = 120, int $height = 40): array
{
$image = imagecreatetruecolor($width, $height);
// 背景
$bgColor = imagecolorallocate($image, 240, 240, 240);
imagefill($image, 0, 0, $bgColor);
// 生成随机验证码
$code = '';
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
for ($i = 0; $i < $length; $i++) {
$char = $chars[random_int(0, strlen($chars) - 1)];
$code .= $char;
// 随机颜色
$color = imagecolorallocate($image, random_int(0, 150), random_int(0, 150), random_int(0, 150));
// 随机位置和角度
$x = 10 + ($i * ($width - 20) / $length);
$y = $height / 2 + random_int(-5, 5);
$angle = random_int(-15, 15);
imagettftext($image, random_int(18, 24), $angle, (int) $x, (int) $y, $color,
'/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', $char);
}
// 添加干扰线
for ($i = 0; $i < 5; $i++) {
$lineColor = imagecolorallocate($image, random_int(150, 255), random_int(150, 255), random_int(150, 255));
imageline($image,
random_int(0, $width), random_int(0, $height),
random_int(0, $width), random_int(0, $height),
$lineColor
);
}
// 添加噪点
for ($i = 0; $i < 100; $i++) {
$dotColor = imagecolorallocate($image, random_int(100, 255), random_int(100, 255), random_int(100, 255));
imagesetpixel($image, random_int(0, $width), random_int(0, $height), $dotColor);
}
// 输出
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
return ['code' => $code];
}注意事项
- 大图操作注意内存限制(
memory_limit) - PNG 透明通道需要
imagealphablending和imagesavealpha - WebP 格式需要 PHP 5.5+ 和 libwebp
下一节
继续学习:ImageMagick