【问题标题】:PDFbox to iText coordinate conversions using AffineTransform使用 AffineTransform 将 PDFbox 坐标转换为 iText
【发布时间】:2013-04-29 19:45:02
【问题描述】:

问题:

我似乎无法让一种坐标格式与另一种格式一起使用。我想我只是没有使用正确的矩阵,但我对它们的了解还不够确定。我希望得到一些帮助,以确定我是否正在假设我的变换应该是什么。

iText 根据 ISO 标准使用左下角作为原点,但 pdfbox 代码和为我提供从 pdf 中抓取坐标的程序都使用左上角作为原点。

我应该做什么样的变换来调整坐标,以便 iText 可以以一种可行的方式使用它们?

背景

我有一些代码使用 pdfbox 来操作 pdf 并删除一些数据,现在我需要将修改后的数据重新注入页面。 PDFBox 的作者一直在破坏 pdf,所以我们决定使用 iText 进行注入。

诀窍是我与 pdfbox 一起使用的坐标(以及我们从生成 pdf 的系统中获得的坐标)似乎与 iText 的不匹配。

到目前为止我做了什么

我检查了一下,iText 页面和cropbox 似乎都是准确的:

  PdfReader splitPDFDocumentReader = new PdfReader(splitPDFdocumentName);

  com.lowagie.text.Rectangle theCropBox = splitPDFDocumentReader.getCropBox(1);
  com.lowagie.text.Rectangle thePageSize = splitPDFDocumentReader.getPageSize(1);

  consolePrintln("Cropbox: " + theCropBox.toString());
  consolePrintln("\tBottom " + theCropBox.getBottom());
  consolePrintln("\tLeft " + theCropBox.getLeft());
  consolePrintln("\tTop " + theCropBox.getTop());
  consolePrintln("\tRight " + theCropBox.getRight());

  consolePrintln("PageSize: " + thePageSize.toString());
  consolePrintln("\tBottom " + thePageSize.getBottom());
  consolePrintln("\tLeft " + thePageSize.getLeft());
  consolePrintln("\tTop " + thePageSize.getTop());
  consolePrintln("\tRight " + thePageSize.getRight());

输出:

Cropbox: Rectangle: 612.0x792.0 (rot: 0 degrees)
    Bottom 0.0
    Left 0.0
    Top 792.0
    Right 612.0
PageSize: Rectangle: 612.0x792.0 (rot: 0 degrees)
    Bottom 0.0
    Left 0.0
    Top 792.0
    Right 612.0

这让我相信这只是翻转 y 坐标的问题,因为 pdfbox 的原点在左上角,而 iTexts 在左下角。

我遇到麻烦的地方

当我应用转换时:

  //  matrix data example:
  //  [m00, m01, m02,
  //   m10, m11, m12,
  //   0  , 0  , 1   ]  // this bit is implied as part of affineTransform docs
  content.saveState();
  int m00 = 1;
  int m01 = 0;
  int m02 = 0;
  int m10 = 0;
  int m11 = -1;
  int m12 = 0;

  content.concatCTM(m00, m10, m01, m11, m02, m12);

  content.setColorStroke(Color.RED);
  content.setColorFill(Color.white);
  content.rectangle(x, y, x + height, y + width);
  content.fillStroke();

  content.restoreState();

它似乎没有达到我的预期。看来数据完全在页面之外了。

杂项说明

说实话,我不太擅长矩阵,也许我需要做一些翻译工作,而不是像我试图做的那样简单地翻转 y?

concatCTM 函数似乎采用与awt.geom.affinetransform 相同的格式,我将通过this exampletutorial 使用转换。

【问题讨论】:

  • iText 使用 ISO-32000-1 中定义的坐标系。如果 PDFBox 中的坐标系不同,则它们使用的是自定义转换。关于转换矩阵,您是对的:CTM 的工作方式与我们在高中时所学的代数略有不同。在高中我们使用矩阵来转换对象;在 PDF 中,矩阵用于变换坐标系。这种细微差别会导致不同的结果。您可能会发现更改坐标(如高中所教)比更改 CTM 更容易(如 ISO-32000-1 中所述)。另外:请升级。
  • 我假设它就像您在 openGL/directX 中操作对象的方式一样,或者类似于 Processing 的转换原语。我想我可能只是转换错误。我认为在 Y 轴上翻转与旋转 180* 并在 X 上翻转是一样的。我会继续玩。你说的升级指的是什么?
  • 关于升级,我看到您在代码中使用了我的名字。请阅读lowagie.com/itext2
  • 你的律师使用的论点在我看来是一种恐吓策略……任何可能都有侵权内容。我们可能对 agpl 下的最新版本(或付费许可)和对早期版本一样负责,或者对使用任何许可的 LGPL(如 hibernate)负责。该论点基本上是说,无论许可证如何,我们都不应该使用任何 3rd 方代码。
  • 我们可以保证您的代码库仍然没有错误代码?我还没有阅读任何关于源代码清理的更改日志,而且你写的那篇文章似乎是在 5.0 发布后 2y8mo 写的。那篇文章是我能找到的关于这个问题的唯一参考。您是否通过我们可以参考的第 3 方签订了源代码审计合同?他们发现不好的事情了吗?

标签: java awt itext pdfbox affinetransform


【解决方案1】:

我想通了。当我翻转 y 坐标时,我假设它会翻转文档的中间并反转所有内容。然而它实际上翻转了 y=0;

翻转 y=0 后,您需要将整个页面向上移动。

我最终直接使用 affineTransform 来完成它,然后将生成的矩阵输入 concatCTM。

content.saveState();

AffineTransform transform = new AffineTransform();

transform.scale(1, -1); // flip along the line y=0
transform.translate(0, -pageHeight); // move the page conet back up

/* the version of iText used in Jasper iReport doesn't seem to use affineTransform directly */
double[] transformMatrix = new double[6];
transform.getMatrix(transformMatrix);

content.concatCTM((float) transformMatrix[0], (float) transformMatrix[1], (float) transformMatrix[2], (float) transformMatrix[3], (float) transformMatrix[4], (float) transformMatrix[5]);

// drawing and printing code here (stamping?)

content.restoreState();

【讨论】:

  • 是的,您的初始转换中缺少翻译。
  • 现在文字是颠倒的……是的,还有更多的变换。感谢您抽出宝贵时间回顾事情。我请求订购您的书的第二版 - 似乎有很多改进,即使我们必须支付一些费用,也值得更新。
  • 我已经开始写第三版了。我会免费提供,但是……我上周二才开始写,而且只有 17 页。至于最新版本:是的,添加了很多功能。
  • 关于 现在文字是倒着写的... 如果您不希望发生这种情况,您可以只使用翻译转换而不是翻转转换y=0。这为您提供了一个坐标系,其原点位于左侧,但页面区域中的 y 坐标。要使用其他程序中的坐标,您只需更改 y 坐标的符号。如果没有翻转转换,文本将不再颠倒呈现......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
相关资源
最近更新 更多