org.apache.pdfbox.pdmodel.common.PDStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pdfbox Show documentation
Show all versions of pdfbox Show documentation
The Apache PDFBox library is an open source Java tool for working with PDF documents.
/*
* 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.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.List;
import java.util.Map;
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.COSNull;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.filter.Filter;
import org.apache.pdfbox.filter.FilterManager;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.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
* @version $Revision: 1.17 $
*/
public class PDStream implements COSObjectable
{
private COSStream stream;
/**
* This will create a new empty PDStream object.
*/
protected PDStream()
{
// should only be called by PDMemoryStream
}
/**
* This will create a new empty PDStream object.
*
* @param document
* The document that the stream will be part of.
*/
public PDStream(PDDocument document)
{
stream = document.getDocument().createCOSStream();
}
/**
* Creates a PDStream which wraps the given COSStream.
*
* @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 = doc.getDocument().createCOSStream();
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)
{
if (((COSArray) base).size() > 0)
{
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();
boolean done = false;
for (int i = 0; i < filters.size() && !done; i++)
{
COSName nextFilter = filters.get(i);
if (stopFilters.contains(nextFilter.getName()))
{
done = true;
}
else
{
Filter filter = manager.getFilter(nextFilter);
filter.decode(is, os, stream, i);
IOUtils.closeQuietly(is);
is = new ByteArrayInputStream(os.toByteArray());
os.reset();
}
}
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(COSName.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, name, stream,
COSName.FILTER);
}
else if (filters instanceof COSArray)
{
retval = (List) ((COSArray) filters).toList();
}
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.converterToCOSArray(filters);
stream.setItem(COSName.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