0

我想向任何可以帮助我完全理解此代码的人提供一张星巴克卡。这对我很重要。感谢您的时间!

我开始阅读 Lowagie 先生的精彩著作(iText in Action,第二版)。它写得很好,内容丰富。由于雇主的压力很大,我被迫跳到第 6 章。理解 n-Up 代码示例对我来说非常重要,作为一个新程序员,我将尝试用我的评论下面的代码问题。

如果可以的话,如果可以的话,请抽出一些时间并通过查看下面的问题来帮助我完成它,那就太好了。我感谢所有有用的评论。

public void manipulatePdf(String src, String dest, int pow)

问:这里的“pow”变量表示,例如,在 pow 为 3 时,生成的 n-up 将是 (2x2x2) 8。生成的 pdf 将有 8 个“src”PDF 副本。这个对吗?

A:

 throws IOException, DocumentException 
 {
   PdfReader reader = new PdfReader(src);
   Rectangle pageSize = reader.getPageSize(1);

   Rectangle newSize = (pow % 2) == 0 ?
     new Rectangle( pageSize.getWidth(), pageSize.getHeight()) : new Rectangle( pageSize.getHeight(), pageSize.getWidth());

问:上面我不确定发生了什么。在我看来,如果模运算的余数为零,那么新的矩形将以纵向创建,反之亦然。这个对吗?如果是这样,我可以问为什么吗?

A:

  Rectangle unitSize = new Rectangle(pageSize.getWidth(), pageSize.getHeight());

  for (int i = 0; i < pow; i++) 
  {
    unitSize = new Rectangle(
    unitSize.getHeight() / 2, unitSize.getWidth());
  }

问:在上面的“for”循环中,我相信我们正在为每个将被压缩到最终 pdf 表面上的 pdf 准备单元大小。我不明白为什么 getWidth() 也没有除以 2?

A:

  int n = (int)Math.pow(2, pow);
  int r = (int)Math.pow(2, pow / 2);
  int c = n / r;

问:'n' 是将 n'uped 到最终 pdf 表面的 pdfPages 的数量。到目前为止一切顺利,对吧?

'r' 可能是行数,'c' 可能是列数?

So, assuming a 'pow' of 3.. 
n = 8 which means 8 up of the pdf when you'll open up the final pdf?
r = 2 which means there'll be be two rows.
c = 4 which means there'll be four columns. 

A:

  Document document = new Document(newSize, 0, 0, 0, 0);
  PdfWriter writer = PdfWriter.getInstance(document,
  new FileOutputStream(String.format(dest, n)));
  document.open();
  PdfContentByte cb = writer.getDirectContent();
  PdfImportedPage page;
  Rectangle currentSize;
  float offsetX, offsetY, factor;
  int total = reader.getNumberOfPages();

  for (int i = 0; i < total; ) 
  {
    if (i % n == 0) 
    {
      document.newPage();
    }

问:每次在当前工作页面中达到预定的 nup 数时,上述 'for' 循环都会在最终的 pdf 中添加一个新页面。因此,如果我们有 n = 8,那么新页面将在 i = 8、16、24 等处调用。对吗?

A:

    currentSize = reader.getPageSize(++i);

问:这一行说明了源 pdf 有很多页面并且并非所有页面共享相同 pdf 页面大小的情况。正确的?

A:

    factor = Math.min(unitSize.getWidth() / currentSize.getWidth(),
                      unitSize.getHeight() / currentSize.getHeight());

问:min 函数返回最小的数。为什么unitSize除以currentSize?这就是我的理解崩溃的地方。

A:

    offsetX = unitSize.getWidth() * ((i % n) % c)
              +(unitSize.getWidth()
              - (currentSize.getWidth() * factor))/2f;

问:好的,offsetX 和 offsetY 用于将 pdf 页面定位到更大的最终 pdf 表面。我明白了。有人可以用英语向非程序员解释计算吗?这是一个知道每个数学运算做什么但不了解全局的情况。

A:

    offsetY = newSize.getHeight()
              - (unitSize.getHeight() * (((i % n) / c) + 1))
              + (unitSize.getHeight()
              - (currentSize.getHeight() * factor))/2f;

    page = writer.getImportedPage(reader, i);

    cb.addTemplate(page,factor, 0, 0, factor, offsetX, offsetY);
  }
  document.close();
}

我希望这个问题可以帮助许多其他人,他们是 iText 的新手,并且可能需要一些详细的代码演练。

我也希望不要发布负面且通常无益的评论。

谢谢大家的时间和帮助!

4

1 回答 1

1

假设您有一个 67 页的文档。

如果您想将此文档 2-up,您最终将得到 34 页:33 页,其中 2 页原始文档 + 1 页仅半满。要将两个页面并排放置,您需要将原始页面缩小到其大小的一半,并且需要将原始页面大小旋转 90 度。

如果您想将此文档 4-up,您最终将得到 17 页:16 页,其中 4 页原始文档 + 1 页,即四分之三页。要将四页并排放置,您需要将原始页面缩小到其大小的四分之一,并且不需要旋转原始页面大小。

