From 6025b6016517c6d898d8957d1d7e03ba71431912 Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 1 Dec 2006 12:20:24 +0000 Subject: Initial import of release 2.2. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@4 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../java/org/pdfbox/pdmodel/common/PDStream.java | 538 +++++++++++++++++++++ 1 file changed, 538 insertions(+) create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDStream.java (limited to 'src/main/java/org/pdfbox/pdmodel/common/PDStream.java') diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDStream.java new file mode 100644 index 0000000..74398b2 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/PDStream.java @@ -0,0 +1,538 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.filter.Filter; +import org.pdfbox.filter.FilterManager; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.common.filespecification.PDFileSpecification; + +/** + * A PDStream represents a stream in a PDF document. Streams are tied to a single + * PDF document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.14 $ + */ +public class PDStream implements COSObjectable +{ + private COSStream stream; + + /** + * This will create a new PDStream object. + */ + protected PDStream() + { + //should only be called by PDMemoryStream + } + + /** + * This will create a new PDStream object. + * + * @param document The document that the stream will be part of. + */ + public PDStream( PDDocument document ) + { + stream = new COSStream( document.getDocument().getScratchFile() ); + } + + /** + * Constructor. + * + * @param str The stream parameter. + */ + public PDStream( COSStream str ) + { + stream = str; + } + + /** + * Constructor. Reads all data from the input stream and embeds it into the + * document, this will close the InputStream. + * + * @param doc The document that will hold the stream. + * @param str The stream parameter. + * @throws IOException If there is an error creating the stream in the document. + */ + public PDStream( PDDocument doc, InputStream str ) throws IOException + { + this( doc, str, false ); + } + + /** + * Constructor. Reads all data from the input stream and embeds it into the + * document, this will close the InputStream. + * + * @param doc The document that will hold the stream. + * @param str The stream parameter. + * @param filtered True if the stream already has a filter applied. + * @throws IOException If there is an error creating the stream in the document. + */ + public PDStream( PDDocument doc, InputStream str, boolean filtered ) throws IOException + { + OutputStream output = null; + try + { + stream = new COSStream( doc.getDocument().getScratchFile() ); + if( filtered ) + { + output = stream.createFilteredStream(); + } + else + { + output = stream.createUnfilteredStream(); + } + byte[] buffer = new byte[ 1024 ]; + int amountRead = -1; + while( (amountRead = str.read(buffer)) != -1 ) + { + output.write( buffer, 0, amountRead ); + } + } + finally + { + if( output != null ) + { + output.close(); + } + if( str != null ) + { + str.close(); + } + } + } + + /** + * If there are not compression filters on the current stream then this + * will add a compression filter, flate compression for example. + */ + public void addCompression() + { + List filters = getFilters(); + if( filters == null ) + { + filters = new ArrayList(); + filters.add( COSName.FLATE_DECODE ); + setFilters( filters ); + } + } + + /** + * Create a pd stream from either a regular COSStream on a COSArray of cos streams. + * @param base Either a COSStream or COSArray. + * @return A PDStream or null if base is null. + * @throws IOException If there is an error creating the PDStream. + */ + public static PDStream createFromCOS( COSBase base ) throws IOException + { + PDStream retval = null; + if( base instanceof COSStream ) + { + retval = new PDStream( (COSStream)base ); + } + else if( base instanceof COSArray ) + { + retval = new PDStream( new COSStreamArray( (COSArray)base ) ); + } + else + { + if( base != null ) + { + throw new IOException( "Contents are unknown type:" + base.getClass().getName() ); + } + } + return retval; + } + + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return stream; + } + + /** + * This will get a stream that can be written to. + * + * @return An output stream to write data to. + * + * @throws IOException If an IO error occurs during writing. + */ + public OutputStream createOutputStream() throws IOException + { + return stream.createUnfilteredStream(); + } + + /** + * This will get a stream that can be read from. + * + * @return An input stream that can be read from. + * + * @throws IOException If an IO error occurs during reading. + */ + public InputStream createInputStream() throws IOException + { + return stream.getUnfilteredStream(); + } + + /** + * This will get a stream with some filters applied but not others. This is useful + * when doing images, ie filters = [flate,dct], we want to remove flate but leave dct + * + * @param stopFilters A list of filters to stop decoding at. + * @return A stream with decoded data. + * @throws IOException If there is an error processing the stream. + */ + public InputStream getPartiallyFilteredStream( List stopFilters ) throws IOException + { + FilterManager manager = stream.getFilterManager(); + InputStream is = stream.getFilteredStream(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + List filters = getFilters(); + Iterator iter = filters.iterator(); + String nextFilter = null; + boolean done = false; + while( iter.hasNext() && !done ) + { + os.reset(); + nextFilter = (String)iter.next(); + if( stopFilters.contains( nextFilter ) ) + { + done = true; + } + else + { + Filter filter = manager.getFilter( COSName.getPDFName(nextFilter) ); + filter.decode( is, os, stream ); + is = new ByteArrayInputStream( os.toByteArray() ); + } + } + return is; + } + + /** + * Get the cos stream associated with this object. + * + * @return The cos object that matches this Java object. + */ + public COSStream getStream() + { + return stream; + } + + /** + * This will get the length of the filtered/compressed stream. This is readonly in the + * PD Model and will be managed by this class. + * + * @return The length of the filtered stream. + */ + public int getLength() + { + return stream.getInt( "Length", 0 ); + } + + /** + * This will get the list of filters that are associated with this stream. Or + * null if there are none. + * @return A list of all encoding filters to apply to this stream. + */ + public List getFilters() + { + List retval = null; + COSBase filters = stream.getFilters(); + if( filters instanceof COSName ) + { + COSName name = (COSName)filters; + retval = new COSArrayList( name.getName(), name, stream, "Filter" ); + } + else if( filters instanceof COSArray ) + { + retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters ); + } + return retval; + } + + /** + * This will set the filters that are part of this stream. + * + * @param filters The filters that are part of this stream. + */ + public void setFilters( List filters ) + { + COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters ); + stream.setItem( "Filter", obj ); + } + + /** + * Get the list of decode parameters. Each entry in the list will refer to + * an entry in the filters list. + * + * @return The list of decode parameters. + * + * @throws IOException if there is an error retrieving the parameters. + */ + public List getDecodeParams() throws IOException + { + List retval = null; + + COSBase dp = stream.getDictionaryObject( "DecodeParms" ); + if( dp == null ) + { + //See PDF Ref 1.5 implementation note 7, the DP is sometimes used instead. + dp = stream.getDictionaryObject( "DP" ); + } + if( dp instanceof COSDictionary ) + { + Map map = COSDictionaryMap.convertBasicTypesToMap( (COSDictionary)dp ); + retval = new COSArrayList(map, dp, stream, "DecodeParams" ); + } + else if( dp instanceof COSArray ) + { + COSArray array = (COSArray)dp; + List actuals = new ArrayList(); + for( int i=0; i