All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.pdfbox.Overlay Maven / Gradle / Ivy

Go to download

The Apache PDFBox library is an open source Java tool for working with PDF documents.

There is a newer version: 3.0.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pdfbox;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdfwriter.COSWriter;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.Map;

/**
 * Overlay on document with another one.
* e.g. Overlay an invoice with your company layout
*
* How it (should) work:
* If the document has 10 pages, and the layout 2 the following is the result:
*
 * Document: 1234567890
 * Layout  : 1212121212
 * 
*
* * @author Mario Ivankovits ([email protected]) * @author Ben Litchfield * * @version $Revision: 1.7 $ */ public class Overlay { /** * @deprecated use the {@link COSName#XOBJECT} constant instead */ public static final COSName XOBJECT = COSName.XOBJECT; /** * @deprecated use the {@link COSName#PROC_SET} constant instead */ public static final COSName PROC_SET = COSName.PROC_SET; /** * @deprecated use the {@link COSName#EXT_G_STATE} constant instead */ public static final COSName EXT_G_STATE = COSName.EXT_G_STATE; private List layoutPages = new ArrayList(10); private PDDocument pdfOverlay; private PDDocument pdfDocument; private int pageCount = 0; private COSStream saveGraphicsStateStream; private COSStream restoreGraphicsStateStream; /** * This will overlay a document and write out the results.

* * usage: java org.apache.pdfbox.Overlay <overlay.pdf> <document.pdf> <result.pdf> * * @param args The command line arguments. * * @throws IOException If there is an error reading/writing the document. * @throws COSVisitorException If there is an error writing the document. */ public static void main( String[] args ) throws IOException, COSVisitorException { if( args.length != 3 ) { usage(); System.exit(1); } else { PDDocument overlay = null; PDDocument pdf = null; try { overlay = getDocument( args[0] ); pdf = getDocument( args[1] ); Overlay overlayer = new Overlay(); overlayer.overlay( overlay, pdf ); writeDocument( pdf, args[2] ); } finally { if( overlay != null ) { overlay.close(); } if( pdf != null ) { pdf.close(); } } } } private static void writeDocument( PDDocument pdf, String filename ) throws IOException, COSVisitorException { FileOutputStream output = null; COSWriter writer = null; try { output = new FileOutputStream( filename ); writer = new COSWriter( output ); writer.write( pdf ); } finally { if( writer != null ) { writer.close(); } if( output != null ) { output.close(); } } } private static PDDocument getDocument( String filename ) throws IOException { FileInputStream input = null; PDFParser parser = null; PDDocument result = null; try { input = new FileInputStream( filename ); parser = new PDFParser( input ); parser.parse(); result = parser.getPDDocument(); } finally { if( input != null ) { input.close(); } } return result; } private static void usage() { System.err.println( "usage: java -jar pdfbox-app-x.y.z.jar Overlay " ); } /** * Private class. */ private static class LayoutPage { private final COSBase contents; private final COSDictionary res; private final Map objectNameMap; /** * Constructor. * * @param contentsValue The contents. * @param resValue The resource dictionary * @param objectNameMapValue The map */ public LayoutPage(COSBase contentsValue, COSDictionary resValue, Map objectNameMapValue) { contents = contentsValue; res = resValue; objectNameMap = objectNameMapValue; } } /** * This will overlay two documents onto each other. The overlay document is * repeatedly overlayed onto the destination document for every page in the * destination. * * @param overlay The document to copy onto the destination * @param destination The file that the overlay should be placed on. * * @return The destination pdf, same as argument passed in. * * @throws IOException If there is an error accessing data. */ public PDDocument overlay( PDDocument overlay, PDDocument destination ) throws IOException { pdfOverlay = overlay; pdfDocument = destination; PDDocumentCatalog overlayCatalog = pdfOverlay.getDocumentCatalog(); collectLayoutPages( overlayCatalog.getAllPages() ); COSDictionary saveGraphicsStateDic = new COSDictionary(); saveGraphicsStateStream = pdfDocument.getDocument().createCOSStream(saveGraphicsStateDic); OutputStream saveStream = saveGraphicsStateStream.createUnfilteredStream(); saveStream.write( " q\n".getBytes("ISO-8859-1") ); saveStream.flush(); restoreGraphicsStateStream = pdfDocument.getDocument().createCOSStream(saveGraphicsStateDic); OutputStream restoreStream = restoreGraphicsStateStream.createUnfilteredStream(); restoreStream.write( " Q\n".getBytes("ISO-8859-1") ); restoreStream.flush(); PDDocumentCatalog pdfCatalog = pdfDocument.getDocumentCatalog(); processPages( pdfCatalog.getAllPages() ); return pdfDocument; } private void collectLayoutPages( List pages) throws IOException { Iterator pagesIter = pages.iterator(); while( pagesIter.hasNext() ) { PDPage page = (PDPage)pagesIter.next(); COSBase contents = page.getCOSDictionary().getDictionaryObject( COSName.CONTENTS ); PDResources resources = page.findResources(); if( resources == null ) { resources = new PDResources(); page.setResources( resources ); } COSDictionary res = resources.getCOSDictionary(); if( contents instanceof COSStream ) { COSStream stream = (COSStream) contents; Map objectNameMap = new TreeMap(); stream = makeUniqObjectNames(objectNameMap, stream); layoutPages.add(new LayoutPage(stream, res, objectNameMap)); } else if( contents instanceof COSArray ) { throw new UnsupportedOperationException("Layout pages with COSArray currently not supported."); // layoutPages.add(new LayoutPage(contents, res)); } else { throw new IOException( "Contents are unknown type:" + contents.getClass().getName() ); } } } private COSStream makeUniqObjectNames(Map objectNameMap, COSStream stream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(10240); byte[] buf = new byte[10240]; int read; InputStream is = stream.getUnfilteredStream(); while ((read = is.read(buf)) > -1) { baos.write(buf, 0, read); } buf = baos.toByteArray(); baos = new ByteArrayOutputStream(buf.length + 100); StringBuffer sbObjectName = new StringBuffer(10); boolean bInObjectIdent = false; boolean bInText = false; boolean bInEscape = false; for (int i = 0; i // // // array.add(0, saveGraphicsStateStream ); array.add( restoreGraphicsStateStream ); array.add(layoutPage.contents); } /** * merges two dictionaries. * * @param dest * @param source */ private void mergeDictionary(COSName name, COSDictionary dest, COSDictionary source, Map objectNameMap) { COSDictionary destDict = (COSDictionary) dest.getDictionaryObject(name); COSDictionary sourceDict = (COSDictionary) source.getDictionaryObject(name); if (destDict == null) { destDict = new COSDictionary(); dest.setItem(name, destDict); } if( sourceDict != null ) { for (Map.Entry entry : sourceDict.entrySet()) { COSName mappedKey = (COSName) objectNameMap.get(entry.getKey().getName()); if (mappedKey != null) { destDict.setItem(mappedKey, entry.getValue()); } } } } /** * merges two arrays. * * @param dest * @param source */ private void mergeArray(COSName name, COSDictionary dest, COSDictionary source) { COSArray destDict = (COSArray) dest.getDictionaryObject(name); COSArray sourceDict = (COSArray) source.getDictionaryObject(name); if (destDict == null) { destDict = new COSArray(); dest.setItem(name, destDict); } for (int sourceDictIdx = 0; sourceDict != null && sourceDictIdx




© 2015 - 2024 Weber Informatics LLC | Privacy Policy