如果您想将此文档 8-up,您最终将得到 9 页:8 页,其中 8 页原始文档 + 1 页仅在 3 / 8 中已满。将八页放在每个旁边的一页上另外,您需要将原始页面缩小到其大小的 1/8,并且您需要将原始页面大小旋转 90 度。

如果您想将此文档 16-up,您最终将得到 5 页:4 页,其中 16 页原始文档 + 1 页仅在 3 / 16 中已满。要在每个页面旁边的一页上放置 16 页另外,您需要将原始页面缩小到其大小的 1/16,并且您不需要旋转原始页面大小。

如果您想将此文档向上 32 页,您将得到 3 页:2 页包含 32 页的原始文档 + 1 页仅在 3 / 32 中已满。将 32 页放在每个旁边的一页上另外,您需要将原始页面缩小到其大小的 1/32,并且您需要将原始页面大小旋转 90 度。

如果您想将此文档向上 64 页,您将得到 2 页:1 页包含 64 页的原始文档 + 1 页仅占 3 / 64 的完整页。将 64 页放在每个旁边的一页上其他,您需要将原始页面缩小到其大小的 1/64,并且您不需要旋转原始页面大小。

2 = 2 (pow 1) => 旋转页面

4 = 2 x 2 (pow 2) => 不旋转页面

8 = 2 x 2 x 2 (pow 3) => 旋转页面

16 = 2 x 2 x 2 x 2 (pow 4) => 不旋转页面

32 = 2 x 2 x 2 x 2 x 2 (pow 5) => 旋转页面

64 = 2 x 2 x 2 x 2 x 2 x 2 (pow 6) => 不旋转页面

你看到图案了吗?pow 为奇数时,需要翻页;当它是偶数时,页面不需要旋转。这就是你需要测试的原因(pow % 2) == 0。它定义了新页面的方向。

该循环也很容易理解,尤其是如果您查看此图像:

在此处输入图像描述

大页A0可以分成两个A1页。这个A1页的高度就是A0页的宽度;A1 页面的宽度是 A0 页面高度的一半。A1可以分为两个A2页面。这个A2页面的高度就是A1页面的宽度;A2 页面的宽度是 A1 页面高度的一半。等等。

关于n我们将尝试在一个页面上放置的页数r、行c数和列数以及接下来的内容,您是对的。

现在我们需要定义factor. 您已经知道这一点width并且height被切换了几次。例如:当对 A4 页面的文档进行 2-upup 时,原始页面大小为 210 x 297,需要将其更改为unitSize148 x 210。换句话说,它需要缩小 148 / 210 倍( 0.705) 或 210 / 297 (0.707)。在这种情况下,我们使用因子 0.705。

我们可以这样计算偏移量:

offsetX = unitSize.getWidth() * ((i % n) % c);
offsetY = newSize.getHeight() - (unitSize.getHeight() * (((i % n) / c);

如果您想对文档进行 8-up,c则等于 4。所以您有:

(0 % 8) % 4 = 0 % 4 = 0; (0 % 8) / 4 = 0 / 4 = 0;
(1 % 8) % 4 = 1 % 4 = 1; (1 % 8) / 4 = 1 / 4 = 0;
(2 % 8) % 4 = 2 % 4 = 2; (2 % 8) / 4 = 2 / 4 = 0;
(3 % 8) % 4 = 3 % 4 = 3; (3 % 8) / 4 = 3 / 4 = 0;
(4 % 8) % 4 = 4 % 4 = 0; (4 % 8) / 4 = 4 / 4 = 1;
(5 % 8) % 4 = 5 % 4 = 1; (5 % 8) / 4 = 5 / 4 = 1;
(6 % 8) % 4 = 6 % 4 = 2; (6 % 8) / 4 = 6 / 4 = 1;
(7 % 8) % 4 = 7 % 4 = 3; (7 % 8) / 4 = 7 / 4 = 1;
(8 % 8) % 4 = 0 % 4 = 0; (8 % 8) / 4 = 0 / 4 = 0;
(9 % 8) % 4 = 1 % 4 = 1; (9 % 8) / 4 = 1 / 4 = 0;

你看到图案了吗?我们将页面添加到如下所示的网格中:(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (1, 1), (2 , 1), (3, 1)。为了得到真实的尺寸,我们乘以unitSize.getWidth()unitSize.getHeight()。显然,我们需要

offsetY = newSize.getHeight() - (unitSize.getHeight() * (((i % n) / c);

因为坐标系的性质:坐标系的原点在左下角。

我们调整offsetXoffsetY用缩小页面的实际宽度和可用空间的一半差值使导入的页面居中。

你说你不想要任何负面评论。请允许我给你一句话:你的问题不是 iText 问题,也不是编程问题。这是一道数学题。你真的需要在尝试编程之前学习数学,就像孩子需要先学会走路才能学会跑步一样。

造成混淆的一个可能原因可能是您没有考虑ISO 216的一项特殊功能。该算法不适用于非标准页面。例如:如果您的页面是正方形,则不能将高度一分为二并保持宽度。但这很明显,不是吗?

于 2014-07-27T00:21:01.633 回答