如何使用 PHP 和 GD 解决字体花饰问题

2023-12-30

我有以下代码可以在图像上打印文本。我还在文本周围添加了一个调试框。然而,我注意到左侧的文本位于 PHP 给我的框之外imagettfbbox.

这看起来像是字体花饰的问题。有什么办法可以解释这一点吗?我能算出斜盘起点和实际位置之间的距离吗imagettfbbox给我?

我不认为这是字体的问题,因为我尝试了一些脚本样式的字体,结果是相似的。

<?php

$font       = 'scriptin.ttf';
$text       = 'Ipsum';
$size       = 30;
$image      = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour   = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));

imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);

$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
    $image,
    $dimensions[0] + 40,
    $dimensions[7] + 50,
    $dimensions[2] + 40,
    $dimensions[3] + 50,
    imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);

imagettftext(
    $image,
    $size,
    0,
    40,
    50,
    $fontColour,
    $font,
    $text
);

header('Content-Type: image/png');
imagepng($image);

代码和字体可以在这里找到:https://github.com/AydinHassan/image-swash-example https://github.com/AydinHassan/image-swash-example

如果您将 VHOST 指向存储库,则只需点击swash.php


Edit:这似乎已在 PHP 中修复7.0.12 http://www.php.net/ChangeLog-7.php#7.0.12 (bug #53504 https://bugs.php.net/bug.php?id=53504)所以不需要下面的代码。


基于一个PHP手册中的注释 http://php.net/manual/en/function.imagettfbbox.php#97357我编写了以下函数来计算并返回 GD 认为边界框左侧的位置与找到最左侧像素的位置之间的差异:

function xadjust($size, $angle, $fontfile, $text)
{
    $bbox = imagettfbbox($size, $angle, $fontfile, $text);

    $width = $bbox[4] - $bbox[6]; // upper right x - upper left x;
    $height = $bbox[1] - $bbox[7]; // lower left y - upper left y;

    // create an image with height and width doubled to fit any 'swash'.
    $im = imagecreatetruecolor($width * 2, $height * 2);

    // set background color to opaque black.
    imagefill($im, 0, 0, 0x00000000);

    // draw the text in opaque white.
    imagettftext(
        $im,
        $size,
        0,
        $width / 2,
        $height,
        0x00ffffff,
        $fontfile,
        $text
    );

    // set the min-width to its possible maximum.
    $min_x = $width * 2;

    for ($x = 0; $x < $width * 2; $x++) {
        // each x-pixel (horizontal)
        for ($y = 0; $y < $height * 2; $y++) {
            // each y-pixel (vertical)
            if (imagecolorat($im, $x, $y) > 0) {
                // non-black pixel found!
                $min_x = min($x, $min_x);
            }
        }
    }

    imagedestroy($im);

    // return the difference between where GD thinks the bounding box is and
    // where we found the leftmost non-black pixel.
    return (($width / 2) - $min_x) - abs($bbox[0]);
}

这可以很容易地集成到您的脚本中:

$font       = 'scriptin.ttf';
$text       = 'Ipsum';
$size       = 30;
$image      = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour   = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));

imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);

$xadjust = xadjust($size, 0, $font, $text); // 1. get the adjust value.

$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
    $image,
    $dimensions[0] + 40 - $xadjust, // 2. move the left-side of the box to the left.
    $dimensions[7] + 50,
    $dimensions[2] + 40 - $xadjust, // 3. move the right-side of the box to the left.
    $dimensions[3] + 50,
    imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);

imagettftext(
    $image,
    $size,
    0,
    40,
    50,
    $fontColour,
    $font,
    $text
);

header('Content-Type: image/png');
imagepng($image);

这给了我以下输出:

