news 2026/9/16 3:44:07

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
imagettftext any2eucjp 报错,这次让 Codex 走 TaoToken 查 GD 的 JIS 开关

PHP 图片脚本里,imagettftext往图上写中文时突然冒出Warning: any2eucjp(): invalid code in input string,验证码、海报、pChart 图表都可能被这一行打断。我这次没有一上来就改 php.ini,而是把排查交给了 Codex:先到 https://taotoken.net/?utm_source=taotoken_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.ini

1.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-conv,GD 就带上了JIS-mapped Japanese Font Support。这个选项本意是让 FreeType 正确渲染日文字体,但实际实现里,imagettftext在处理非 ASCII 字符时,会先把 UTF-8 字符串按日文规则转一遍。中文虽然也是方块字,但它不是日文,编码字节不符合 GD 的预期,转换时就触发any2eucjp(): invalid code in input string

这个问题在 PHP 官方 bug 系统里有记录,地址是 bugs.php.net/bug.php?id=42218,挂了很多年。它和你的业务代码无关,也不是把mb_internal_encoding改成 UTF-8 就能解决的。最麻烦的是,你无法通过 php.ini 直接关闭这个 JIS 开关,因为它是编译期定下来的,运行期没有对应配置项。所以排查方向要放在「确认开关状态」和「绕开转换」这两件事上。

2. 给 Codex 配好 TaoToken:Key 从官网创建,Base URL 填 https://taotoken.net/api

2.1 去官网创建一把 YOUR_API_KEY

在动手查 simhei.ttf 之前,先把 Codex 能用的 API 通道准备好。打开 TaoToken,注册登录后,在控制台创建一把 API Key,拿到的字符串就是后面要填的YOUR_API_KEY。这个平台是统一接入通道,官网主要做三件事:创建 Key、看模型广场、看用量。模型 ID 不靠猜,以 TaoToken 模型广场 当时列表为准。

这里有两类地址要分清:给人点的官网落地页是https://taotoken.net/?utm_source=taotoken_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_KEY=YOUR_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;如果显示disablednot 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-FPM:

systemctl 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 创建。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 3:43:25

ACL访问控制列表从原理到实操:配置方法与排障指南

到今天为止&#xff0c;我的网络学习日志已经写到第26篇了。前面几篇一直在折腾路由协议、接口调试和基础排障&#xff0c;这篇终于轮到 ACL。ACL 全称 Access Control List&#xff0c;翻译过来就是访问控制列表&#xff0c;网工圈子里基本都直接叫“ACL”。它不是某个厂商的私…

作者头像 李华
网站建设 2026/9/16 3:43:12

RDD2022数据集格式转换与清洗全流程实战:VOC转YOLO指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 3:42:56

ENSP企业网规划实战:从顶层设计到VLAN/NAT配置全流程解析

选这个题目的人&#xff0c;第一眼都是被“毕设好做”“ENSP免费”“公司网络规划有套路”吸引过来的。但真打开软件&#xff0c;从拖出第一台AR路由器到全网互Ping通&#xff0c;中间隔着的不只是几条命令&#xff0c;而是一整套规划习惯。这篇文章就按我实际做“尤尼克斯公司…

作者头像 李华
网站建设 2026/9/16 3:42:38

鸿蒙开发实战:用DevEco CLI从零构建宝贝日程表到上架全流程

1. 立项背景与需求拆解1.1 为什么做“宝贝日程表”而不是其它 App做鸿蒙开发这行&#xff0c;最常被问的一句话就是“能不能用个小项目带我入门&#xff1f;”市面上的教程项目&#xff0c;要么是待办清单&#xff0c;要么是记事本&#xff0c;看完确实能学会 ArkTS 语法&#…

作者头像 李华
网站建设 2026/9/16 3:40:17

力扣101:对称二叉树的递归与迭代解法详解

不用引入太多背景&#xff0c;直接说结论&#xff1a;力扣第101题“对称二叉树”是一道非常典型的二叉树递归/迭代练习题&#xff0c;也是面试里出现频率很高的基础题。很多人在刚接触二叉树时&#xff0c;被遍历、深度、翻转这些概念绕晕&#xff0c;等做到“对称”这道题时又…

作者头像 李华
网站建设 2026/9/16 3:37:46

UVa 11509 Touring Robot:圆缩点与BFS网格搜索的几何避障解法

在做算法竞赛题目的时候&#xff0c;我最大的感受是&#xff1a;很多所谓“难”的题&#xff0c;其实不是代码量大&#xff0c;也不是某个算法特别复杂&#xff0c;而是题目本身披了一层“故事外衣”&#xff0c;你得把那层外衣剥掉之后&#xff0c;才能看到里面真正要求的东西…

作者头像 李华