PDFBOX 2.0: How can I scale large page sizes to letter?
Setting a new MediaBox size is indeed enough to push the scaled content stream inside the smaller page. Comparing the dividends of source width/height and target width/height allows me to find a suitable scaling factor to apply to both sides, maintaining aspect ratio. The resulting margins from the pages themselves look acceptable for our use so I'm not worrying about fine control now, just setting the paper to 0 margin and letting it go. SHRINK_TO_FIT in the PDFPrintable constructor doesn't seem to be doing anything, I'm not sure what circumstances it has an effect under.
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) {
}
}
}
Set PDF to print with no scaling
Scaling is controlled by the PDF application - it is not set in the file.
GhostScript (PostScript): Printer cut- off borders when scaling down from A* to A4
It sounds like your printer has a non-printable area. This is not uncommon, the paper handling needs to hold the paper while its being printed, and this can lead to some areas of the media not being printable.
If your content reaches to the edge of the media, its possible that the printer simple cannot print there, resulting in the content being cropped.
It is entirely possible to have ps2write drop the media content to a smaller size, but you can't have it (automatically) scale down and also shift the content location, because the content is fitted to the media size.
However, the FitPage mechanism doesn't look at the content, just the media size requests. So if the input requests A3 and the selected media is A4 (and fixed) then a scale factor is applied to scale the content to the required media size (and the media request for A3 is ignored).
So what you could do is leave the code you have as it is as present, but add a BeginPage or Install procedure which uses the scale operator to further reduce the size of marks on the page, and the translate operator to move the origin slightly so that the final content is centered.
Something like (example only, untested):
<<
/BeginPage {
0.95 0.95 scale
16 20 translate
}
>> setpagedevice
By the way, you do realise Ghostscript is licenced under the AGPL ?
Also, I'd very strongly recommend that you do not use the -g and -r switches, but instead simply use -dDEVICEWIDTHPOINTS and -dDEVICEHEIGHTPOINTS to alter the media size.
The -g switch works in pixels, but high level output devices (eg pdfwrite and ps2write) don't emit pixels, they write high level vector objects. However, due to differences in the PostScript and PDF graphics models, some elements do need to be rendered to images and enclosed in that fashion in the PostScript output. By setting the resolution to 300 you are fixing the resolution at which those elements (eg pages containing transparency) are rendered. I'd suggest that you don't do so, unless you are working in a very tightly controlled workflow and know the resolution of the final output.
By using the DEVICEHEIGHTPOINTS and DEVICEWIDTHPOINTS switches you can control the media size without reference to the resolution. Note that in PostScript (and PDF) 1 point = 1/72 inch.
Scale HTML proportionally to fit exactly to PDF A4 size
Your background image is not exactly high-res, this won't look great in print.
I don't know wkhtmltopdf itself, but your body already has absolute dimensions set (in inches). This is probably the problem. Your body has a max size, the content has an absolute size too (given due to the background image pixel dimensions).
This is not a good starting point for html-to-print transformaions, and PDF is essentially print.
what to do (intermediate)
- remove any size restrictions from body
- wkhtml... has a switch called
zoom
,1.5
should be an appropriate value to fill the page - use page-size a4
what to do (the "right" way)
- remove size restrictions from body
- build the background borders (the black ones) with html elements and css styling
- refrain from defining "width" rules for those. You will only have to define a "width" once, all other widths should be set to "auto".
- heights will prove troublesome, because divs are only as high as their content requires. But setting height: 100% does not respect border and margin sizes.
- that yellow cross could be designed in css too, or a much higher resolution png/jpeg
- Use only "real" dimensions. That means do not use pixels, use points, inches, or mm. You can use % values, but make sure those are % values of real dimensions (that means that at some point a parent element has a real dimension)
Scale image in page by adding margins to PDF with Ghostscript
You can look at the code presented in my answer here. That shows you how to rescale the content of a PDF file to a different media size, and how to reposition the scaled content on the nominal output medium.
I'm rather surprised that -c "<>setpagedevice" -f
doesn't simply produce an error, since that's not valid PostScript.
[edit]
OK so you either need to do two passes or do the calculation of the scale yourself.
In the two pass model you first apply the scaling, which will get you a PDF file where the content still fills the page, but the page has been resized to the smaller dimensions. You then run it with the translation and the desired final media size, but don't set FitPage.
To do the scaling yourself you would need to add the scale to the BeginPage command instead of having Ghostscript do it for you. That means you are going to have to calculate the scale factors yourself.
The parameter to the setpagedevice operator would look something like :
<</BeginPage {0.5 0.5 scale 200 0 translate}>> setpagedevice
That will scale the content down by 50% in each direction, and move the origin by 100 points to the right. Obviously the translate values will depend on the scale factor and the size of the original and scaled media. I would try this to check it, but you haven't supplied an example PDF file to test.
iTextSharp Scaling image to be full-page
If you're determined to do it empirically, then take print a page with your code as is that scales to page border such that the image would paint black in the first half inch of margin, if it could go to the edge. Measure the distance from each edge to black in inches and divide each by 72.0.
Let's name them: lm, rm, tm, bm (left right top bottom margins.
Dim pageWidth = document.PageSize.Width - (lm + rm);
Dim pageHeight = document.PageSize.Height - (bm + tm);
Content.SetAbsolutePosition(lm, bm);
Content.ScaleToFit(pageWidth, pageHeight);
Document.Add(Content)
Related Topics
Simplest Way to Build Dotnet Sdk Project Requiring Net461 on Macos
Pyinstaller on 32-Bit Linux - Importerror: The 'six' Package Is Required
Linux: Find a List of Files in a Dictionary Recursively
How Does The 64 Bit Linux Kernel Kick Off a 32 Bit Process from an Elf
Diff Files Comparing Only First N Characters of Each Line
Libv4L2: Error Turning on Stream: No Space Left on Device
Powershell Connecting from a Linux Client to a Windows Remote
How to Successfully Use Rdap Protocol Instead of Whois
Linux Postfix/Dovecot 554 Relay Access Denied
How to Send a Mail with a Message in Unix Script
Shipping Gnu/Linux Firefox Plugin with Shared Libraries (For Installation with No Root Access)
Firefox Not Closing After Selenium Tests Are Run
Installing Ffmpeg on Amazon Linux - Cpp, Gcc & Libstdc++ Dependancies
Cross-Compilation to X86_64-Unknown-Linux-Gnu Fails on MAC Osx
How to Install Docker 1.9+ in Centos 6.5
How to Set Folder Permissions for a Particular Container on Elastic Beanstalk