摘要

  • RFC 2159 虽称 G3Fax 映射“几乎逐字节复制”,实际算法还要映射参数、翻转每个字节内的位序、补齐页尾并插入六个 EOL 的页面分隔符。
  • 无损返回依赖页界、末尾 EOL 和未具名 DCS 位都在;正文哈希相同,不能单独证明返回的是同一个传真对象。
  • 结构可以正确往返,接收端仍可能不支持所声明的编码、分辨率或页面宽度,也可能渲染出比例错误或缺行的图像。

“几乎”不是修辞,而是算法边界

1998 年 1 月发布的 RFC 2159 处理的是一种非常具体的搬运:把已经采用 Group 3 传真格式的数据放进 MIME,并在它与 X.400 表示之间转换。文档还特意说明,image/g3fax 并不是通用互联网图像格式。它不负责把任意图片变成传真,而是尽量保全一个已经存在的传真表示。

这个表示由三类状态组成。第一类是编码方式的选项;第二类是把连续比特划分成页面的结构;第三类才是每一页依照 T.4 编码的图像比特。三类状态走的通道并不相同:选项进入 MIME 参数,X.400 的逐页 BIT STRING 序列变成 MIME 正文里的分隔符,页内比特又采用另一种字节内位序。

因此,“几乎逐字节复制”比听上去更严格。早期的 RFC 1494 把真正的 Byte Copy 定义为不做转换、直接复制字节流。G3Fax 从来不符合这个定义。压缩图像无需解码再编码,但装载这些比特的对象必须重建。

默认值和未知位也是内容

MIME 一侧可以声明页面长度、页面宽度、一维或二维编码、非压缩模式、粗或细分辨率、页数,以及用 Base64 表示的 Device Control String。缺省并不等于“没有信息”:未写参数时,RFC 2159 规定 A4 长度、A4 宽度、一维编码和粗分辨率。

同一个具名选项在 T.30 和 X.400 中还可能对应不同的位号。原因不是语义变化,而是两套体系从字节的不同方向编号。网关必须映射“这个位代表什么”,不能机械复制“第几个位”。这和后面把页面数据中每个字节的位序翻转,又是两件不同的工作。

命名参数之外还有 DCS 位。RFC 要求:只要 Device Control String 中出现没有专门名称的位,就应带上 DCS 参数;同时又警告,使用这些非基础位时,互通并无保证。保存未知位能保住证据,却不能凭空制造接收能力。

这也是为什么正文哈希不够。页面比特可以原样留存,但默认值可能被不同解释,某个能力位可能丢失,或者接收端根本不支持它请求的模式。图像数据与能力合同相关,却不是同一份记录。

X.400 的页面序列必须变成 MIME 的页界

X.400 把传真正文表示为 ASN.1 BIT STRING 的序列,每个元素是一页。MIME 需要一段连续正文,于是 RFC 2159 借用返回命令模式标记作为页界:连续六个 EOL,每个 EOL 是十一个 0 加一个 1。六个 EOL 必须从字节边界开始,所以必要时要在图像末尾补 0。

文档给出的分隔字节序列是 00 10 01 00 10 01 00 10 01,并称它不会出现在图像内部。这让网关无需先渲染页面就能查找边界。但页界位置、对齐方式和补了多少位,也由此变成不可丢的证据。相同的一长串比特如果失去分隔,不能证明还保留原来的页面序列。

从 X.400 到 MIME 时,网关先去掉每页末尾已有的 EOL,把字节内位序调整为互联网常用的“首字节最高位是 G3Fax 第一位”,补齐到整字节,再加六个 EOL,最后连接所有页面。这没有重编码传真图像,却也绝不是原封不动复制。

返回 X.400 时,网关按六 EOL 切页,不得删除末尾 EOL;随后翻转每个字节内的位序,把每页变为 ASN.1 BIT STRING,再组成序列。RFC 2159 明确说“不删除末尾 EOL”是对 RFC 1494 的修改;旧算法曾要求返回时去掉末尾 EOL 和填充。宏观标签没变,边界上的字节规则却已经改变。

哈希必须标明自己在证明哪一层

如果 MIME 邮件经过一跳后哈希不变,这能证明那段 MIME 八位组在这一步未变。它不能证明前一个网关从 X.400 打包时采用了正确位序。直接把 ASN.1 BIT STRING 的打包字节与 MIME 正文求哈希,正确转换反而可能不同,因为规范要求逐字节翻转。

有效比较必须选择同一语义层。先记录每页有意义的比特长度和 ASN.1 未使用位数,再按指定规则转换位序,记录为对齐补了多少 0、每个六 EOL 从哪里开始。返回后,页界数量应恢复页数;在同一填充规则下,应恢复各页的有意义比特、参数和 DCS 位。

相邻的 RFC 2157 给出了判断标准:equivalence 是两条映射组合后形成的无损转换。单向产生合法正文只证明完成了一次 mapping;把同一个已识别对象按具名反向规则还原,才触及更强的等价主张。

可逆对象仍可能是不可用页面

RFC 2159 的非规范性实现提示没有把“结构可逆”说成“传真可用”。没有 fineResolution 时,像素高度是宽度的两倍。DCS 功能位的范围当时已经超过 MIME 少数具名参数。文档还转述:细分辨率与某些页面长度相对容易支持,B4 或 A3 宽度则更困难;有些传真机要求每条扫描线严格包含声明的像素数,省略右侧空白可能出问题。

所以,网关可以完美保留页面和选项,接收解码器却不支持那个模式;解码器也可能接受数据,却用错误几何比例显示;图像看起来像一页传真,右侧仍可能被裁掉。语法接受、页面重建、像素几何、视觉一致与人工可读,是相继发生的不同事实。

今天的 IANA 媒体类型注册表 仍列出 image/g3fax,历史性的 MIME/X.400 映射表 仍把它配到 g3-facsimile。注册表证明公共名称和参考映射存在,不证明某个产品实现了 1998 年返回规则,更不证明部署中的接收端能显示所有选项。

真正有用的是一张联结收据

可靠测试应从完整 X.400 对象开始:参数、DCS 原始字节、页数、各 BIT STRING 的有意义比特长度与指纹。它还要记录网关版本与映射表身份。转成 MIME 后,保存参数、正文、补位数量和分隔符偏移。反向转换必须明确使用哪一个实现,并比较恢复后的序列、页长度、参数和 DCS。

结构往返通过后,才轮到解码测试:明确支持的一维/二维模式、分辨率、宽度和长度;统计每条扫描线像素;测量页面几何;把渲染结果与约定参照物比较。投递与人类阅读仍在更后面。

Lu Heng 的 Running-Code Primacy 提醒我们,算法是协调路径,执行记录才是运行事实;Minimum Initial Specification 把共享规则与本地解码能力分开;Reality Layers 则解释了为什么类型标签、可逆表示、渲染图像和可用文档不能互借证据。

RFC 2159 的“几乎”并非含糊,而是一份极短的缺口清单:除了页内图像比特,还有参数、页界、位序、填充和接收端。缺少其中任何一项,完整的字节流也可能无法重建成原来的传真对象。

来源