本文目录导读:

在PHP中实现图片水印添加,主要使用 GD库 或 Imagick 扩展,以下是两种主流方法的详细实现方案:
使用GD库(最常用,无需额外安装)
文字水印
<?php
function addTextWatermark($sourcePath, $savePath, $text = 'Watermark') {
// 获取原图信息
list($width, $height, $type) = getimagesize($sourcePath);
// 根据图片类型创建资源
switch ($type) {
case IMAGETYPE_JPEG:
$image = imagecreatefromjpeg($sourcePath);
break;
case IMAGETYPE_PNG:
$image = imagecreatefrompng($sourcePath);
break;
case IMAGETYPE_GIF:
$image = imagecreatefromgif($sourcePath);
break;
default:
return false;
}
// 设置水印颜色(白色半透明)
$watermarkColor = imagecolorallocatealpha($image, 255, 255, 255, 50);
// 设置字体文件路径
$fontFile = './font/arial.ttf'; // 需要实际存在的字体文件
// 文字大小
$fontSize = 20;
// 计算文字位置(右下角)
$textBox = imagettfbbox($fontSize, 0, $fontFile, $text);
$textWidth = $textBox[2] - $textBox[0];
$textHeight = $textBox[1] - $textBox[7];
$x = $width - $textWidth - 20;
$y = $height - $textHeight - 20;
// 添加水印
imagettftext($image, $fontSize, 0, $x, $y, $watermarkColor, $fontFile, $text);
// 保存图片
switch ($type) {
case IMAGETYPE_JPEG:
imagejpeg($image, $savePath, 90);
break;
case IMAGETYPE_PNG:
imagepng($image, $savePath);
break;
case IMAGETYPE_GIF:
imagegif($image, $savePath);
break;
}
// 释放内存
imagedestroy($image);
return true;
}
// 使用示例
addTextWatermark('original.jpg', 'watermarked.jpg', '© 2024 My Site');
?>
图片水印(添加Logo)
<?php
function addImageWatermark($sourcePath, $watermarkPath, $savePath, $position = 'bottom-right') {
// 创建原图资源
list($srcWidth, $srcHeight, $srcType) = getimagesize($sourcePath);
switch ($srcType) {
case IMAGETYPE_JPEG:
$mainImg = imagecreatefromjpeg($sourcePath);
break;
case IMAGETYPE_PNG:
$mainImg = imagecreatefrompng($sourcePath);
break;
case IMAGETYPE_GIF:
$mainImg = imagecreatefromgif($sourcePath);
break;
default:
return false;
}
// 创建水印资源
list($wmWidth, $wmHeight, $wmType) = getimagesize($watermarkPath);
switch ($wmType) {
case IMAGETYPE_JPEG:
$watermark = imagecreatefromjpeg($watermarkPath);
break;
case IMAGETYPE_PNG:
$watermark = imagecreatefrompng($watermarkPath);
break;
case IMAGETYPE_GIF:
$watermark = imagecreatefromgif($watermarkPath);
break;
default:
return false;
}
// 计算位置
$padding = 10;
switch ($position) {
case 'top-left':
$x = $padding;
$y = $padding;
break;
case 'top-right':
$x = $srcWidth - $wmWidth - $padding;
$y = $padding;
break;
case 'bottom-left':
$x = $padding;
$y = $srcHeight - $wmHeight - $padding;
break;
case 'bottom-right':
default:
$x = $srcWidth - $wmWidth - $padding;
$y = $srcHeight - $wmHeight - $padding;
break;
}
// 保持PNG透明度
imagealphablending($mainImg, true);
imagesavealpha($mainImg, true);
// 合并图片
imagecopy($mainImg, $watermark, $x, $y, 0, 0, $wmWidth, $wmHeight);
// 保存
switch ($srcType) {
case IMAGETYPE_JPEG:
imagejpeg($mainImg, $savePath, 90);
break;
case IMAGETYPE_PNG:
imagepng($mainImg, $savePath);
break;
case IMAGETYPE_GIF:
imagegif($mainImg, $savePath);
break;
}
imagedestroy($mainImg);
imagedestroy($watermark);
return true;
}
// 使用示例
addImageWatermark('original.jpg', 'logo.png', 'watermarked.jpg', 'bottom-right');
?>
使用Imagick扩展(功能更强大,支持更多格式)
<?php
function addImagickWatermark($sourcePath, $savePath, $type = 'text', $content = 'Watermark') {
$image = new Imagick($sourcePath);
if ($type === 'text') {
// 文字水印
$draw = new ImagickDraw();
$draw->setFillColor(new ImagickPixel('white'));
$draw->setFontSize(30);
$draw->setOpacity(0.5);
$image->annotateImage($draw, 10, $image->getImageHeight() - 30, 0, $content);
} else {
// 图片水印
$watermark = new Imagick($content);
// 设置水印大小(可选)
$watermark->scaleImage(100, 0); // 宽度100px,高度自动
// 设置透明度
$watermark->evaluateImage(Imagick::EVALUATE_MULTIPLY, 0.5, Imagick::CHANNEL_ALPHA);
// 计算位置
$x = $image->getImageWidth() - $watermark->getImageWidth() - 10;
$y = $image->getImageHeight() - $watermark->getImageHeight() - 10;
// 合并图片
$image->compositeImage($watermark, Imagick::COMPOSITE_OVER, $x, $y);
$watermark->destroy();
}
$image->writeImage($savePath);
$image->destroy();
return true;
}
// 使用示例
addImagickWatermark('original.jpg', 'watermarked.jpg', 'text', '© 2024');
// 或者
addImagickWatermark('original.jpg', 'watermarked.jpg', 'image', 'logo.png');
?>
完整的水印类封装
<?php
class Watermark {
private $sourcePath;
private $savePath;
private $type; // gd or imagick
public function __construct($sourcePath, $savePath = null) {
$this->sourcePath = $sourcePath;
$this->savePath = $savePath ?: $sourcePath;
$this->type = extension_loaded('imagick') ? 'imagick' : 'gd';
}
public function addText($text, $options = []) {
$defaults = [
'fontSize' => 20,
'color' => 'white',
'opacity' => 50,
'position' => 'bottom-right',
'fontFile' => './font/arial.ttf'
];
$options = array_merge($defaults, $options);
if ($this->type === 'imagick') {
return $this->addTextImagick($text, $options);
} else {
return $this->addTextGD($text, $options);
}
}
public function addImage($watermarkPath, $options = []) {
$defaults = [
'position' => 'bottom-right',
'opacity' => 80,
'scale' => 0.3 // 水印缩放比例
];
$options = array_merge($defaults, $options);
if ($this->type === 'imagick') {
return $this->addImageImagick($watermarkPath, $options);
} else {
return $this->addImageGD($watermarkPath, $options);
}
}
// 私有方法实现细节...
}
?>
配置检查
<?php
// 检查GD库是否可用
if (function_exists('gd_info')) {
echo "GD库已安装\n";
print_r(gd_info());
}
// 检查Imagick是否可用
if (class_exists('Imagick')) {
echo "Imagick已安装\n";
}
?>
常见问题与优化建议
注意事项:
- 字体文件:使用imagettftext()时需要提供TrueType字体文件路径
- 透明度:PNG水印需要保留透明度信息
- 性能优化:
- 使用缓存机制避免重复处理
- 对于大图片考虑使用缩略图添加水印
- 使用队列系统处理批量水印
最佳实践:
// 异步处理水印
class WatermarkJob {
public function handle($imagePath) {
// 使用队列处理大量图片
$watermark = new Watermark($imagePath);
$watermark->addText('© 2024');
}
}
// 缓存水印处理结果
function getWatermarkedImage($sourcePath) {
$cachePath = './cache/' . md5($sourcePath) . '.jpg';
if (file_exists($cachePath)) {
return $cachePath; // 返回缓存
}
// 生成水印
$watermark = new Watermark($sourcePath, $cachePath);
$watermark->addText('© 2024');
return $cachePath;
}
推荐优先使用 GD库,因为它是PHP内置的,无需额外安装,如果项目需要处理大量图片或特殊格式,可以考虑使用 Imagick。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播