PdfDocument implements IEventDispatcher, Closeable, Serializable { @Override public void close() { if (closed) { return; } isClosing = true; try { if (writer != null) { if (catalog.isFlushed()) { throw new PdfException(PdfException.CannotCloseDocumentWithAlreadyFlushedPdfCatalog); } updateProducerInInfoDictionary(); updateXmpMetadata(); if (pdfVersion.compareTo(PdfVersion.PDF_2_0) >= 0) { for (PdfName deprecatedKey : PdfDocumentInfo.PDF20_DEPRECATED_KEYS) { info.getPdfObject().remove(deprecatedKey); } } if (getXmpMetadata() != null) { PdfStream xmp = catalog.getPdfObject().getAsStream(PdfName.Metadata); if (isAppendMode() && xmp != null && !xmp.isFlushed() && xmp.getIndirectReference() != null) { xmp.setData(xmpMetadata); xmp.setModified(); } else { xmp = (PdfStream) new PdfStream().makeIndirect(this); xmp.getOutputStream().write(xmpMetadata); catalog.getPdfObject().put(PdfName.Metadata, xmp); catalog.setModified(); } xmp.put(PdfName.Type, PdfName.Metadata); xmp.put(PdfName.Subtype, PdfName.XML); if (writer.crypto != null && !writer.crypto.isMetadataEncrypted()) { PdfArray ar = new PdfArray(); ar.add(PdfName.Crypt); xmp.put(PdfName.Filter, ar); } } checkIsoConformance(); PdfObject crypto = null; Set<PdfIndirectReference> forbiddenToFlush = new HashSet<>(); if (properties.appendMode) { if (structTreeRoot != null) { tryFlushTagStructure(true); } if (catalog.isOCPropertiesMayHaveChanged() && catalog.getOCProperties(false).getPdfObject().isModified()) { catalog.getOCProperties(false).flush(); } if (catalog.pageLabels != null) { catalog.put(PdfName.PageLabels, catalog.pageLabels.buildTree()); } for (Map.Entry<PdfName, PdfNameTree> entry : catalog.nameTrees.entrySet()) { PdfNameTree tree = entry.getValue(); if (tree.isModified()) { ensureTreeRootAddedToNames(tree.buildTree().makeIndirect(this), entry.getKey()); } } PdfObject pageRoot = catalog.getPageTree().generateTree(); if (catalog.getPdfObject().isModified() || pageRoot.isModified()) { catalog.put(PdfName.Pages, pageRoot); catalog.getPdfObject().flush(false); } if (info.getPdfObject().isModified()) { info.getPdfObject().flush(false); } flushFonts(); if (writer.crypto != null) { assert reader.decrypt.getPdfObject() == writer.crypto.getPdfObject() : "Conflict with source encryption"; crypto = reader.decrypt.getPdfObject(); if (crypto.getIndirectReference() != null) { forbiddenToFlush.add(crypto.getIndirectReference()); } } writer.flushModifiedWaitingObjects(forbiddenToFlush); for (int i = 0; i < xref.size(); i++) { PdfIndirectReference indirectReference = xref.get(i); if (indirectReference != null && !indirectReference.isFree() && indirectReference.checkState(PdfObject.MODIFIED) && !indirectReference.checkState(PdfObject.FLUSHED) && !forbiddenToFlush.contains(indirectReference)) { indirectReference.setFree(); } } } else { if (catalog.isOCPropertiesMayHaveChanged()) { catalog.getPdfObject().put(PdfName.OCProperties, catalog.getOCProperties(false).getPdfObject()); catalog.getOCProperties(false).flush(); } if (catalog.pageLabels != null) { catalog.put(PdfName.PageLabels, catalog.pageLabels.buildTree()); } catalog.getPdfObject().put(PdfName.Pages, catalog.getPageTree().generateTree()); for (Map.Entry<PdfName, PdfNameTree> entry : catalog.nameTrees.entrySet()) { PdfNameTree tree = entry.getValue(); if (tree.isModified()) { ensureTreeRootAddedToNames(tree.buildTree().makeIndirect(this), entry.getKey()); } } for (int pageNum = 1; pageNum <= getNumberOfPages(); pageNum++) { getPage(pageNum).flush(); } if (structTreeRoot != null) { tryFlushTagStructure(false); } catalog.getPdfObject().flush(false); info.getPdfObject().flush(false); flushFonts(); if (writer.crypto != null) { crypto = writer.crypto.getPdfObject(); crypto.makeIndirect(this); forbiddenToFlush.add(crypto.getIndirectReference()); } writer.flushWaitingObjects(forbiddenToFlush); for (int i = 0; i < xref.size(); i++) { PdfIndirectReference indirectReference = xref.get(i); if (indirectReference != null && !indirectReference.isFree() && !indirectReference.checkState(PdfObject.FLUSHED) && !forbiddenToFlush.contains(indirectReference)) { PdfObject object; if (isFlushUnusedObjects() && !indirectReference.checkState(PdfObject.ORIGINAL_OBJECT_STREAM) && (object = indirectReference.getRefersTo(false)) != null) { object.flush(); } else { indirectReference.setFree(); } } } } writer.crypto = null; if (!properties.appendMode && crypto != null) { crypto.flush(false); } trailer.put(PdfName.Root, catalog.getPdfObject()); trailer.put(PdfName.Info, info.getPdfObject()); PdfObject fileId = PdfEncryption.createInfoId(ByteUtils.getIsoBytes(originalDocumentId.getValue()), ByteUtils.getIsoBytes(modifiedDocumentId.getValue())); xref.writeXrefTableAndTrailer(this, fileId, crypto); writer.flush(); for (ICounter counter : getCounters()) { counter.onDocumentWritten(writer.getCurrentPos()); } } catalog.getPageTree().clearPageRefs(); removeAllHandlers(); } catch (IOException e) { throw new PdfException(PdfException.CannotCloseDocument, e, this); } finally { if (writer != null && isCloseWriter()) { try { writer.close(); } catch (Exception e) { Logger logger = LoggerFactory.getLogger(PdfDocument.class); logger.error(LogMessageConstant.PDF_WRITER_CLOSING_FAILED, e); } } if (reader != null && isCloseReader()) { try { reader.close(); } catch (Exception e) { Logger logger = LoggerFactory.getLogger(PdfDocument.class); logger.error(LogMessageConstant.PDF_READER_CLOSING_FAILED, e); } } } closed = true; } PdfDocument(PdfReader reader);  PdfDocument(PdfReader reader, DocumentProperties properties);  PdfDocument(PdfWriter writer);  PdfDocument(PdfWriter writer, DocumentProperties properties);  PdfDocument(PdfReader reader, PdfWriter writer);  PdfDocument(PdfReader reader, PdfWriter writer, StampingProperties properties); void setXmpMetadata(XMPMeta xmpMeta, SerializeOptions serializeOptions); void setXmpMetadata(XMPMeta xmpMeta); byte[] getXmpMetadata(); byte[] getXmpMetadata(boolean createNew); PdfObject getPdfObject(int objNum); int getNumberOfPdfObjects(); PdfPage getPage(int pageNum); PdfPage getPage(PdfDictionary pageDictionary); PdfPage getFirstPage(); PdfPage getLastPage(); PdfPage addNewPage(); PdfPage addNewPage(PageSize pageSize); PdfPage addNewPage(int index); PdfPage addNewPage(int index, PageSize pageSize); PdfPage addPage(PdfPage page); PdfPage addPage(int index, PdfPage page); int getNumberOfPages(); int getPageNumber(PdfPage page); int getPageNumber(PdfDictionary pageDictionary); boolean movePage(PdfPage page, int insertBefore); void movePage(int pageNumber, int insertBefore); boolean removePage(PdfPage page); void removePage(int pageNum); PdfDocumentInfo getDocumentInfo(); PdfString getOriginalDocumentId(); PdfString getModifiedDocumentId(); PageSize getDefaultPageSize(); void setDefaultPageSize(PageSize pageSize); @Override void addEventHandler(String type, IEventHandler handler); @Override void dispatchEvent(com.itextpdf.kernel.events.Event event); @Override void dispatchEvent(com.itextpdf.kernel.events.Event event, boolean delayed); @Override boolean hasEventHandler(String type); @Override void removeEventHandler(String type, IEventHandler handler); @Override void removeAllHandlers(); PdfWriter getWriter(); PdfReader getReader(); boolean isAppendMode(); PdfIndirectReference createNextIndirectReference(); PdfVersion getPdfVersion(); PdfCatalog getCatalog(); @Override void close(); boolean isClosed(); boolean isTagged(); PdfDocument setTagged(); PdfStructTreeRoot getStructTreeRoot(); int getNextStructParentIndex(); TagStructureContext getTagStructureContext(); List<PdfPage> copyPagesTo(int pageFrom, int pageTo, PdfDocument toDocument, int insertBeforePage); List<PdfPage> copyPagesTo(int pageFrom, int pageTo, PdfDocument toDocument, int insertBeforePage, IPdfPageExtraCopier copier); List<PdfPage> copyPagesTo(int pageFrom, int pageTo, PdfDocument toDocument); List<PdfPage> copyPagesTo(int pageFrom, int pageTo, PdfDocument toDocument, IPdfPageExtraCopier copier); List<PdfPage> copyPagesTo(List<Integer> pagesToCopy, PdfDocument toDocument, int insertBeforePage); List<PdfPage> copyPagesTo(List<Integer> pagesToCopy, PdfDocument toDocument, int insertBeforePage, IPdfPageExtraCopier copier); List<PdfPage> copyPagesTo(List<Integer> pagesToCopy, PdfDocument toDocument); List<PdfPage> copyPagesTo(List<Integer> pagesToCopy, PdfDocument toDocument, IPdfPageExtraCopier copier); void flushCopiedObjects(PdfDocument sourceDoc); boolean isCloseReader(); void setCloseReader(boolean closeReader); boolean isCloseWriter(); void setCloseWriter(boolean closeWriter); boolean isFlushUnusedObjects(); void setFlushUnusedObjects(boolean flushUnusedObjects); PdfOutline getOutlines(boolean updateOutlines); void initializeOutlines(); void addNamedDestination(String key, PdfObject value); List<PdfIndirectReference> listIndirectReferences(); PdfDictionary getTrailer(); void addOutputIntent(PdfOutputIntent outputIntent); void checkIsoConformance(Object obj, IsoKey key); @Deprecated void checkIsoConformance(Object obj, IsoKey key, PdfResources resources); void checkIsoConformance(Object obj, IsoKey key, PdfResources resources, PdfStream contentStream); void checkShowTextIsoConformance(CanvasGraphicsState gState, PdfResources resources); void addFileAttachment(String key, PdfFileSpec fs); void addAssociatedFile(String description, PdfFileSpec fs); PdfArray getAssociatedFiles(); PdfEncryptedPayloadDocument getEncryptedPayloadDocument(); void setEncryptedPayload(PdfFileSpec fs); String[] getPageLabels(); boolean hasOutlines(); void setUserProperties(boolean userProperties); PdfFont getFont(PdfDictionary dictionary); PdfFont getDefaultFont(); PdfFont addFont(PdfFont font); boolean registerProduct(final ProductInfo productInfo); FingerPrint getFingerPrint(); PdfFont findFont(String fontProgram, String encoding);  }
@Test public void testImageCompressLevel() throws IOException { byte[] b = ImageDataFactory.create(sourceFolder + "berlin2013.jpg").getData(); com.itextpdf.io.source.ByteArrayOutputStream image = new com.itextpdf.io.source.ByteArrayOutputStream(); image.assignBytes(b, b.length); ByteArrayOutputStream byteArrayStream1 = new com.itextpdf.io.source.ByteArrayOutputStream(); DeflaterOutputStream zip = new DeflaterOutputStream(byteArrayStream1, 9); image.writeTo(zip); ByteArrayOutputStream byteArrayStream2 = new com.itextpdf.io.source.ByteArrayOutputStream(); DeflaterOutputStream zip2 = new DeflaterOutputStream(byteArrayStream2, -1); image.writeTo(zip2); Assert.assertTrue(byteArrayStream1.size() == byteArrayStream2.size()); zip.close(); zip2.close(); }