我的电子书阅读器如何失去了它的条纹
摘要
一位作者分享了他们使用小型e-ink阅读器的经历,该阅读器在安装开源固件后遇到了显示故障,并使用了Codex中的GPT-6 Astra来诊断和修复问题。
暂无内容
查看缓存全文
缓存时间: 2026/09/14 17:51
# 我的电子阅读器条纹问题始末
来源:https://www.serpentine.com/posts/2026/x3-stripes/
我毕生都是个书虫,但在当下这个充斥着无尽琐碎干扰的时代,这个习惯显得格外脆弱。虽然书籍和电子墨水屏阅读器解决了注意力竞争的问题,但它们的便捷性仍无法与手机相提并论。我口袋里那个小玩意儿,让阅读变得更容易,也更容易在通知弹出时被随时取代。
几天前,我第一次了解到新一代超小型电子墨水屏阅读器。由于价格低廉,好奇心很容易占了上风:我购买了一款 Xteink X3 (https://crosspointreader.com/)。这款设备不仅小得惊人,我还能立刻安装令人愉悦的开源固件 CrossPoint (https://github.com/crosspoint-reader/crosspoint-reader)。很快我就装上了几本书,也很欣赏能安装自定义字体的功能,不过字体渲染效果平平让我略感惊讶(*伏笔……*)。
CrossPoint 开箱即可高度自定义,因此我将一张照片转换成抖动处理的黑白位图作为“设备休眠”屏幕,并对其呈现效果相当满意。当得知设备支持整整四种灰度级时,我产生了兴趣:灰度图像的效果会更好吗?
## 深入探究:首次发现图像缺陷
这暴露出一个疑似漏洞:休眠屏幕显示灰度图像时,暗部区域显得异常浑浊。若非我的中年视力终于衰退,那便是深灰色被渲染成了黑色?我快速制作测试图验证了深灰色确实被显示为黑色,而浅灰色则显得极其苍白(近乎白色)。这虽然有点烦人,但对一款廉价设备来说不足为奇,且容易通过变通方案解决:那就制作一张三色图!
当生成图像中黑色区域减少后,我又发现了一个新问题:在 CrossPoint 查看器应用中,先前屏幕内容仍以鬼影形式残留(仅出现在显示屏较浅区域,因此我之前才没注意到)。然而同一张图像在休眠屏幕显示时却没有此问题。这暗示着存在两个采用不同决策的图像渲染器,而查看器应用的代码存在缺陷。
但无论哪种情况,照片上都出现了文件位图中没有的独特垂直条纹。
[我的三色图像手机拍摄图。细微的垂直条纹在背景处最易观察。]
由于我对电子墨水屏、ESP32开发或 CrossPoint几乎一无所知,我以2026年末特有的方式展开调查——使用 Codex 中的 GPT-6 Astra。我通过手机拍摄 X3 屏幕截图,并将图像拖入 Codex 会话。
电子墨水屏利用电压脉冲移动黑白颜料颗粒,断电后颗粒保持原位。不完整更新或电压不足会留下先前图像的鬼影。
为显示灰度图像,CrossPoint 首先绘制黑白底图(其中灰色像素初始均为黑色),然后施加短电压脉冲波形,将选定像素*部分*推向白色。这第二阶段的“推动”通过不同时长驱动像素,产生明暗不同的灰色调。
Astra 发现查看器执行了快速黑白更新后便停止,从未进行灰阶推动操作。它迅速修复了该问题。
条纹问题则顽固得多。Astra 最初偏离方向,归咎于它为休眠图使用的 Floyd–Steinberg 抖动算法。更换算法后问题依旧。随后它沿技术栈向下追踪,将推动波形标记为值得研究的环节。
但我们难以就所观察或测量的伪影达成共识,这让我担忧——毕竟不想浪费顶级模型资源追逐幻影。当我追问时,Astra 确认检测到两像素宽的条纹模式。这不合常理,于是我要求它标注照片,发现它识别的是细微抖动纹理而非我所见的图像条带。
[Astra 通过快速傅里叶变换(FFT)检测的结果] 此处运用 FFT 相当巧妙:它几乎是识别量化重复模式的理想工具。Astra 对照片小块区域和源图像进行二维FFT分析,在两者中都发现约两屏幕像素处存在强周期信号。
可惜误差扩散抖动本身会产生结构——通常是高频噪声,在FFT中形成强信号。Astra 识别出的正是 Floyd–Steinberg 算法产生的细微点状图案(即它早期选择的图像处理算法)。而我抱怨的较宽条带仅出现在阅读器上。当我质疑其估计时,它做出标注,证实我们关注的是不同模式。
[Astra 标注的图像,放大区域及亮度曲线显示约二十个屏幕像素内包含十个细微抖动周期]
## 量化条纹
受 Astra 无效假设困扰,我转向 Claude Code 中的 Fable 5.1 寻求新视角。
我直觉认为条纹宽度具有特定意义,但即使*识别*条纹本身都让 Astra 无从下手。这确实不易,因多重干扰源混杂其中:
- 图像自身的抖动图案(曾误导Astra)
- 产生条纹的未知因素
- X3 屏幕自身物理特性
- 手机拍摄此场景的干扰:传感器噪声、景深变化、镜头畸变(需微距拍摄259ppi屏幕)、光线曝光差异、处理痕迹、手持抖动导致的运动模糊
在警示下避开 Astra 的图像处理死胡同后,Fable 编写了逐列亮度平均的代码。对于下方视图,它使用200行高滑动窗口:每个点成为其附近短垂直条带的平均值。这平滑了抖动纹理,而沿列持续的亮度差异得以保留。图像的整体形状依然可见,但条纹变得更易辨识:
[应用滑动垂直平均后的裁剪图。宽幅形状属于照片本身;细垂直带即为缺陷]
Fable 接着对一维亮度分布进行FFT分析,测量垂直模式的间距和强度。其初步估计显示条纹间距约七屏幕像素,但这基于对照片比例的猜测。
它重新关注固件中的抖动处理,提出累积舍入误差可能对齐形成垂直条纹。当我指出源图像已预处理为抖动图时,它变得兴奋,但这最终是20分钟的徒劳探索。另一次调查中,Fable 围绕图像位深度展开分析,同样无果。至少它比Astra更有创新性?
## 灰度的特殊之处
我也在设备上测试了更简单的图像。移除*灰色*或*图案*中任一要素,条纹即消失:
| 图像类型 | 含灰色像素 | 相邻像素状态不同 | 条纹现象 |
|----------------|------------|------------------|----------|
| 纯灰场 | 是 | 否 | 无 |
| 黑白抖动图 | 否 | 是 | 无 |
| 灰色抖动图 | 是 | 是 | 是 |
灰色像素与不同色调的邻居特定组合是问题根源。Fable 将源图像小块与手机照片匹配,终于发现浅灰像素承载着条纹——这个重要细节因浅灰色调极淡连我都未清晰辨识。
证据指向屏幕通过灰度推动产生灰色的方式。相关代码位于 CrossPoint 使用的硬件库 freeink-sdk (https://github.com/Free-Ink/freeink-sdk) 中。
Fable 最初不愿深入:“我无法在此设计或验证查找表(LUT)更改。”LUT是存储推动波形的查找表。当我指出X3就在桌上且可拍摄新构建的任何显示内容时,它提出了可执行的实验方案。
X3 的磁性接触充电器在此发挥作用。Fable 可在设备通电时通过USB刷写固件并重启,而我无需插拔USB-C接头即可拿起设备拍照后放回。
## 测试图案与第二个漏洞
现有推动波形持续七个扫描周期:每次控制器遍历面板各行,为每个像素施加电压序列的下一阶段。我们当时认为条纹间距约七像素,是否时序以空间图案形式显现?改变波形持续时间可提供比较基准。
首先需要更易测量的图像,我建议 Fable 生成测试图案。它制作了包含四种纯色色块、灰色与黑白混合、棋盘格及双向线条的图案。
[测试图案。纯色块确立四种灰度;图案区域测试灰色与其他色调的相邻效果。棋盘格位于第三行右侧]
测试图像使进程显著加快。Fable 知道图像*应有*的呈现效果,因此能识别并计入我的照片与屏幕显示间的差异。例如,Fable 的原始比例估计曾将照片频谱特征误判为屏幕像素网格。以测试图案为标尺,条纹周期实为八像素而非七像素。
我同时提供手机原始DNG文件与处理后的照片。对比显示手机处理使条纹振幅增大约70%,并偏移了灰度层次。之后我们采用原始文件。Fable 克服了构图、透视和镜头畸变变化,找到测试色块的定位方法,从而能以统一标准测量每次构建和照片。
我们将推动波形从七帧延长至十帧,又测试了驱动脉冲与间歇交替的版本,均未影响条纹。这排除了帧数与条纹周期相关的假设。
## 从三色到四色灰度
测试图案还重现了我们先前变通解决的问题。
[原始波形下的测试图案。顶行前两个色块应为黑色和深灰色,但两者皆为黑色。第三行左侧的深灰色-黑色色块也消失不见]
我们原本以为具备四灰度显示的设备*实际*只显示三色——这并非我视力老化所致。深灰色即为黑色。幸运的是我正观察Fable的推理过程时它发现了这点,因为它仅以顺便提及的方式报告。理解该发现的重要性后,我立即介入让它深入追踪。
Fable 追溯到 CrossPoint 与驱动层关于请求深灰色的分歧。CrossPoint 为推动阶段每像素使用两位编码,选择四种波形表之一。其深灰色代码选择了无效表,而真正的深灰色驱动存于*另一*表中。Fable 修复了错误并向 freeink-sdk 提交PR。
修复后深灰色得以呈现,原本应为深灰色抖动的黑色色块变成可见斑点而非纯黑方块。但浅灰色驱动未变,条纹依然存在。我们在构建首个漏洞测试时,顺带修复了另一个漏洞。
缺失的灰度级曾导致文本显示*粗糙*(还记得提及字体渲染平平吗?)CrossPoint 使用抗锯齿文本,本应用深灰色柔化边缘的像素错误显示为*黑色*,造成字体粗重。恢复该灰度级后整个阅读器的文本显示都得到改善。
## 更耗时的图像绘制方式
驱动层还包含我们未尝试的波形:制造商的四灰度图像模式 XTH4。它使用更长的脉冲序列产生四种灰度,刷新约需一秒。这在每次翻页时会令人烦恼,但用于打开图片或绘制休眠屏尚可接受。
该波形已包含在 freeink-sdk 中,另一款阅读器的驱动层使用了其图像模式变体。我们无需从头发明波形,可直接在X3上试用。Fable对此能否奏效毫无把握,但我敦促其推进。
首先需解决内存问题。推动阶段仅需区分深灰色、浅灰色和“保持像素不变”。黑白可共享后一指令,因首轮绘制已完成。更长的波形需为四种灰度设置独立指令。
另一阅读器驱动通过保留黑白图像副本并在RAM中与灰度数据合并来解决。我的X3使用ESP32-C3,约380KB RAM,最大空闲块仅53KB。528×792像素的屏幕即使一位副本也需52KB,无法随意添加缓冲区。
Fable 提议让 CrossPoint 初始即以所需格式绘制数据。图像查看器每次渲染已解码文件一次;这些通道可生成标识四种灰度的两位像素数据。驱动层无需额外整屏数据即可获得所需信息。
实现并刷写后,我打开引发调查的图像,对 Fable 说:“在我的原始*为什么有条纹*图像中,条纹已不再可见。”
[X3上修改前后对比。分界线下使用原始灰度波形;上方使用新波形]
测量结果一致:列亮度变化从黑白范围的大约4%降至1%;八像素处的峰值在频谱中完全消失。
[黑白范围相对列亮度,网格线间隔八屏幕像素。上图的规则波动在下图中消失]
更长波形还产生提升灰度表现的意外效果。深灰色的恢复赋予我们四级灰度;这也将浅灰色与白色进一步分离(还记得我关于它过于苍白的评价吗?)。深灰色比理想略深,但……
相似文章
一款微型电子阅读器
作者分享了他们使用XTEINK X4的体验,这是一款非常小巧的电子阅读器,做工精良,运行极简的cross point固件,并使用OpenDyslexic字体进行舒适的休闲阅读。
Xteink X4 电子墨水屏阅读器
对 Xteink X4 的评测,这是一款售价40英镑的电子墨水屏阅读器,小巧到可以贴在手机上。文章重点介绍了该设备的轻量化设计、不错的原厂固件,以及活跃的自定义固件生态,包括 CrossPoint、Papyrix 和 Inx 等选项。
你的ePub没问题。但Kobo说不。都怪Adobe。
一篇博文详细介绍了为何通过了严格的epubcheck验证的电子书在Kobo设备上却无法正常显示,原因在于Adobe过时的RMSDK渲染引擎,这凸显了以DRM为核心的Adobe Digital Editions的兼容性问题。
纸上编程
一位程序员分享了他使用Onyx BOOX Mira Pro Color电子墨水显示器作为主要编码显示器的经验,包括自定义主题和开源工具以提升可用性。
逆向工程我的电动滑板车并用Rust语言重写固件
Ben逆向工程了Egret GT电动滑板车,通过蓝牙和CAN总线发现了隐藏功能,并用Rust语言为显示屏单元编写了自定义固件。