我正在从Pdf到postscript解析Type3字形字体。输入文件具有内联图像,其中应用了数据流flate解码过滤器。过滤器具有预测器15。 任何正文都可以帮助我将图像流从pdf格式化为postscript。 这是输入流以pdf
给出的方式32 0 obj
<<
/Length 342
>>
stream
37 0 4 -52 33 -1 d1
0.01 0 0 0.01 0 0 concat
gsave 2900 0 0 -5100 400 -100 concat
BI
/IM true
/W 29
/H 51
/BPC 1
/D[1
0]
/F/Fl
/DP<</Predictor 15
/Columns 29>>
ID xœ=Ì¡
Â`ÅñÿeÂLθ n`0>Ù`ñ
f[¦DŒF_ÁhC1ì%Ä)¶o.¢Ÿ"†ßá†s®àì]^ÏŠÅS³tFËÂÚ3sç'Æi èÐÇ:j‹¹¨åìOTÿ ª•ÉÙÕÅŸ¨‡¹Ó$°ÆΚWèÁ!¯Cê
÷0&f µtðV ©Ë÷iôíتÄ~Ø•Œöí&´« +ro#Ê‚ûÏÅùlßG'
EI gRestore
endstream
endobj
这就是我想在Postscript
中输出的内容/g21 {
37 0 4 -52 33 -1 setcachedevice
q
[0.01 0 0 0.01 0 0] concat
q
[2900 0 0 -5100 400 -100] concat
[ xœ…ѱNÃ0à3©p'l` ¢abä*‰'@‚W`KP¡00öQ`d@ ¨CWž€u`‰štj4Ü]@ /ù¤œíÿ| ÂìÊüå7úŠ‰V'‚ª¦zò¡9à*´º
m1Õ`ñ—íü‹‡½Gù@ãÝAVxc¥Ž®"6oFܬJHÃB3(æod¾…xFP†o$!v±Ã»·0—gØY÷J$û„`´#zÊ
Oí¼œÑ¸é`Ê}ü…ñ.Z¯›cF4\¡*O¤ÑPÒYòî¦/éG‘qÑç¼2>öq<Üœ<
B˜5‚²¢ºÎ/èqUTUàoÓ9͔Π܉ä²z ‡S×ÛÙC(PA²š7èT¾ŽCGÈRaLéåksnˆÃ0z<zø:ž=
]
0
<<
/ImageType 1
/Width 29
/Height 51
/ImageMatrix [29 0 0 -51 0 51]
/BitsPerComponent 1
/Decode [1 0]
/DataSource { 2 copy get exch 1 add exch }
<</Predictor 15
/Columns 29
>>
/FlateDecode filter
>>
imagemask
pop pop
gRestore
gRestore
} def
答案 0 :(得分:0)
PostScript与PDF大致相同。您不需要解压缩数据,只需在PostScript中使用FlateDecode过滤器并保持压缩数据不变。
请注意,预测器15(或任何其他PNG预测器)需要语言级别3,但这不应该成为问题,级别3已经成为18年的标准。
否则,您需要实现支持PNG预测器的FlateDecode过滤器版本。我相信zlib非常有能力做到这一点。
[编辑]
你的PostScript输出&#39;如果不完整,您使用的是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
当然,您需要查看序言,看看如何定义所有程序,但您可以自己做,但您当然不需要我这样做。请注意,imagemask使用CCITTFax和ASCII85解码过滤器,它可以添加额外的过滤器。由于数据保证是单色的&#39; (它的掩码)CCITT滤波器通常会给Flate提供更好的压缩。
请注意,如果你真的使用Ghostscript 9.05,那么你应该升级,即6岁。
如果你要解释为什么你想从PDF中获取一个丑陋的,位图的3型字体并从中制作一个丑陋的,位图类型的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处理。不出所料,这会导致错误的语法错误(二进制令牌,类型= 156)&#39;用Ghostscript处理时。
如果你已经过去了,那么你会发现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
,我们将其推送到操作数堆栈。 {
字符引入了一个可执行数组,因此我们在操作数堆栈上放置了mark
。
接下来我们读取88,以空格字符结束。这是一个数字,所以我们将它存储在操作数堆栈上,同样是其他数字。操作数堆栈现在包含:
/g10135
mark
88
0
4
-70
82
8
然后我们读取setcachedevice,它由一个空格终止。这不是标准令牌,因此解释器开始查看字典堆栈上的字典,寻找定义。由于它是标准运算符,我们在systemdict中找到它并执行它。从操作数堆栈中消耗6个操作数,它没有其他效果(实际上它确实如此,但这有点特殊,因为我们在字体内部执行,但我们现在忽略它)。
接下来我们遇到q
,再次查询字典堆栈中的每个字典以查找定义。这在你自己的prolog中被定义为gsave
,因此它不需要操作数并且不返回操作数,它只是保存图形状态,将保存深度增加1。
我不会经历剩下的任务,但是,最终我们到达你的/DataSource
,这是一个名字,所以我们把它推到操作数堆栈上。接下来我们遇到的是{
,它是一个过程定义,因此我们在操作数堆栈上按下一个标记。然后我们遇到417
,因此我们推送string
,dup
,currentfile
,exch
和readstring
,因此我们的堆栈如下所示:
/DataSource
mark
417
string
dup
currentfile
exch
readstring
然后我们得到字符}
这是可执行数组的结束标记,所以我们创建数组并将其推送到操作数堆栈:
/DataSource
{....}
然后我们返回程序并继续执行它。接下来我们发现的是一些二进制数据,因此我们尝试将其作为PostScript二进制令牌执行。因为它不是有效的,所以解释器会抛出错误。
仅创建可执行数组并不足以实际执行它。如果你查看我在上面编辑3结尾处发布的大纲代码,你会注意到我不将readstring
等放在可执行数组中,我只是允许解释器立即执行该代码。
通过这样做readstring
作用于currentfile
(在这种情况下是实际的PostScript程序)并从该文件中的当前点读取数据字节。在消耗终止readstring
的空格(即实际二进制数据)之后,当前点将立即生效。 readstring
运算符从文件中读取足够的字节以填充字符串,将字符串保留在操作数堆栈上。文件指针已移至二进制数据之后的字节,解释器在该点恢复令牌扫描。然后它创建FilterParams字典将/ FlateDecode名称放在堆栈上,然后执行filter
运算符,该运算符使用名称,字典和字符串操作数,返回文件对象。然后,该文件对象将成为与图像字典中的DataSource键关联的值,该值将传递给imagemask
运算符。
虽然我还没有测试过该代码,但它基本上是正确的。当然还有其他方法可以实现同样的目标。
基本上我已准备好接受这一点,你需要去看看我写的内容并将其与你自己的程序进行比较。
请注意,调查此问题的最简单方法是获取CharProc的内容(不包括setcachedevice),然后将其作为PostScript程序运行。