【问题标题】:Confusion about current transformation matrix in a PDFPDF中当前变换矩阵的困惑
【发布时间】:2016-06-24 03:54:16
【问题描述】:

我对 PDF 中的当前转换矩阵 (CTM) 有一些困惑。对于this PDF 中的第 5 页,我检查了令牌流 (http://pastebin.com/k6g4BGih),它显示了在curve (c) 命令将转换矩阵设置为COSInt{10},COSInt{0},COSInt{0},COSInt{10},COSInt{0},COSInt{0} 之前的最后一个cm 操作。完整输出在http://pastebin.com/9XaPQQm9

接下来,我使用以下代码集从同一页面中提取直线和曲线命令,遵循 related SO question 中提供的代码 @mkl

  1. 主类:http://pastebin.com/htiULanR
  2. 助手类:

    一个。扩展 PDFGraphicsStreamEngine 的类:http://pastebin.com/zL2p75ha

    b. Path:http://pastebin.com/d3vXCgnC

    c。 Subpath:http://pastebin.com/CxunHPiZ

    d。 Segment:http://pastebin.com/XP1Dby6U

    e。 Rectangle:http://pastebin.com/fNtHNtws

    f。 Line:http://pastebin.com/042cgZBp

    g. Curve:http://pastebin.com/wXbXZdqE

在该代码中,我在 curveTo() 方法中使用 getGraphicsState().getCurrentTransformationMatrix() 打印了 CTM,该方法被 PDFGraphicsStreamEngine 类覆盖。这将 CTM 显示为 [0.1,0.0,0.0,0.1,0.0,0.0]。所以我的问题是:

  1. 这两个CTM不应该一样吗?

  2. 这两个 CTM 都具有缩放操作:第一个缩放系数为 10,第二个缩放系数为 0.1。如果我忽略缩放,我可以创建看起来非常接近原始 PDF 的an SVG。但我很困惑为什么会发生这种情况。我是否需要考虑all transformation matrices before the path 而不是最后一个?

【问题讨论】:

  • 是的,除非被“Q”重置,否则它们会相互连接。顺便说一句,您知道 PDFDebugger 工具吗?
  • 不,没听说过。你能指出来吗?
  • 只需从下载页面下载 debugger-app。它将以颜色和缩进向您显示内容流,这可能会简化理解。缩放 10 然后 0.1 显然缩放到 1。
  • @TilmanHausherr 感谢您指出这一点。这是一个真正的节省时间。

标签: pdf pdfbox


【解决方案1】:

首先:你说

curve (c) 命令之前的最后一个cm 操作将变换矩阵设置为COSInt{10},COSInt{0},COSInt{0},COSInt{10},COSInt{0},COSInt{0}

这是不正确的,cm 没有将变换矩阵设置到参数值,但它将矩阵参数乘以和前一个当前变换矩阵并将结果设置为新的当前变换矩阵,这个过程也称为连接。因此:

  1. 这两个 CTM 不应该是一样的吗?

不,因为 cm 没有设置,它会连接!

此外,当前的转换矩阵(以及所有其他图形状态值!)不仅会被显式设置器或连接器指令更改,还会被您当前忽略的恢复状态指令更改。因此:

  1. 是否需要考虑路径之前的所有转换矩阵而不是最后一个?

您可能需要考虑的不仅仅是上一个,但仅限于那些未被图形状态恢复撤销的。


让我们看看您的示例文档...

当您想跟踪当前的变换矩阵时,您必须同时检查 cmq/Q 指令。在您的第 5 页的情况下,内容流以这些指令为重点,直到第一条 c 曲线指令如下所示:

q 0.1 0 0 0.1 0 0 cm
q
q 10 0 0 10 0 0 cm BT
[...large text object...]
ET Q
Q
q 
[...clip path definition...]
q 10 0 0 10 0 0 cm BT 
[...small text object...]
ET Q
Q
q 
[...new clip path definition...]
0.737761 w
1 i
2086.54 2327.82 m
2088.17 2327.59 2089.82 2327.47 2091.46 2327.47 c 

假设一个起始单位变换矩阵,这意味着当前当前变换矩阵和图形堆栈中的当前变换矩阵的以下流程:

CTM:1 0 0 1 0 0

堆栈:空

q

CTM:1 0 0 1 0 0

堆栈:1 0 0 1 0 0

0.1 0 0 0.1 0 0 cm

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0

q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0

q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0 / 0.1 0 0 0.1 0 0

10 0 0 10 0 0 cm

CTM:1 0 0 1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0 / 0.1 0 0 0.1 0 0

BT
[...large text object...]
ET Q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0

Q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0

q 

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0

[...clip path definition...]
q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0 / 0.1 0 0 0.1 0 0

10 0 0 10 0 0 cm

CTM:1 0 0 1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0 / 0.1 0 0 0.1 0 0

BT 
[...small text object...]
ET Q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0

Q

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0

q 

CTM:0.1 0 0 0.1 0 0

堆栈:1 0 0 1 0 0 / 0.1 0 0 0.1 0 0

[...new clip path definition...]
0.737761 w
1 i
2086.54 2327.82 m
2088.17 2327.59 2089.82 2327.47 2091.46 2327.47 c 

因此,当您观察时,PDFBox 是正确的:

我在 curveTo() 方法中使用 getGraphicsState().getCurrentTransformationMatrix() 打印了 CTM,该方法被 PDFGraphicsStreamEngine 类覆盖。这将 CTM 显示为 [0.1,0.0,0.0,0.1,0.0,0.0]

【讨论】:

  • 非常感谢您的精彩回答。但是,如果我在绘制曲线的点处将变换矩阵设为 [0.1,0,0,0.1,0,0],那会将路径缩放 1/10,对吗?不知何故,这在视觉上似乎不正确,请参阅我在帖子中附加的 SVG,我在 没有 进行转换的情况下创建了该 SVG。
  • 但是在您的 svg 中,您的坐标值在 200..700 范围内,而 PDF 内容流中的坐标值在 2000 以上。因此,您似乎已经使用 1/10 缩放转换来创建它。
  • 哦,所以当我从 PDFGraphicsStreamEngine 覆盖方法say lineto(x,y) 时,x 和 y 已经转换了吗?我不必自己处理转换?
  • @rivu 是的,您在 lineTo 实现中检索到的坐标是将当前变换矩阵应用于内容流中的坐标值的结果。
  • 哦,非常感谢。我想我现在明白了。谢谢你对我这么有耐心:)。
猜你喜欢
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
相关资源
最近更新 更多