PostScript 具有与 PDF 大致相同的过滤器。您不需要解压缩数据,只需使用 PostScript 中的 FlateDecode 过滤器,并保持压缩数据不变。
请注意,Predictor 15(或任何其他 PNG 预测器)需要语言级别 3,但这应该不是问题,级别 3 已经是 18 年的标准。
否则,您需要实现支持 PNG 预测器的 FlateDecode 过滤器版本。我相信 zlib 非常有能力做到这一点。
[编辑]
您的“PostScript 输出”不完整,您正在使用尚未提供定义的 PDF 运算符(q 和 Q)。除此之外,这使得无法通过解释器运行代码。请按要求提供一个完整的简单示例文件。没有粘贴代码,我不倾向于自己创建文件,此外,二进制文件根本不能很好地剪切和粘贴。
从桌面检查我的头顶我不能立即发现问题,但由于我无法运行代码,我很容易遗漏一些东西。
[编辑 2]
不出所料,该文件可以正常工作。
您尚未提供您正在创建的PostScript文件。通过查看您开始使用的 PDF 文件,我很难判断您创建的 PostScript 有什么问题。
当然,您可以使用 Ghostscript(我看到您已经使用它来创建 PDF 文件)来创建 PostScript 文件,然后查看其中包含的内容。如果设置 -dCompressFonts=false 则输出字体甚至不会被压缩。
例如:
37 0 4 -52 33 -1 d1
0.01 0 0 0.01 0 0 cm
q 2900 0 0 -5100 400 -99.9998 cm
BI
/IM true
/W 29
/H 51
/BPC 1
/D[1
0]
/F[/A85
/CCF]
/DP[null
<</K -1
/Columns 29>>]
ID
-D=,M5m+t^0_>op8\HM"Du]KKrr2rthqG/5qU_ik]$f$TlUslD91qoN93j0%dckk:ld^*DV25!+
!WX>~>
EI Q
当然,您需要查看序言以了解其中使用的所有过程是如何定义的,但是您可以自己做,当然不需要我做。请注意,图像掩码使用 CCITTFax 和 ASCII85 解码过滤器,添加其他过滤器很简单。由于数据保证为“单色”(它是一个掩码),CCITT 过滤器通常会提供优于 Flate 的压缩。
请注意,如果您真的使用的是 Ghostscript 9.05,那么您应该升级,即 6 岁。
如果您要解释为什么要从 PDF 中获取丑陋的位图 type 3 字体并从中制作丑陋的位图 type 3 PostScript 字体,这可能会有所帮助。
[编辑 3]
仔细查看您的 PostScript 文件,字形的定义与您在问题中提出的内容不匹配。实际内容如下所示:
/g10135{
88 0 4 -70 82 8 setcachedevice
q
[
0.01 0 0 0.01 0 0 ] M
q
[7800 0 0 -7800 400 800 ]M
<<
/ImageType 1
/Width 78
/Height 78
/ImageMatrix [ 78 0 0 -78 0 78]
/BitsPerComponent 1
/Decode [1
0]
/DataSource ....binary data.....
<< /Predictor 15
/Columns 78
/BitsPerComponent 1>>
/FlateDecode filter def
>> imagemask
Q
Q
}bind def
您没有提供文件、过程或字符串源作为字典中 DataSource 键的值。本质上,PostScript 解释器读取并标记/DataSource
密钥,然后继续将二进制文件作为 PostScript 处理。不出所料,当使用 Ghostscript 处理时,这会导致错误“(二进制令牌,类型 = 156)中的语法错误”。
如果您已经过去了,那么您会发现filter
操作员也采用了数据源,而您也没有为此提供数据源。
所以你需要为你的二进制数据创建一个数据源。取决于你如何做到这一点,但这currentfile
是一种方式。或者readstring
假设您知道字符串长度。
所以像:
<<
/ImageType 1
/Width 29
/Height 51
/ImageMatrix [29 0 0 -51 0 51]
/BitsPerComponent 1
/Decode [1 0]
/DataSource
<length> string dup
currentfile exch readstring
.....binary data.....
<<
/Predictor 15
/Columns 29
>> /FlateDecode filter
>> imagemask
显然,您必须通过知道字符串长度来填写自己。在我看来,FlateDecode 的字典参数似乎不需要它。
[编辑 4] 我注意到这似乎是为了商业用途。这没什么错,但我不会为你做所有的功课,如果你的工作取决于你学习语言以完成这项工作。
我将略过下面的实际实现细节,试图勾勒出你哪里出错了。在实践中事情会稍微复杂一些,我没有讨论存储在 CharStrings 字典中的过程是如何创建的,或者与早期名称绑定(这是 PostScript 中的一个重要概念)的区别。
您现有的代码是:
/g10135{
88 0 4 -70 82 8 setcachedevice
q
[
0.01 0 0 0.01 0 0 ] M
q
[7800 0 0 -7800 400 800 ]M
<<
/ImageType 1
/Width 78
/Height 78
/ImageMatrix [ 78 0 0 -78 0 78]
/BitsPerComponent 1
/Decode [1
0]
/DataSource {417 string dup
currentfile exch readstring}
...binary data....
<< /Predictor 15
/Columns 78
>>/FlateDecode filter def
>> imagemask
Q
Q
}bind def
因此,PostScript 解释器一次读取一个字节,并将它们转换为标记。这要么产生一个可执行的令牌,它被执行,要么导致一个堆栈上的操作。
所以/g10135
被{
字符终止,因为那是一个保留字符。/
引入了一个名称对象,所以我们最终得到了g10135
我们推送到操作数堆栈的名称对象。该{
字符引入了一个可执行数组,因此我们将 amark
放在操作数堆栈中。
接下来我们读到 88,以一个空格字符结束。那是一个数字,所以我们将它存储在操作数堆栈中,就像其他数字一样。操作数堆栈现在包含:
/g10135
mark
88
0
4
-70
82
8
然后我们读取以空格结尾的 setcachedevice。这不是标准标记,因此解释器开始查看字典堆栈上的字典,寻找定义。由于是标准运算符,我们在systemdict中找到并执行。这消耗了操作数堆栈中的 6 个操作数,它没有其他效果(实际上它有,但这有点特殊,因为我们在字体内执行,但我们现在将忽略它)。
接下来我们遇到 a q
,再次在字典堆栈上的每个字典中查找它以找到定义。这在您自己的序言中定义为 a gsave
,因此它不接受操作数并且不返回任何操作数,它只是保存图形状态,将保存深度增加 1。
剩下的我就不赘述了,但是,最终我们到达了 your /DataSource
,这是一个名字,所以我们将它压入操作数堆栈。接下来我们遇到的是{
一个过程定义,所以我们在操作数堆栈上压入一个标记。然后我们遇到 a417
所以我们推送那个 , string
, dup
, and currentfile
,所以我们的堆栈看起来像:exch
readstring
/DataSource
mark
417
string
dup
currentfile
exch
readstring
然后我们得到字符}
That 是可执行数组的结束标记,因此我们创建数组并将其压入操作数堆栈:
/DataSource
{....}
然后我们返回程序并继续执行它。接下来我们找到一些二进制数据,因此我们尝试将其作为 PostScript 二进制标记来执行。因为它无效,解释器会抛出错误。
仅仅创建一个可执行数组并不足以实际执行它。如果您查看我在上面编辑 3 末尾发布的大纲代码,您会注意到我没有将等readstring
放在可执行数组中,我只是让解释器立即执行该代码。
通过这样做,readstring
操作currentfile
(在这种情况下为实际的 PostScript 程序)并从该文件中的当前点读取数据字节。当前点将在消耗终止 的空白之后立即出现readstring
,即实际的二进制数据。运算符从文件中读取足够的readstring
字节来填充字符串,将字符串留在操作数堆栈上。文件指针移动到二进制数据之后的字节,解释器在该点恢复令牌扫描。因此,它会创建 FilterParams 字典,将 /FlateDecode 名称放在堆栈上,然后执行filter
使用名称、字典和字符串操作数的运算符,返回一个文件对象。然后,该文件对象成为与传递给操作员的图像字典中的 DataSource 键关联的值imagemask
。
虽然我没有测试过该代码,但它基本上是正确的。当然还有其他方法可以达到同样的目的。
基本上就我准备好了,你需要去看看我写的东西,并将它与你自己的程序进行比较。
请注意,调查此问题的最简单方法是获取 CharProc 的内容(不包括 setcachedevice),然后将其作为 PostScript 程序运行。