danfickle / danfickle/openhtmltopdf
Caching and Reuse of PDFormXObject (embedded pdf via img tag)
- Dominant language
- Java
- Stars
- 2.2k
- Forks
- 423
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
we are rendering pdfs with multiple pages where the header of each page contains a logo. This logo comes from another pdf file. Embedding this logo.pdf via img tag works well, but the resulting PDF file grows a lot with each page, because the logo is embedded as a new XObject instance again and again.
When i looked at the code i understood that no further manipulation is done to the PDFormXObject after it has been created until it is added to the pdf dictionary.
Therefore i added a little cache so that pdfbox will receive the same PDFormXObject instance for a specified src url + page and will recognize that this element is already part of the pdf dictionary and will reuse the already existing object.
Here is my code example. For me this works and file size is way smaller. Does anyone know if this might not be a good idea?
This code is in com.openhtmltopdf.pdfboxout.PdfBoxPDFReplacedElement
See the use of pdfCache map.
```java
private static Map pdfCache = new HashMap<>();
public static PdfBoxPDFReplacedElement create(PDDocument target, byte[] pdfBytes, Element e, Box box, CssContext ctx, SharedContext shared) {
try (PDDocument srcDocument = PDDocument.load(pdfBytes)){
int pageNo = parsePage(e);
if (pageNo >= srcDocument.getNumberOfPages()) {
XRLog.log(Level.WARNING, LogMessageId.LogMessageId0Param.LOAD_PAGE_DOES_NOT_EXIST_FOR_PDF_IN_IMG_TAG);
return null;
}
PDPage page = srcDocument.getPage(pageNo);
float conversion = 96f / 72f;
float width = page.getMediaBox().getWidth() * shared.getDotsPerPixel() * conversion;
float height = page.getMediaBox().getHeight() * shared.getDotsPerPixel() * conversion;
LayerUtility util = new LayerUtility(target);
String cacheKey = e.getAttribute("src") + pageNo;
PDFormXObject formXObject = pdfCache.get(cacheKey);
if (formXObject == null){
formXObject = util.importPageAsForm(srcDocument, page);
pdfCache.put(cacheKey, formXObject);
}
return new PdfBoxPDFReplacedElement(formXObject, e, box, ctx, shared, width, height);
} catch (InvalidPasswordException e1) {
XRLog.log(Level.WARNING, LogMessageId.LogMessageId0Param.EXCEPTION_TRIED_TO_OPEN_A_PASSWORD_PROTECTED_DOCUMENT_AS_SRC_FOR_IMG, e1);
} catch (IOException e1) {
XRLog.log(Level.WARNING, LogMessageId.LogMessageId0Param.EXCEPTION_COULD_NOT_READ_PDF_AS_SRC_FOR_IMG, e1);
}
return null;
}
```
And a question on the side: Why are normale images like png automatically reused?
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.