我正在尝试在PDF页面上叠加图像。当我尝试使用adobe acrobat并选择从顶部和左侧的垂直距离等于0时,然后在所需位置正确覆盖图像。
我正在尝试使用iText API实现相同功能,但似乎无法将图像定位在pdf上的正确位置。
位置的值是跟踪和错误。 pdf的大小是612X792,图像的大小是1699.0x817.0,所以我缩放图像以适合pdf大小。
图像的左侧和pdf正确对齐,但顶部有问题。我尝试了所有的值,并以某种方式792/2 + 100匹配,但如果我得到一个不同的PDF或图像再次将改变。
不知何故,adobe reader能够做到这一点。有没有办法在iText或任何其他库中对齐左侧和顶部。
pdf是从其他来源生成的现有pdf。
更新了源代码
public void manipulatePdfNoTransparency(String inputFileName,
String outputfileName, String overlayFilePath,
int altPage) throws IOException, DocumentException {
System.out.println("outputfileName :"+outputfileName);
PdfReader reader = new PdfReader(inputFileName);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputfileName));
stamper.setRotateContents(false);
// image watermark
Image img = Image.getInstance(overlayFilePath);
float yOffset=calculateYOffset(reader.getPageSize(1).getWidth(), reader.getPageSize(1)
.getHeight(),img.getWidth(),img.getHeight());
img.scaleToFit(reader.getPageSize(1).getWidth(), reader.getPageSize(1)
.getHeight());
Rectangle pagesize;
float x, y;
// loop over every page
//int i=1;
pagesize = reader.getPageSize(1);
x = (pagesize.getLeft() + pagesize.getRight()) / 2;
y = (pagesize.getTop() + pagesize.getBottom()) / 2;
img.setAbsolutePosition(0,yOffset);
for (int i = 1; i <= n; i = i + altPage) {
stamper.getUnderContent(i).addImage(img);
}
stamper.close();
reader.close();
System.out.println("File created at "+outputfileName);
}
public static float calculateYOffset(float pdfWidth,float pdfHeight, float originalImageWidth,float originalImageHeight) {
// size of image 1699.0x817.0
// size of pdf 612X792
//This means that the scaled image has a height of 817 * (612/1699) = ca. 294.3 PDF coordinate system units.
System.out.println("pdfWidth : "+pdfWidth+ " pdfHeight : "+pdfHeight+" originalImageWidth : "+originalImageWidth+" originalImageHeight : "+originalImageHeight);
float scaledImageHeight = originalImageHeight*pdfWidth / originalImageWidth;
//The image shall be positioned on the page by putting its top left corner onto the top left corner of the page.
//Thus, the x coordinate of its lower left corner is 0, and the y coordinate of its lower left corner is
//the y coordinate of the upper left corner of the page minus the height of the scaled image,
//i.e. ca. 792 - 294.3 = 497.7.
float yOffset = pdfHeight-scaledImageHeight;
System.out.println("yoffset : "+ yOffset);
return yOffset;
}
答案 0 :(得分:1)
首先让我们来看看这一行:
img.scaleToFit(
reader.getPageSize(1).getWidth(),
reader.getPageSize(1).getHeight());
scaleToFit()
方法调整图像的大小,保持宽高比不变。你似乎忽略了这一点,所以让我举一个例子来说明保持宽高比的完整性。
假设您有一个用于测量400 x 600个用户单位的图像img400x600
,并且您将该图像缩放为适合200 x 10,000个用户单位的矩形:
img400x600.scaleToFit(200, 10000);
image400x600
的大小是多少?您似乎认为大小将是200 x 10,000,但这种假设是不正确的。图像的新大小为200 x 300,因为宽高比为width = 0.66666 * height
。
您抱怨使用scaleToFit()
时图像的大小不等于页面的大小,但如果图像的宽高比不同于图像的宽高比,则这是正常的。页。
如果您确实希望图片具有相同的页面大小,则需要使用scaleAbsolute()
方法:
img.scaleAbsolute(
reader.getPageSize(1).getWidth(),
reader.getPageSize(1).getHeight());
然而,这可能会导致图像失真,因为scaleAbsolute()
并不尊重宽高比。例如:我见过开发人员在人物肖像上使用scaleAbsolute()
,结果是这些人的照片变得丑陋;他们的头部变得非常肥胖,或者根据长宽比的不同而变得非常薄。
现在让我们来看看这一行:
img.setAbsolutePosition(0,y+100);
这是一条非常奇怪的路线。您假设左下角的x
坐标为0
;我了解y + 100
是通过反复试验获得的。
让我们看看官方文档中有关定义添加到现有PDF文档的对象的偏移量的内容。有关此主题的几个常见问题项目:
您目前只查看/MediaBox
的值(使用getPageSize()
方法获取此值),并忽略/CropBox
(如果它存在)。< / p>
如果我是你,我会这样做:
Rectangle pageSize = reader.getCropBox(pageNumber);
if (pageSize == null)
pageSize = reader.getPageSize(pageNumber);
获得pageSize后,您需要在添加内容时添加考虑偏移量。原点可能与(0, 0)
坐标不一致:
img.setAbsolutePosition(pageSize.getLeft(), pageSize.getBottom());
正如您所看到的:不需要反复试验。您可以计算所需的所有值。
<强>更新强>
在评论中,@ mkl澄清@Gagan希望图像完全符合高度。这很容易实现。
如果需要保留纵横比,那么足以按比例缩放高度:
img.scaleToFit(100000f, pageSize.getHeight());
在这种情况下,图像不会变形,但部分图像将不可见。
如果不需要保留纵横比,可以像这样缩放图像:
img.scaleAbsolute(pageSize.getWidth(), pageSize.getHeight());
如果这个仍然没有回答这个问题,我建议OP澄清一下不清楚数学的含义。
答案 1 :(得分:0)
在对我提到的问题的评论中
以某种方式792/2 + 100匹配此 - 实际上是大约1.7。你只需要非常简单的数学来计算它。
并且OP回复了
当你说它被1.7关闭时,需要简单的数学来计算它。你能不能让我知道数学以及你是如何到达1.7的。
这个答案解释了数学。
从OP的问题和后来的评论我推断出这些要求:
在目前的情况下, pdf的大小为612X792,图像的大小为1699.0x817.0 。此外,OP的评论意味着页面的左下角实际上是坐标系的原点。
要缩放图像的水平范围以精确适合页面,必须按比例缩放612/1699。要缩放垂直范围以精确适合页面,必须按比例缩放792/817。为了使整个图像适合保持纵横比的页面,必须使用较小的比例因子612/1699。 OP就是这个
img.scaleToFit(reader.getPageSize(1).getWidth(),reader.getPageSize(1).getHeight());
,假设裁剪框与媒体框重合。
这意味着缩放图像的高度为817 *(612/1699)= ca. 294.3 PDF坐标系单位。
在PDF页面上定位图像时,通常会给出图像左下角的坐标。
图像应位于页面上,方法是将其左上角放在页面的左上角。因此,其左下角的 x 坐标为0,其左下角的 y 坐标为上部的 y 坐标页面左下角减去缩放图像的高度,即大约792 - 294.3 = 497.7。
因此,缩放后的图像应位于(0, 497.7)
。
通过试验和错误找到的数字对于 x 为0,中间高度对于 y 为100。中间高度是(792 + 0)/ 2 = 396.因此,他使用坐标(0, 496)
,其中(见上文)垂直偏离大约。 1.7。