ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

imagettftext any2eucjp 报错,这次让 Codex 走 TaoToken 查 GD 的 JIS 开关

imagettftext any2eucjp 报错,这次让 Codex 走 TaoToken 查 GD 的 JIS 开关 PHP 图片脚本里imagettftext往图上写中文时突然冒出Warning: any2eucjp(): invalid code in input string验证码、海报、pChart 图表都可能被这一行打断。我这次没有一上来就改 php.ini而是把排查交给了 Codex先到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建一把 Key再把 Base URL 填成https://taotoken.net/api让 Codex 按老步骤检查 simhei.ttf 路径、确认 GD 的 JIS-mapped Japanese Font Support 是否 enabled。整个过程里Codex 的模型请求走 TaoToken 下发PHP 侧只做本地执行最终用mb_convert_encoding转码把中文正常画回图片上报错也不再打断生成流程。排查的关键不是猜编码而是按顺序确认字体文件与 GD 编译选项这两点确认完修复方案基本就出来了。1. 先复现 imagettftext 的 any2eucjp 报错别急着改 php.ini1.1 中文文字没画上去先多了一行 Warning下面这段脚本是图片上写中文最常见的写法?php $pic imagecreatetruecolor(250, 30); $black imagecolorallocate($pic, 0, 0, 0); $white imagecolorallocate($pic, 255, 255, 255); $font C:/Windows/Fonts/simhei.ttf; $str 中华人民共和国; imagettftext($pic, 10, 0, 10, 20, $white, $font, $str); header(Content-type: image/png); imagepng($pic, output.png); imagedestroy($pic);在大多数 PHP 环境里这段代码能把汉字画出来。但如果你拿到的是别人编译的 PHP 包或者当初编译时为了支持日文字体多开了一个参数浏览器访问时不一定看得到报错反而在命令行执行时先出现一行Warning: imagettftext(): any2eucjp(): invalid code in input string in C:\xampp\htdocs\make_pic.php on line 9注意这个 Warning 是从imagettftext内部冒出来的不是mb_convert_encoding这类函数报的。它说明字符串已经进了 GD 的字体渲染流程GD 在内部尝试做一次 EUC-JP 转换但输入字符串里出现了它认为非法的字节。于是图片上「中华人民共和国」没有正常画出来生成流程直接被打断。1.2 根因是编译 PHP 时的 --enable-gd-jis-conv不是你的业务代码编译 PHP 时如果加了--enable-gd-jis-convGD 就带上了JIS-mapped Japanese Font Support。这个选项本意是让 FreeType 正确渲染日文字体但实际实现里imagettftext在处理非 ASCII 字符时会先把 UTF-8 字符串按日文规则转一遍。中文虽然也是方块字但它不是日文编码字节不符合 GD 的预期转换时就触发any2eucjp(): invalid code in input string。这个问题在 PHP 官方 bug 系统里有记录地址是 bugs.php.net/bug.php?id42218挂了很多年。它和你的业务代码无关也不是把mb_internal_encoding改成 UTF-8 就能解决的。最麻烦的是你无法通过 php.ini 直接关闭这个 JIS 开关因为它是编译期定下来的运行期没有对应配置项。所以排查方向要放在「确认开关状态」和「绕开转换」这两件事上。2. 给 Codex 配好 TaoTokenKey 从官网创建Base URL 填 https://taotoken.net/api2.1 去官网创建一把 YOUR_API_KEY在动手查 simhei.ttf 之前先把 Codex 能用的 API 通道准备好。打开 TaoToken注册登录后在控制台创建一把 API Key拿到的字符串就是后面要填的YOUR_API_KEY。这个平台是统一接入通道官网主要做三件事创建 Key、看模型广场、看用量。模型 ID 不靠猜以 TaoToken 模型广场 当时列表为准。这里有两类地址要分清给人点的官网落地页是https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end给 Codex 填的接口 Base URL 是https://taotoken.net/api末尾不用加/v1。前者在浏览器里打开后者出现在配置文件里。2.2 在 ~/.codex/config.toml 里注册 TaoToken 模型提供方Codex 使用~/.codex/config.toml来声明模型提供方。如果这个文件不存在手动创建。配置如下model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY保存后在终端里把 Key 写进环境变量export TAOTOKEN_API_KEYYOUR_API_KEY然后启动 Codex先不要急着让它写代码发一句「请确认你已经就绪并列出你将要执行的排查步骤」。如果它正常返回了说明 TaoToken 通道已经通如果返回 401回控制台检查 Key 是不是复制多了空格。2.3 为什么不直接改 php.ini如果目标只是让这张图片不报错确实可以直接去服务器上找 PHP 安装包重新编译或者换一台没开 JIS 的机器。但很多项目不止一个环境开发机、测试机、客户服务器各一套有些是 Docker 镜像重编译成本很高。让 Codex 先把问题定位清楚再决定用转码还是重编译才是改动最小的一条路。3. 按原文排查顺序让 Codex 走一遍字体路径 → GD JIS 开关原文的排查顺序很明确先确认 simhei.ttf 路径再检查 GD 的 JIS 开关最后才决定转码还是重编译。按这个顺序走不会把问题误判成字体缺失。3.1 第一步确认 simhei.ttf 存在且路径可读在本地终端执行fc-list | grep -i simhei如果输出里包含/usr/share/fonts/truetype/simhei.ttf这类路径说明字体存在。如果没有任何输出说明服务器上根本没有 simhei.ttf需要换用其它中文字体比如 simsun.ttc 或 wqy-zenhei.ttc并同步修改 PHP 里的$font变量。把这条命令的输出贴回 Codex 对话它会判断当前路径能否被 FreeType 正常加载。如果你写的是 Windows 路径C:/Windows/Fonts/simhei.ttf而实际上代码跑在 Linux 容器里Codex 会提示你路径写错了。注意这里不需要让 Codex 登录服务器执行任何命令只需要你在本地把结果贴回去由它来分析。3.2 第二步检查 GD 的 JIS-mapped Japanese Font Support用一条命令查看 JIS 开关php -i | grep -i jis更直观的方式是打印 GD 信息?php $info gd_info(); echo JIS-mapped Japanese Font Support: . ($info[JIS-mapped Japanese Font Support] ?? not available) . PHP_EOL;把执行结果贴给 Codex。如果显示enabled就坐实了编译参数里带着--enable-gd-jis-conv如果显示disabled或not available那 any2eucjp 报错就不一定是这个原因需要先用mb_check_encoding($str, UTF-8)检查输入字符串本身是否非法。4. 落地修复mb_convert_encoding 转码优先重编译兜底排查完成后Codex 通常会给出两条修复路径。先用转码方案成本最低重编译 PHP 是根治但要动编译参数风险也大。4.1 把 UTF-8 中文转成 HTML 实体再给 imagettftext核心修复是把汉字转成 HTML 实体形式$str mb_convert_encoding($str, html-entities, UTF-8);这行代码会把「中华人民共和国」变成类似#21738;#19968;#20154;#27665;#20849;#21644;#22269;的数字实体。GD 渲染时看到的是纯 ASCII 数字不再把它当日文处理画到图片上仍然是中文。完整的可运行版本?php // make_pic.php $pic imagecreatetruecolor(250, 30); $black imagecolorallocate($pic, 0, 0, 0); $white imagecolorallocate($pic, 255, 255, 255); $font /usr/share/fonts/truetype/simhei.ttf; $str 中华人民共和国; $str mb_convert_encoding($str, html-entities, UTF-8); imagettftext($pic, 10, 0, 10, 20, $white, $font, $str); header(Content-type: image/png); imagepng($pic, output.png); imagedestroy($pic);注意mb_convert_encoding的输入必须是合法 UTF-8。如果字符串本来是从 GBK 文件里读进来的先转成 UTF-8 再做 HTML 实体转换$str mb_convert_encoding($str, UTF-8, GBK); $str mb_convert_encoding($str, html-entities, UTF-8);4.2 去掉 --enable-gd-jis-conv 编译选项如果项目里几十处 imagettftext 都不方便改再考虑重编译 PHP。先把当前编译参数保存下来php -i | grep configure在输出的 configure 命令里找到--enable-gd-jis-conv并去掉然后重新编译make clean make make install编译完成后重启 PHP-FPMsystemctl restart php-fpm再次运行php -i | grep -i jis确认JIS-mapped Japanese Font Support不再是 enabled。如果这台机器的 PHP 是 apt 或 yum 装的没有源码目录就别走这条路径优先用转码方案。5. pChart 图表里的中文标签也按同一套转码处理原文后半部分用 pChart 画饼图时图例里的中文同样会触发这个报错。pChart 底层画文字时一样调用 imagettftext所以只要 JIS 开关是 enabled中文标签就躲不过。5.1 AddPoint 之前先递归转码数组pChart 的标签通常是一个数组$months array(Jan, 二月, 三月, Apr, May);不能直接把数组塞给 AddPoint要先逐个转成 HTML 实体。写一个递归函数可以用在多个图表上function utf8ToHtmlEntity($value) { if (is_array($value)) { return array_map(utf8ToHtmlEntity, $value); } return mb_convert_encoding($value, html-entities, UTF-8); } $months utf8ToHtmlEntity(array(Jan, 二月, 三月, Apr, May)); $DataSet-AddPoint($months, Serie2);递归版本的好处是数组里不一定全是字符串也可能嵌套分组一层 foreach 不一定覆盖全递归能保证每个元素都处理到。5.2 给项目准备一个公共的文本转换函数如果项目里有多处 pChart 或 imagettftext 调用可以把转码函数放进公共文件所有入图的文字统一走它function textForGd($str) { return mb_convert_encoding((string) $str, html-entities, UTF-8); }然后调用处统一使用imagettftext($pic, 10, 0, 10, 20, $white, $font, textForGd($str));这样即使以后把代码迁到一台开了 JIS 的机器上也不会因为漏掉某个调用而再次报错。6. 验证图片、清掉报错再回控制台对一下调用消耗6.1 本地跑一遍 PHP 脚本输出图片和 CLI 日志修复后至少要验证两个点中文渲染正确Warning 消失。在终端执行php make_pic.php脚本里已经用imagepng($pic, output.png)保存了图片打开 output.png 看到「中华人民共和国」六个字正常出现同时命令行里没有任何 any2eucjp 输出说明转码生效了。如果还有报错大概率是还有某个 imagettftext 调用没用textForGd按报错行号找过去改掉就行。6.2 回 TaoToken 控制台看这次 Codex 对话的用量Codex 排查过程中你对它发的每条消息、它生成的每段排查步骤都是经由刚才配置的 Base URL 走 TaoToken 发到模型的。回到 TaoToken 控制台打开用量页面能看到这次对话的 token 消耗和请求记录。这能同时验证两件事Key 有效且请求确实走到了 TaoToken而不是还在用本机默认配置。6.3 转码后常见的三个坑报错变成Could not find/open font字体路径不对回 3.1 节用 fc-list 确认。转码后文字变方块字体文件本身不支持中文比如用 arial.ttf 画中文就会出现方块换成 simhei.ttf 或 wqy-zenhei.ttc。图片能显示但 pChart 图例里还是英文utf8ToHtmlEntity只处理了你传入的数组如果 pChart 内部拼接了中文常量需要把这些常量也统一走textForGd。验证通过之后如果接下来要用同一把 Key 做更多模型测试可以在 TaoToken 模型对话 里先发一条消息确认模型切换、上下文长度都没问题日常写代码排查如果量比较大可以打开 Coding Plan 看套餐是否够用需要新建一把专门给 Codex 用的 Key直接去 控制台 API Keys 创建。
返回列表