PDFBOX 2.0:如何将大页面尺寸缩放为字母?
PDFBOX 2.0: How can I scale large page sizes to letter?
我正在使用 pdfbox 2.0.21 来(物理地)打印可能具有混合页面尺寸的 PDF 文件,包括非标准尺寸,例如 8.7"x11.3",它可以在不缩放的情况下打印在合法尺寸或更大的纸张上。 pdf 由许多不同的员工以不同的方式创建(Acrobat DC,从 Word 保存,打印到 pdf,由我们的文档系统生成......)并发送给我的团队打印和邮寄。该卷不允许我们单独检查它们,最终我们将我们的应用程序指向一个文件夹,它会打印那里的所有内容。我更愿意创建一个 PrinterJob 或 PDFPageable 来根据需要自动缩放所有页面,但无法让它工作。
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
Paper paper = new Paper();
Paper.setSize(612, 792); // letter size
paper.setImageableArea(36, 36, paper.getWidth() - 72, paper.getHeight() - 72); // 0.5in margins
PageFormat format = new PageFormat();
format.setPaper(paper);
PDFPageable pageable = new PDFPageable(pdf);
//doesn't scale down pages
//printer will ask for legal and cutoff bottom when forced to use letter
pageable.append(new PDFPrintable(pdf, Scaling.SCALE_TO_FIT), format);
job.setPageable(pageable);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
我尝试遍历每个页面并直接缩小任何大于字母的内容,但以令人费解的方式在页面上四处移动内容,但失败了。
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
PDFPageable pageable = new PDFPageable(pdf);
PDPageTree tree = pdf.getDocumentCatalog().getPages();
Iterator<PDPage> iterator = tree.iterator();
while (iterator.hasNext()) {
PDPage page = iterator.next();
if (page.getMediaBox().getWidth() !=612 || page.getMediaBox().getHeight() != 792) {
PDPageContentStream contentStream = new PDPageContentStream(pdf, page,
PDPageContentStream.AppendMode.PREPEND, false);
//these are the wrong scaling factors but they do shrink oversized pages
//however the shrunk content is moved far down the page and runs off the bottom
//printer still asks for legal and cuts off bottom when forced to use letter
//edit: these floats should probably be smaller
//to account for margins, but the result is still
//offset significantly below the upper left
contentStream.transform(Matrix.getScaleInstance(612f / page.getMediaBox().getWidth(),
792f / page.getMediaBox().getHeight()));
//round figures, a large positive Y moves the content upward
//but not cleanly to the upper left
//whereas a large negative Y moves the content down and cuts off the bottom
//but does print on letter without the printer complaining about size
contentStream.transform(Matrix.getTransformInstance(0f, 250f);
contentStream.close();
}
}
job.setPageable(pageable);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
使用具有 MediaName、MediaSizeName 和 MediaTray 常量的各种组合的属性集也导致没有减少,打印机停止并要求 legal 纸张,并在强制信纸时切掉底部。
如何使用 pdfbox 2.0 在打印时将单个超大页面正确缩小为字母大小?
编辑:通过将页面的 MediaBox 设置为 PDRectangle.LETTER,我可以确保打印机不会要求提供合法纸张,并且左下角的内容流源可见。现在只需要使用正确的数学方法来获得缩放因子并可能影响边距,使用 ImageableArea 或 CropBox?
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
PDFPageable pageable = new PDFPageable(pdf);
PDPageTree tree = pdf.getDocumentCatalog().getPages();
Iterator<PDPage> iterator = tree.iterator();
while (iterator.hasNext()) {
PDPage page = iterator.next();
if (page.getMediaBox().getWidth() !=612 || page.getMediaBox().getHeight() != 792) {
PDPageContentStream contentStream = new PDPageContentStream(pdf, page,
PDPageContentStream.AppendMode.PREPEND, false);
//these are the wrong scaling factors but they do shrink oversized pages
contentStream.transform(Matrix.getScaleInstance(0.5f,0.5f));
page.setMediaBox(PDRectangle.LETTER); // make the page letter size with shrunk content origin in lower left
contentStream.close();
}
}
job.setPageable(pageable);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
设置新的 MediaBox 大小确实足以将缩放后的内容流推入较小的页面。比较源 width/height 和目标 width/height 的红利让我找到一个合适的比例因子应用于双方,保持纵横比。页面本身产生的边距看起来可以接受我们的使用,所以我现在不担心精细控制,只需将纸张设置为 0 边距并放手。 SHRINK_TO_FIT PDFPrintable 的构造函数中好像没有做任何事情,我不确定它在什么情况下会起作用。
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
PDPageTree tree = pdf.getDocumentCatalog().getPages();
Iterator<PDPage> iterator = tree.iterator();
while (iterator.hasNext()) {
PDPage page = iterator.next();
if (page.getMediaBox().getWidth() > 612 || page.getMediaBox().getHeight() > 792) {
float fWidth = 612f / page.getMediaBox().getWidth();
float fHeight = 792f / page.getMediaBox().getHeight();
float factor = 0f;
if (fWidth > fHeight) {
factor = fHeight;
} else {
factor = fWidth;
}
PDPageContentStream contentStream = new PDPageContentStream(pdf, page,
PDPageContentStream.AppendMode.PREPEND, false);
contentStream.transform(Matrix.getScaleInstance(factor, factor));
contentStream.close();
page.setMediaBox(PDRectangle.LETTER);
}
}
Paper paper = new Paper();
paper.setSize(612, 792);
paper.setImageableArea(0, 0, 612, 792);
PageFormat pageFormat = new PageFormat();
pageFormat.setPaper(paper);
Book book = new Book();
book.append(new PDFPrintable(pdf, Scaling.SHRINK_TO_FIT), pageFormat, pdf.getNumberOfPages());
job.setPageable(book);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
我正在使用 pdfbox 2.0.21 来(物理地)打印可能具有混合页面尺寸的 PDF 文件,包括非标准尺寸,例如 8.7"x11.3",它可以在不缩放的情况下打印在合法尺寸或更大的纸张上。 pdf 由许多不同的员工以不同的方式创建(Acrobat DC,从 Word 保存,打印到 pdf,由我们的文档系统生成......)并发送给我的团队打印和邮寄。该卷不允许我们单独检查它们,最终我们将我们的应用程序指向一个文件夹,它会打印那里的所有内容。我更愿意创建一个 PrinterJob 或 PDFPageable 来根据需要自动缩放所有页面,但无法让它工作。
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
Paper paper = new Paper();
Paper.setSize(612, 792); // letter size
paper.setImageableArea(36, 36, paper.getWidth() - 72, paper.getHeight() - 72); // 0.5in margins
PageFormat format = new PageFormat();
format.setPaper(paper);
PDFPageable pageable = new PDFPageable(pdf);
//doesn't scale down pages
//printer will ask for legal and cutoff bottom when forced to use letter
pageable.append(new PDFPrintable(pdf, Scaling.SCALE_TO_FIT), format);
job.setPageable(pageable);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
我尝试遍历每个页面并直接缩小任何大于字母的内容,但以令人费解的方式在页面上四处移动内容,但失败了。
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
PDFPageable pageable = new PDFPageable(pdf);
PDPageTree tree = pdf.getDocumentCatalog().getPages();
Iterator<PDPage> iterator = tree.iterator();
while (iterator.hasNext()) {
PDPage page = iterator.next();
if (page.getMediaBox().getWidth() !=612 || page.getMediaBox().getHeight() != 792) {
PDPageContentStream contentStream = new PDPageContentStream(pdf, page,
PDPageContentStream.AppendMode.PREPEND, false);
//these are the wrong scaling factors but they do shrink oversized pages
//however the shrunk content is moved far down the page and runs off the bottom
//printer still asks for legal and cuts off bottom when forced to use letter
//edit: these floats should probably be smaller
//to account for margins, but the result is still
//offset significantly below the upper left
contentStream.transform(Matrix.getScaleInstance(612f / page.getMediaBox().getWidth(),
792f / page.getMediaBox().getHeight()));
//round figures, a large positive Y moves the content upward
//but not cleanly to the upper left
//whereas a large negative Y moves the content down and cuts off the bottom
//but does print on letter without the printer complaining about size
contentStream.transform(Matrix.getTransformInstance(0f, 250f);
contentStream.close();
}
}
job.setPageable(pageable);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
使用具有 MediaName、MediaSizeName 和 MediaTray 常量的各种组合的属性集也导致没有减少,打印机停止并要求 legal 纸张,并在强制信纸时切掉底部。
如何使用 pdfbox 2.0 在打印时将单个超大页面正确缩小为字母大小?
编辑:通过将页面的 MediaBox 设置为 PDRectangle.LETTER,我可以确保打印机不会要求提供合法纸张,并且左下角的内容流源可见。现在只需要使用正确的数学方法来获得缩放因子并可能影响边距,使用 ImageableArea 或 CropBox?
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
PDFPageable pageable = new PDFPageable(pdf);
PDPageTree tree = pdf.getDocumentCatalog().getPages();
Iterator<PDPage> iterator = tree.iterator();
while (iterator.hasNext()) {
PDPage page = iterator.next();
if (page.getMediaBox().getWidth() !=612 || page.getMediaBox().getHeight() != 792) {
PDPageContentStream contentStream = new PDPageContentStream(pdf, page,
PDPageContentStream.AppendMode.PREPEND, false);
//these are the wrong scaling factors but they do shrink oversized pages
contentStream.transform(Matrix.getScaleInstance(0.5f,0.5f));
page.setMediaBox(PDRectangle.LETTER); // make the page letter size with shrunk content origin in lower left
contentStream.close();
}
}
job.setPageable(pageable);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}
设置新的 MediaBox 大小确实足以将缩放后的内容流推入较小的页面。比较源 width/height 和目标 width/height 的红利让我找到一个合适的比例因子应用于双方,保持纵横比。页面本身产生的边距看起来可以接受我们的使用,所以我现在不担心精细控制,只需将纸张设置为 0 边距并放手。 SHRINK_TO_FIT PDFPrintable 的构造函数中好像没有做任何事情,我不确定它在什么情况下会起作用。
public class PDPrn {
public static void main(String[] args) {
try (PDDocument pdf = PDDocument.load(new File("foo.pdf"))) {
PrinterJob job = PrinterJob.getPrinterJob();
PDPageTree tree = pdf.getDocumentCatalog().getPages();
Iterator<PDPage> iterator = tree.iterator();
while (iterator.hasNext()) {
PDPage page = iterator.next();
if (page.getMediaBox().getWidth() > 612 || page.getMediaBox().getHeight() > 792) {
float fWidth = 612f / page.getMediaBox().getWidth();
float fHeight = 792f / page.getMediaBox().getHeight();
float factor = 0f;
if (fWidth > fHeight) {
factor = fHeight;
} else {
factor = fWidth;
}
PDPageContentStream contentStream = new PDPageContentStream(pdf, page,
PDPageContentStream.AppendMode.PREPEND, false);
contentStream.transform(Matrix.getScaleInstance(factor, factor));
contentStream.close();
page.setMediaBox(PDRectangle.LETTER);
}
}
Paper paper = new Paper();
paper.setSize(612, 792);
paper.setImageableArea(0, 0, 612, 792);
PageFormat pageFormat = new PageFormat();
pageFormat.setPaper(paper);
Book book = new Book();
book.append(new PDFPrintable(pdf, Scaling.SHRINK_TO_FIT), pageFormat, pdf.getNumberOfPages());
job.setPageable(book);
try {
job.print();
} catch (PrinterException pe) {
}
pdf.close();
} catch (IOException ioe) {
}
}
}