我用其他一些字体和大小运行过它,它似乎精确到 1 像素以内。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 PHP 和 GD 解决字体花饰问题 的相关文章

  • Azure 上的“phpcomposer.phar install”出现“无法终止进程”错误

    我正在尝试将我的 Symfony 2 应用程序部署到 Microsoft Azure 网站云 为此 我按照本指南中的步骤操作http symfony com doc current cookbook deployment azure web
  • postgreSQL 在 WAMP 上的集成

    我刚刚在 Windows 7 上安装了 postgreSQL 我正在尝试将 postgreSQL 与 WAMP 服务器集成 为此 我在 httpd conf 和 php ini 文件中进行了以下更改 1个加载模块c path to libp
  • 将数组拆分为特定数量的块

    我知道array chunk 允许将数组拆分为多个块 但块的数量根据元素的数量而变化 我需要的是始终将数组拆分为特定数量的数组 例如 4 个数组 以下代码将数组分为 3 个块 两个块各有 2 个元素 1 个块有 1 个元素 我想要的是将数组
  • PHP文件上传

    如果我想在文件名转到服务器的永久位置 而不是临时位置 之前更改文件名 我该如何执行此操作 代码如下
  • php下拉菜单人口

    我正在尝试编写一个 php 脚本 该脚本将根据主下拉菜单的选择填充第二个下拉菜单 我想使用 jquery 来完成所有非页面刷新的事情 但我发现现有的所有东西都很难理解和修改 你知道有什么写得很好且易于理解的东西吗 或者可能是现有的教程 下面
  • mysqli bind_param 中的 NULL 是什么类型?

    我正在尝试将参数绑定到 INSERT INTO MySQLi 准备好的语句 如果该变量存在 否则插入 null 然后我知道 type variable i corresponding variable has type integer d
  • 检查文件权限

    我怎样才能检查file permissions 无需通过运行操作系统特定命令passthru or exec Use 文件权限 http php net fileperms功能 clearstatcache echo substr spri
  • PHP cURL 在本地工作,在 AWS 服务器上出现错误 77

    最新更新 脚本作为管理员用户通过 SSH shell 作为 php script php 成功运行 当由 nginx 用户运行时 curl 命令无法执行 https 请求 所以我猜测这是nginx用户无法正确使用curl的问题 我已经检查了
  • “pdo_mysql”已禁用,我无法启用它。我在 iMac 7.1 OSX 10.6.8 上安装了 MAMP v. 3.0.4

    pdo mysql 已禁用 我无法启用它 我在 iMac 7 1 OSX 10 6 8 上安装了 MAMP v 3 0 4 在我的 phpinfo 页面上 我可以看到唯一启用的 PDO 是 sqlite 如果我查看 php 5 5 10 扩
  • 文件修改时间检查的成本

    对于Linux下包含少量字节的文件 我只需要处理自上次处理以来发生更改的时间 我通过调用 PHP 检查文件是否被更改clearstatcache filemtime 定期 由于整个文件总是很小 因此删除对 filemtime 的调用并通过将
  • PHP - 扩展 __construct

    我想知道你是否可以帮助我 我有两个类 一个扩展了另一个 B 类将由各种不同的对象扩展 并用于常见的数据库交互 现在我希望 B 类能够处理其连接和断开连接 而无需来自 A 类或任何外部输入的指示 据我了解 问题是扩展类不会自动运行其 cons
  • JavaScript 中带前导零的数字发生变化

    我使用 print 语句从 php 调用 javascript 函数来打印 html 代码 并且传入一个整数 但是 在 php 中传递的值与 javascript 函数接收到的数字不匹配 我不知道为什么 这是调用 javascript 函数
  • PHP、jQuery 和 Ajax 调用乱序

    我正在使用 jQuery 进行 Ajax 调用 我有 x 数量的 Ajax 调用附加到 div 这些 Ajax 加载请求是由 PHP foreach 循环生成的 问题是它们渲染的顺序不正确 它们被设置在数组中
  • 重新排列数组键 php [重复]

    这个问题在这里已经有答案了 我有这个数组 Array 15 gt 13 1 16 gt Mark one answer 19 gt You see a car on the hard shoulder of a motorway with
  • 如何在 Twitter Card 中传递动态图像路径?

    我在用
  • 如何解决 Laravel 8 UI 分页问题?

    我在尝试最近发布的 laravel 8 时遇到了问题 我试图找出变化是什么以及它是如何工作的 当我这样做时 我遇到了分页 laravel 8 UI 变得混乱的问题 不知何故它发生了 有人可以帮助我吗 或者经历过同样的事情 像这样我在 lar
  • PHP:在脚本完成之前获取输出

    我有一个名为 data php 的脚本 如下所示 do some stuff echo result do some other stuff eg database operations 我需要在另一个脚本中使用 data php 的输出
  • 接口中的构造方法

    接口中的构造方法不好吗 为什么人们认为有人想要实例化接口 我们想要做的是强制实现者实现构造函数 就像其他接口方法一样 接口就像一个合同 假设我有一个接口 Queue 并且我想确保实现者创建一个带有一个参数的构造函数 该构造函数创建一个单例队
  • 显式删除会话cookie会产生什么影响?

    我使用 php session 来维护用户的会话 Session 在登录后创建 在注销或超时后销毁 我需要管理面板中的一个选项来强制注销任何用户 如果他在网站上处于活动状态 我怎样才能做到这一点 我正在考虑删除临时会话文件 这应该有效地破坏
  • 如何在 Carbon Laravel 中添加日期和另一个日期?

    在我的 laravel 项目中 我想将日期时间增加到前一个日期时间 这是我的代码 expire order 0 gt expire date new Carbon now gt addMonths 6 这两行的结果是 2018 01 28

