GD库使用字体路径问题

一个小小的问题,用GD生成小图片,正常的写完程序之后提示是两个warning:Could not find/open font。分别是imagettfbbox()和imagettftext()函数找不到所使用的字体,看了一下刚好我的Linux确实安装该字体,于是想起拷贝到XP实验机上试试,迅速的配置好了XP上的PHP和Apache,正想着问题迎刃而解的时候出来了更多的问题,反而头一下晕了。折腾一番后找到问题所在,原来这两个函数中使用的font文件路径比较怪异,即使在同一目录下也需要写完整,例如$font = "./Arial.ttf"。比较合适的解决办法是设置GD环境,使用putenv('GDFONTPATH=' . realpath('.');以上是假设.ttf文件在同一目录下,如果有专门的font文件夹,后面换成realpath('./font/')。这样的话在下面就可以直接给$font赋值为$font = 'Arial';后面再调用$font时就不会出错了。

总结来讲,在一个问题没解决的情况下去重新配个环境来试这个问题导致多个问题重叠,把自己搞晕了,例如WIN下装了PHP没开启GD扩展之类的小问题

另外后来发现WIN常用的字体有部分也可以在Linux下使用,相应的我的UBUNTU是有相应安装包的
sudo apt-get install msttcorefonts
其他的套件就自己寻找下了,其中已经包含很多WIN下的常用字体了,包括
Andale Mono, Arial, Comic Sans MS, Courier New,GeorgiaImpact, Times New Roman, Trebuchet MS,Verdana, Webdings
<think>我们使用GD内置字体(而不是TrueType字体)来添加文本水印。GD内置字体是1到5的整数,分别代表不同大小的字体。这些字体是固定大小的,不支持自定义大小,但处理速度快,不需要外部字体文件。 内置字体使用函数: - 获取文本宽度的函数:`imagefontwidth($font)` - 获取文本高度的函数:`imagefontheight($font)` - 写入文本的函数:`imagestring($image, $font, $x, $y, $string, $color)` 由于内置字体不支持自定义大小,所以我们需要根据所选字体号计算水印文本的宽度和高度。 我们仍然支持8个位置:top-left, top-center, top-right, middle-left, center, middle-right, bottom-left, bottom-center, bottom-right。 实现步骤: 1. 加载原始图片(支持JPEG和PNG)。 2. 根据选定的内置字体号(1-5)计算水印文本的宽度和高度。 3. 根据指定的位置计算水印的坐标(考虑边距)。 4. 使用`imagestring`函数将水印文本绘制到图片上。 5. 保存图片。 注意:内置字体不支持透明度,但我们可以通过调整文本颜色来模拟半透明效果(例如使用浅灰色)。但是,`imagestring`函数不支持透明度,所以如果需要半透明效果,我们可以使用其他方法(例如先创建一个带透明度的颜色,然后使用`imagestring`绘制,但内置字体绘制函数不支持透明度)。因此,我们这里不处理透明度,如果用户需要透明度,建议使用TrueType字体。 但是,根据要求,我们使用内置字体,所以只提供不透明的水印。用户可以通过设置颜色为浅色(如浅灰色)来降低水印的突兀感。 代码实现: 我们将创建一个函数,参数包括: - $sourcePath: 源图片路径 - $outputPath: 输出图片路径 - $watermarkText: 水印文本 - $position: 位置,默认为'center' - $font: 内置字体号(1-5),默认为5(较大字体) - $color: 文本颜色,数组形式[R,G,B],默认为[255,255,255](白色) 由于内置字体不支持改变大小,所以没有字体大小参数。 完整代码: ```php <?php /** * 使用GD内置字体为图片添加文本水印 * @param string $sourcePath 原始图片路径 * @param string $outputPath 输出图片路径 * @param string $watermarkText 水印文本 * @param string $position 水印位置(默认'center') * @param int $font 内置字体号(1-5,默认5) * @param array $color 文本颜色,如[255,255,255]表示白色 * @return bool 成功返回true,失败返回false */ function addWatermarkWithBuiltInFont($sourcePath, $outputPath, $watermarkText, $position = 'center', $font = 5, $color = [255, 255, 255]) { try { // 验证字体号 if ($font < 1 || $font > 5) { throw new Exception("字体号必须在1到5之间"); } // 步骤1: 加载原始图片 $sourceInfo = getimagesize($sourcePath); if (!$sourceInfo) { throw new Exception("无法加载原始图片: $sourcePath"); } $mimeType = $sourceInfo['mime']; switch ($mimeType) { case 'image/jpeg': $sourceImage = imagecreatefromjpeg($sourcePath); break; case 'image/png': $sourceImage = imagecreatefrompng($sourcePath); break; default: throw new Exception("不支持的图片格式: $mimeType"); } $sourceWidth = imagesx($sourceImage); $sourceHeight = imagesy($sourceImage); // 步骤2: 计算水印文本尺寸 $textWidth = imagefontwidth($font) * strlen($watermarkText); $textHeight = imagefontheight($font); // 步骤3: 计算水印位置(8个位置,加上边距10像素) $positions = [ 'top-left' => ['x' => 10, 'y' => 10], 'top-center' => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => 10], 'top-right' => ['x' => $sourceWidth - $textWidth - 10, 'y' => 10], 'middle-left' => ['x' => 10, 'y' => ($sourceHeight - $textHeight) / 2], 'center' => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => ($sourceHeight - $textHeight) / 2], 'middle-right' => ['x' => $sourceWidth - $textWidth - 10, 'y' => ($sourceHeight - $textHeight) / 2], 'bottom-left' => ['x' => 10, 'y' => $sourceHeight - $textHeight - 10], 'bottom-center' => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => $sourceHeight - $textHeight - 10], 'bottom-right' => ['x' => $sourceWidth - $textWidth - 10, 'y' => $sourceHeight - $textHeight - 10] ]; if (!isset($positions[$position])) { throw new Exception("无效的水印位置: $position。支持: " . implode(', ', array_keys($positions))); } $pos = $positions[$position]; $x = max(0, $pos['x']); // 确保坐标不超出边界 $y = max(0, $pos['y']); // 步骤4: 创建颜色 $textColor = imagecolorallocate($sourceImage, $color[0], $color[1], $color[2]); // 添加水印文本 imagestring($sourceImage, $font, $x, $y, $watermarkText, $textColor); // 步骤5: 输出图片 switch ($mimeType) { case 'image/jpeg': imagejpeg($sourceImage, $outputPath, 100); // 100%质量 break; case 'image/png': imagepng($sourceImage, $outputPath, 9); // 压缩级别9 break; } // 释放资源 imagedestroy($sourceImage); return true; } catch (Exception $e) { error_log("水印添加失败: " . $e->getMessage()); return false; } } // 示例用法 // 添加文本水印到图片,位置为右下角,使用内置字体5,白色 $result = addWatermarkWithBuiltInFont( 'path/to/source.jpg', 'path/to/output.jpg', 'Copyright', 'bottom-right', 5, [255, 255, 255] // 白色 ); if ($result) { echo "水印添加成功!"; } else { echo "水印添加失败,请检查错误日志。"; } ?> ``` ### 说明: 1. 内置字体:我们使用`imagefontwidth`和`imagefontheight`来计算文本的宽度和高度。注意,内置字体是等宽字体,所以每个字符宽度相同。 2. 位置计算:与之前类似,我们预定义了8个位置(加上中心共9个)的坐标计算,并固定边距为10像素。 3. 颜色:通过`imagecolorallocate`创建颜色,这里使用用户传入的RGB数组。 4. 绘制文本:使用`imagestring`函数,该函数将文本绘制到指定位置。 5. 不支持透明度:由于内置字体函数不支持透明度,所以无法设置半透明。但可以通过设置浅色(如灰色)来降低水印的明显程度。 ### 注意事项: - 内置字体大小有限,且不支持中文(因为内置字体是西文字体)。如果需要中文,必须使用TrueType字体。 - 由于内置字体较小,可能不适合大图片,但可以满足简单的水印需求。 这个方案适用于简单的版权声明,且不需要复杂效果的情况。GD内置字体处理速度快,不需要额外加载字体文件,适合简单应用场景[^2]。 §§相关问题§§ 1. GD内置字体有哪些局限性? 2. 如何为GD水印添加阴影效果? 3. 在PHP中,如何读取图片的EXIF数据并添加为水印?[^3] 4. 使用GD处理图片时,如何避免内存不足的问题? [^1]: 随着数字媒体的发展,图片水印已经成为保护图片版权、宣传品牌的一种常见手段。本章节将深入探讨如何使用GDPHP中添加图片水印,包括水印创建过程、参数设置、位置调整以及应用场景分析。 [^2]: GDphp处理图形的扩展GD提供了一系列用来处理图片的API,使用GD可以处理图片,或者生成图片,也可以给图片加水印。最新版的GD支持GIF、JPEG、PNG、WBMP、XBM等格式的图像文件,此外还支持winows下的ttf字体、FreeType等字体显示。通过GD中的函数可以完成各种点、线、几何图形、文本、颜色的操作和处理。 [^3]: 我们有一个文件夹,里面存放着 300 张照片。每张照片都有拍摄时间的元数据(EXIF 数据)。我们要做的是: 读取每张照片的拍摄时间。在照片的右下角合适的位置添加这个拍摄时间作为水印。保存带有水印的新照片到另一个文件夹中。 所需工具 PHP:我们将使用 PHP 编写代码。GD :这是 PHP 内置的一个图像处理,用来操作图片。EXIF 函数:用于读取照片的元数据(如拍摄时间)。 实现步骤 第一步:准备环境 [^4]: php中的gd图像处理,PHP图像处理(GD)。①PHP不仅限于只产生HTML的输出,还可以创建与操作多种不同格式的图像文件。PHP提供了一些内置的图像处理函数,也可以使用GD函数创建新图像或处理已有的图像。目前GD2支持JPEG、PNG和WBMP格式。</think>### PHP GD使用内置字体添加水印(支持8个位置) 以下是使用GD内置字体为图片添加水印的完美解决方案,支持指定8个位置。GD提供了5种内置字体(编号1-5),这些字体是等宽字体,适用于简单的水印场景[^2][^4]。 #### 完整代码实现 ```php <?php /** * 使用GD内置字体添加水印 * @param string $sourcePath 原始图片路径 * @param string $outputPath 输出图片路径 * @param string $watermarkText 水印文本 * @param string $position 水印位置(默认'center') * @param int $font 内置字体编号(1-5,默认5) * @param array $color 文本颜色 [R, G, B](默认白色[255,255,255]) * @param int $margin 边距(像素,默认10) * @return bool 成功返回true,失败返回false */ function addWatermarkWithBuiltInFont( $sourcePath, $outputPath, $watermarkText, $position = 'center', $font = 5, $color = [255, 255, 255], $margin = 10 ) { try { // 验证字体编号 if ($font < 1 || $font > 5) { throw new Exception("字体编号必须在1-5之间"); } // 加载原始图片 $sourceInfo = getimagesize($sourcePath); if (!$sourceInfo) { throw new Exception("无法加载图片: $sourcePath"); } $mimeType = $sourceInfo['mime']; switch ($mimeType) { case 'image/jpeg': $sourceImage = imagecreatefromjpeg($sourcePath); break; case 'image/png': $sourceImage = imagecreatefrompng($sourcePath); // 保留PNG透明度 imagealphablending($sourceImage, true); imagesavealpha($sourceImage, true); break; default: throw new Exception("不支持的格式: $mimeType"); } $sourceWidth = imagesx($sourceImage); $sourceHeight = imagesy($sourceImage); // 计算水印尺寸(内置字体) $charWidth = imagefontwidth($font); $charHeight = imagefontheight($font); $textWidth = $charWidth * strlen($watermarkText); $textHeight = $charHeight; // 计算8个位置坐标 $positions = [ 'top-left' => ['x' => $margin, 'y' => $margin], 'top-center' => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => $margin], 'top-right' => ['x' => $sourceWidth - $textWidth - $margin, 'y' => $margin], 'middle-left' => ['x' => $margin, 'y' => ($sourceHeight - $textHeight) / 2], 'center' => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => ($sourceHeight - $textHeight) / 2], 'middle-right' => ['x' => $sourceWidth - $textWidth - $margin, 'y' => ($sourceHeight - $textHeight) / 2], 'bottom-left' => ['x' => $margin, 'y' => $sourceHeight - $textHeight - $margin], 'bottom-center' => ['x' => ($sourceWidth - $textWidth) / 2, 'y' => $sourceHeight - $textHeight - $margin], 'bottom-right' => ['x' => $sourceWidth - $textWidth - $margin, 'y' => $sourceHeight - $textHeight - $margin] ]; if (!isset($positions[$position])) { throw new Exception("无效位置: $position"); } $pos = $positions[$position]; $x = max(0, $pos['x']); // 确保不超出左边界 $y = max(0, $pos['y']); // 确保不超出上边界 // 创建水印颜色 $textColor = imagecolorallocate($sourceImage, $color[0], $color[1], $color[2]); // 添加水印文本 imagestring($sourceImage, $font, $x, $y, $watermarkText, $textColor); // 保存图片 switch ($mimeType) { case 'image/jpeg': imagejpeg($sourceImage, $outputPath, 100); break; case 'image/png': imagepng($sourceImage, $outputPath, 9); break; } // 释放资源 imagedestroy($sourceImage); return true; } catch (Exception $e) { error_log("水印错误: " . $e->getMessage()); return false; } } // 使用示例 $result = addWatermarkWithBuiltInFont( 'input.jpg', // 原始图片 'output.jpg', // 输出图片 '© WATERMARK', // 水印文本 'bottom-right', // 位置 5, // 字体大小(1-5) [255, 0, 0], // 红色文本 20 // 边距 ); if ($result) { echo "水印添加成功!"; } else { echo "水印添加失败,请查看错误日志"; } ?> ``` #### 关键功能说明 1. **内置字体支持**: - 使用GD内置的5种字体(通过`$font`参数选择) - 字体尺寸关系:$1 < 2 < 3 < 4 < 5$ - 使用`imagefontwidth()`和`imagefontheight()`计算文本尺寸 2. **8个位置支持**: - 左上(top-left)、中上(top-center)、右上(top-right) - 左中(middle-left)、中心(center)、右中(middle-right) - 左下(bottom-left)、中下(bottom-center)、右下(bottom-right) - 位置计算基于图片尺寸和水印文本尺寸:$x = \frac{\text{imgWidth} - \text{textWidth}}{2}$ 3. **自定义选项**: - 文本颜色(RGB数组) - 边距设置(像素) - 支持JPEG和PNG格式 - 保留PNG图片的透明度[^4] 4. **错误处理**: - 验证图片格式和字体编号 - 捕获并记录异常 - 确保水印位置不超出图片边界 #### 使用场景建议 - 内置字体适合简单英文水印(不支持中文) - 字体5(最大号)适合大尺寸图片 - 红色水印在浅色背景上更醒目 - 右下角位置最常用,不影响主要内容[^1] - 边距20像素可确保水印不被裁剪 GD提供的高效图像处理能力使其成为PHP中处理水印任务的理想选择[^2]。虽然内置字体功能有限,但对于简单版权声明已足够实用[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值