为什么将某些 PDF 包含到输出 PDF 而不是其他 PDF 时出现失真?
Why am I getting distortion when including some PDFs into an output PDF, but not others?
我正在使用 PDFBox 版本 2.0.23 创建一个由多个输入 PDF 组成的输出 PDF。有时,多个输入 PDF 需要放在输出 PDF 的同一页上,所以我不能只将输入的页面添加到输出。
我遇到的问题是一些输入的 PDF 莫名其妙地扭曲了:它们似乎在 Y 轴上被拉伸了。
这是最小的可重现示例:
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.multipdf.LayerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
public class Main {
public static void main(String[] args) {
PDDocument d = new PDDocument();
LayerUtility layerUtility = new LayerUtility(d);
String[] paths = { "Automania.pdf", "Colonel.pdf" };
for (String p : paths) {
PDPage page = new PDPage(PDRectangle.LETTER);
d.addPage(page);
try (PDPageContentStream contents = new PDPageContentStream(d, page, PDPageContentStream.AppendMode.APPEND,
true)) {
PDDocument source = null;
source = PDDocument.load(new File(p));
PDFormXObject form = layerUtility.importPageAsForm(source, 0);
source.close();
contents.drawForm(form);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
d.save(new File("out.pdf"));
d.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Complete.");
}
}
Here is a sample 两个输入文件(Automania.pdf 和 Colonel.pdf)和输出(out.pdf);都在 public 域中。 Automania.pdf 被严重拉伤,而 colonel.pdf 没有受伤。这两个文件之间有什么不同导致失真,我该如何解决?
感谢@mkl 解决了这个问题!
问题是调用 importPageAsForm 在遇到 90 度和 270 度旋转时会扭曲所有内容,从而保持原始的、未旋转的纵横比。 @mkl 建议的快速修复是在导入之前将页面旋转设置为 0,然后手动应用旋转,效果很好。
此解决方案的代码如下,稍微更改为生成我们自己的输入文档而不是从文件加载它们。
package pdftest;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.multipdf.LayerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.util.Matrix;
public class Main {
public static void main(String[] args) {
PDDocument d = new PDDocument();
LayerUtility layerUtility = new LayerUtility(d);
for (int i = 0; i < 360; i += 90) {
PDPage page = new PDPage(PDRectangle.LETTER);
d.addPage(page);
try (PDPageContentStream contents = new PDPageContentStream(d, page, PDPageContentStream.AppendMode.APPEND,
true)) {
/* Generate Test Input Document */
PDDocument source = new PDDocument();
PDPage sourcePage = new PDPage(new PDRectangle(500, 200));
PDPageContentStream sourceStream = new PDPageContentStream(source, sourcePage);
// Draw text
sourceStream.beginText();
sourceStream.newLineAtOffset(sourcePage.getBBox().getUpperRightX() / 2, sourcePage.getBBox().getUpperRightY() / 2);
sourceStream.setFont(PDType1Font.TIMES_ROMAN, 12);
sourceStream.showText("This Way Up! " + i);
sourceStream.endText();
sourceStream.addRect(0, 0, sourcePage.getBBox().getUpperRightX(), sourcePage.getBBox().getUpperRightY());
sourceStream.setLineWidth(10);
sourceStream.stroke();
sourceStream.close();
source.addPage(sourcePage);
sourcePage.setRotation(i);
/* Place the Test Input Document into the Output Document */
// Rotations of 90 and 270 are distorted by importPageAsForm, so we remove them here
int rotation = sourcePage.getRotation();
switch (rotation) {
case 90:
case 270:
sourcePage.setRotation(0);
break;
default:
break;
}
PDFormXObject form = layerUtility.importPageAsForm(source, 0);
source.close();
// Re-add rotations of 90 and 270 now that we're past importPageAsForm.
PDRectangle viewBox = sourcePage.getBBox();
switch (rotation) {
case 90:
contents.transform(Matrix.getRotateInstance(Math.toRadians(-rotation), 0, viewBox.getWidth()));
break;
case 270:
contents.transform(Matrix.getRotateInstance(Math.toRadians(-rotation), viewBox.getHeight(), 0));
break;
default:
break;
}
contents.drawForm(form);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
d.save(new File("out.pdf"));
d.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Complete.");
}
}
我正在使用 PDFBox 版本 2.0.23 创建一个由多个输入 PDF 组成的输出 PDF。有时,多个输入 PDF 需要放在输出 PDF 的同一页上,所以我不能只将输入的页面添加到输出。
我遇到的问题是一些输入的 PDF 莫名其妙地扭曲了:它们似乎在 Y 轴上被拉伸了。
这是最小的可重现示例:
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.multipdf.LayerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
public class Main {
public static void main(String[] args) {
PDDocument d = new PDDocument();
LayerUtility layerUtility = new LayerUtility(d);
String[] paths = { "Automania.pdf", "Colonel.pdf" };
for (String p : paths) {
PDPage page = new PDPage(PDRectangle.LETTER);
d.addPage(page);
try (PDPageContentStream contents = new PDPageContentStream(d, page, PDPageContentStream.AppendMode.APPEND,
true)) {
PDDocument source = null;
source = PDDocument.load(new File(p));
PDFormXObject form = layerUtility.importPageAsForm(source, 0);
source.close();
contents.drawForm(form);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
d.save(new File("out.pdf"));
d.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Complete.");
}
}
Here is a sample 两个输入文件(Automania.pdf 和 Colonel.pdf)和输出(out.pdf);都在 public 域中。 Automania.pdf 被严重拉伤,而 colonel.pdf 没有受伤。这两个文件之间有什么不同导致失真,我该如何解决?
感谢@mkl 解决了这个问题!
问题是调用 importPageAsForm 在遇到 90 度和 270 度旋转时会扭曲所有内容,从而保持原始的、未旋转的纵横比。 @mkl 建议的快速修复是在导入之前将页面旋转设置为 0,然后手动应用旋转,效果很好。
此解决方案的代码如下,稍微更改为生成我们自己的输入文档而不是从文件加载它们。
package pdftest;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.multipdf.LayerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.util.Matrix;
public class Main {
public static void main(String[] args) {
PDDocument d = new PDDocument();
LayerUtility layerUtility = new LayerUtility(d);
for (int i = 0; i < 360; i += 90) {
PDPage page = new PDPage(PDRectangle.LETTER);
d.addPage(page);
try (PDPageContentStream contents = new PDPageContentStream(d, page, PDPageContentStream.AppendMode.APPEND,
true)) {
/* Generate Test Input Document */
PDDocument source = new PDDocument();
PDPage sourcePage = new PDPage(new PDRectangle(500, 200));
PDPageContentStream sourceStream = new PDPageContentStream(source, sourcePage);
// Draw text
sourceStream.beginText();
sourceStream.newLineAtOffset(sourcePage.getBBox().getUpperRightX() / 2, sourcePage.getBBox().getUpperRightY() / 2);
sourceStream.setFont(PDType1Font.TIMES_ROMAN, 12);
sourceStream.showText("This Way Up! " + i);
sourceStream.endText();
sourceStream.addRect(0, 0, sourcePage.getBBox().getUpperRightX(), sourcePage.getBBox().getUpperRightY());
sourceStream.setLineWidth(10);
sourceStream.stroke();
sourceStream.close();
source.addPage(sourcePage);
sourcePage.setRotation(i);
/* Place the Test Input Document into the Output Document */
// Rotations of 90 and 270 are distorted by importPageAsForm, so we remove them here
int rotation = sourcePage.getRotation();
switch (rotation) {
case 90:
case 270:
sourcePage.setRotation(0);
break;
default:
break;
}
PDFormXObject form = layerUtility.importPageAsForm(source, 0);
source.close();
// Re-add rotations of 90 and 270 now that we're past importPageAsForm.
PDRectangle viewBox = sourcePage.getBBox();
switch (rotation) {
case 90:
contents.transform(Matrix.getRotateInstance(Math.toRadians(-rotation), 0, viewBox.getWidth()));
break;
case 270:
contents.transform(Matrix.getRotateInstance(Math.toRadians(-rotation), viewBox.getHeight(), 0));
break;
default:
break;
}
contents.drawForm(form);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
d.save(new File("out.pdf"));
d.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Complete.");
}
}