随机推荐

  • Google Play 游戏功能徽章在 Google Play 上不可见

    我成功地将 Google Play 服务集成到我的 Android 应用程序中 并添加了成就和排行榜 但发布已经几天了 但我在 Google Play 上看不到它的徽章 我需要向 AndroidManifest xml 添加什么内容吗 这些
  • Java util zip 创建“损坏”的 zip 文件

    我正在压缩目录的内容 但在尝试打开压缩文件时遇到错误 谁能告诉我的代码发生了什么 也许我没有分配足够的字节 查看 zipDirectory 内部 您会看到我正在压缩包含特殊扩展文件的文件夹 不确定错误发生在哪里 所以也许有人可以帮助我 非常
  • 使用 MongoDB 进行 Elastic Beanstalk 部署

    非常感谢有关如何通过以下堆栈正确部署 Elastic Beanstalk 的资源建议 MongoDB 导轨 美洲狮 Sidekiq Redis 弹性搜索 我需要在 ebextension 文件中设置所有这些内容吗 或者是在 AWS 中手动设
  • 给定音频流,查找门何时关上(声压级计算?)

    与拍手探测器没什么不同 拍手 拍手鼓掌拍手吧 拍手鼓掌拍手 拍手 拍板 拍手鼓掌 我需要检测门何时关闭 这是在车辆中 这比房间或家庭门更容易 Listen http ubasics com so van driver door openin
  • 这不是尾递归风格的代码吗?

    我对 Scala 有点陌生 在阅读 David Pollack 的 Begining Scala 时尝试了它 他定义了一个简单的递归函数 从文件中加载所有字符串 def allStrings expr gt String List Stri
  • Android Volley,JsonObjectRequest 但接收 JsonArray

    所以我正在使用JsonObjectRequest发送一个JsonObject到休息电话 但它返回JsonArray而不是一个JsonObject 它给了我一个错误 说它无法解析来自JsonObjectRequest 但如果我使用JsonAr
  • Go指针第一次赋值

    当我在玩弄闭包时 我偶然发现了这种行为 我无法理解它 此代码片段的工作原理 func main var a string foo var b string var c string bar b c fmt Printf s s n a b
  • 比较数组不打印差异

    这是我的测试代码 a array Peter gt 35 Ben gt 37 Joe gt 21 b array Peter gt 35 Ben gt 21 Joe gt 43 function leo array diff a b map
  • DWT Java 脚本库进度对话框自动与 Angular 5 显示

    我将 Dynamic Web Twain javascript 库合并到我的 Angular 应用程序中 以允许我的最终用户使用 Web 浏览器而不是桌面应用程序进行扫描 加载页面后 立即弹出进度条 这不是预期的行为 当我使用 Angula
  • IE 9+ 下载属性解决方法

    我正在尝试从我的网络服务下载文件 我需要将复杂的元数据传递到服务器才能知道如何下载文件 以下是我如何在常青浏览器中实现这一目标 i use angular but not important for this demo http post
  • 再次仔细检查锁定和 C#

    最近 我一直在重构一些 C 代码 我发现发生了一些双重检查锁定实践 我当时并不知道这是一种不好的做法 我真的很想摆脱它 问题是我有一个类应该延迟初始化并被大量线程频繁访问 我也不想将初始化移至静态初始化程序 因为我计划使用弱引用来防止初始化
  • 使用 ITextSharp 将 HTML 文件转换为 PDF 文件

    我想完成以下任务 给定 html 文件的路径名和所需的 pdf 文件的路径名 使用 ITextSharp 将 HTML 文件转换为 PDF 我见过很多代码示例 它们的功能与此接近 但不完全是我需要的 我相信我的解决方案需要使用 iTextS
  • 使用 api v2 创建 Facebook 事件

    可以使用 Facebook API 创建事件吗 API v1 中可以实现 https developers facebook com docs graph api reference v1 0 event publish https dev
  • 需要在ARCORE中播放视频

    正如我们在 ARCore 中所知 我们可以通过单击水平面来检测 3D 对象 而不是 3d 对象 当用户要单击平面时 我需要显示视频 外观和感觉应该与显示的 3D 对象相同 视频应以预览模式显示 而不是 3D 对象 在 ARcore 中 他们
  • OpenGL 中的纹理贴图

    我在使 mipmap 正常工作时遇到了很多麻烦 我使用的是 OpenGL 1 1 并且没有 glu 因此我使用以下纹理启动代码 glGenTextures 1 texname glBindTexture GL TEXTURE 2D texn
  • 错误:无法找到 conda 二进制文件。 Anaconda安装了吗?网状Rstudio [重复]

    这个问题在这里已经有答案了 我通过 Rstudio 安装了 reticulate 现在我想用conda create 但我将 anaconda 安装在另一个目录中 然后是默认目录 如何更改 Rstudio 搜索 anaconda 的目录 E
  • 动态计算字段中的字符数

    我想动态计算表单文本区域字段中的字符 我知道有一个类似的问题 但我想知道它是否可以从某个数字向 0 计数 例如在 Twitter 上写推文时 这段代码可以是 javascript PHP 这对我来说并不重要 这应该可以帮助你 这里有一个tu
  • 如何让discord.py 机器人向非作者的人发送私人/直接消息?

    假设我想制作一个具有 poke 功能的机器人 又名当有人说 poke user 0000 时向用户发送一条说 Boop 的消息 我该怎么做 当我这样做时它工作得很好 bot command pass context True async d
  • 无法读取用户的字符[重复]

    这个问题在这里已经有答案了 在这段代码中 我正在创建一个二叉树 直到用户想要节点数 但是在从用户获取输入时 它在某个地方失败了 struct node createTree struct node root int n char ch st
  • 如何使用 PHP 和 GD 解决字体花饰问题

    我有以下代码可以在图像上打印文本 我还在文本周围添加了一个调试框 然而 我注意到左侧的文本位于 PHP 给我的框之外imagettfbbox 这看起来像是字体花饰的问题 有什么办法可以解释这一点吗 我能算出斜盘起点和实际位置之间的距离吗im