iText - 扫描的 PDF 上的 pageSize 指示错误
iText - Wrong indication of pageSize on scanned PDFs
我正在使用 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 中,它不是位于右上角,而是位于 sheet 的中间。如果我取一个文本PDF文件,结果是正确的。
你误解了那些吸气剂的输出。特别是它们与像素无关。
所有这些框均以默认用户 space 单位给出。一个这样的单位是 1/72 英寸,除非它被相应页面的 UserUnit 条目重新定义(一个正数,应给出默认用户 space 单位的大小,是 1 ⁄ 72 英寸的倍数。支持值的范围应取决于实现。 - ISO 32000-2,Table 31 — 页面对象中的条目)。
关于您添加的有关向 PDF 添加文本的问题:
之所以你的文本绘制位置不是你期望的绘制位置,是因为用户 space 坐标系在原始内容流中已被转换:
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
)改变了当前的变换矩阵,因此有效地将用户坐标系缩放了 .36;之后一个用户 space 单位是 1/200 inch.
以下指令包裹在q(保存图形状态)... Q (恢复图形状态)包络,因此其中当前变换矩阵的变化不影响此后的任何指令。
为了完全不受现有内容流指令的此类图形状态变化的影响,您应该自己将现有的未知内容包装在另一个 q ... Q信封.
实际上有一个 PdfCanvas
构造函数为您做这件事;只需替换
PdfCanvas canvas=new PdfCanvas(page.newContentStreamAfter(),page.getResources(),pdfDoc);
来自
PdfCanvas canvas=new PdfCanvas(page, true);
另请参阅该构造函数的 JavaDocs:
/**
* 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 层包裹的嵌套限制。
我正在使用 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 中,它不是位于右上角,而是位于 sheet 的中间。如果我取一个文本PDF文件,结果是正确的。
你误解了那些吸气剂的输出。特别是它们与像素无关。
所有这些框均以默认用户 space 单位给出。一个这样的单位是 1/72 英寸,除非它被相应页面的 UserUnit 条目重新定义(一个正数,应给出默认用户 space 单位的大小,是 1 ⁄ 72 英寸的倍数。支持值的范围应取决于实现。 - ISO 32000-2,Table 31 — 页面对象中的条目)。
关于您添加的有关向 PDF 添加文本的问题:
之所以你的文本绘制位置不是你期望的绘制位置,是因为用户 space 坐标系在原始内容流中已被转换:
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
)改变了当前的变换矩阵,因此有效地将用户坐标系缩放了 .36;之后一个用户 space 单位是 1/200 inch.
以下指令包裹在q(保存图形状态)... Q (恢复图形状态)包络,因此其中当前变换矩阵的变化不影响此后的任何指令。
为了完全不受现有内容流指令的此类图形状态变化的影响,您应该自己将现有的未知内容包装在另一个 q ... Q信封.
实际上有一个 PdfCanvas
构造函数为您做这件事;只需替换
PdfCanvas canvas=new PdfCanvas(page.newContentStreamAfter(),page.getResources(),pdfDoc);
来自
PdfCanvas canvas=new PdfCanvas(page, true);
另请参阅该构造函数的 JavaDocs:
/**
* 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 层包裹的嵌套限制。