微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

iText - 扫描的 PDF 上页面大小的错误指示

如何解决iText - 扫描的 PDF 上页面大小的错误指示

我正在使用 iText 7 (7.1.14) 开发一个应用程序,以在现有 PDF 的右上角写入文本。 除了在某些文件上,例如可以从 here 下载的文件,它给我的页面大小不正确。 它发生在扫描的 PDF 中。 页面大小返回 595.44 x 842.04。 但真正的尺寸是 1656.0 x 2339.0。 我尝试了所有页面大小,如 MediaBox 等...

PdfDocument pdfDoc = new PdfDocument(pdfReader,new PdfWriter(file));
pageSize = page.getPageSize();
System.out.println("W:"+page.getPageSize().getWidth()+"H:"+page.getPageSize().getHeight());
System.out.println("W:"+page.getMediaBox().getWidth()+"H:"+page.getMediaBox().getHeight());
System.out.println("W:"+page.getCropBox().getWidth()+"H:"+page.getCropBox().getHeight());
System.out.println("W:"+page.getBleedBox().getWidth()+"H:"+page.getBleedBox().getHeight());
System.out.println("W:"+page.getArtBox().getWidth()+"H:"+page.getArtBox().getHeight());

准确地说,剩下的代码是这样的:

PdfFont bf = PdfFontFactory.createFont(FontConstants.HELVETICA);
float stringWidth = bf.getWidth(stringa,fontSize);
PdfCanvas canvas=new PdfCanvas(page.newContentStreamAfter(),page.getResources(),pdfDoc);
float centeredPosition = pageSize.getWidth() - (pageSize.getWidth()/30);
float yCoord = (pageSize.getHeight()-fontSize-5);
float xCoord = centeredPosition-stringWidth;
canvas.beginText().setFontAndSize(bf,fontSize)
    .moveText(xCoord,yCoord)
    .showtext(stringa)
    .setTextRenderingMode(pageN)
    .endText();
pdfDoc.close();

链接的示例 PDF 中,它不是位于右上角,而是位于工作表的中间。如果我使用文本 PDF 文件,结果是正确的。

解决方法

你误解了这些 getter 的输出。特别是它们与像素无关。

所有这些框都以默认用户空间单位给出。一个这样的单位是 1/72 英寸,除非它被相应页面的 UserUnit 条目重新定义(一个正数,应该给出默认用户空间单位的大小,以 1 ⁄ 72 英寸的倍数表示。支持值的范围应取决于实现。 - ISO 32000-2,表 31 — 页面对象中的条目)。 >


关于您添加的有关向 PDF 添加文本的问题:

你的文本被绘制的位置不是你期望它被绘制的位置的原因是用户空间坐标系已经在原始内容流中进行了转换:

0.36000 0 0 0.36000 0 0 cm
q
1656 0 0 2339 0 0 cm
/Im1 Do
Q

第一条指令(0.36000 0 0 0.36000 0 0 cm)改变了当前的变换矩阵,从而有效地将用户坐标系缩放了 0.36;之后一个用户空间单位是 1/200 英寸。

以下指令包含在 q保存图形状态)... Q恢复图形状态 em>) 包络,因此其中当前变换矩阵的变化不会影响其后的任何指令。

为了完全不受现有内容流指令的此类图形状态更改的影响,您应该自己将现有的未知内容包装在另一个 q ... Q 信封中.

实际上有一个 PdfCanvas 构造函数为你做这件事;简单替换

PdfCanvas canvas=new PdfCanvas(page.newContentStreamAfter(),page.getResources(),pdfDoc);

PdfCanvas canvas=new PdfCanvas(page,true);

另请参阅该构造函数的 JavaDoc:

/**
 * Convenience method for fast PdfCanvas creation by a certain page.
 *
 * @param page           page to create canvas from.
 * @param wrapOldContent true to wrap all old content streams into q/Q operators so that the state of old
 *                       content streams would not affect the new one
 */
public PdfCanvas(PdfPage page,boolean wrapOldContent)

但请注意:如果您向一个页面添加多个新的内容流,请不要对同一页面反复使用 true 代替 wrapOldContent;这会将旧内容越来越深地包裹在这样的信封中,但 PDF 处理器只需要支持有限的深度,PDF 32000-1 仍然提到了 28 个包裹的嵌套限制。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。