You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/02/23 21:25:10 UTC
svn commit: r1571082 [1/2] - in /pdfbox/trunk/pdfbox/src:
main/java/org/apache/pdfbox/cos/ main/java/org/apache/pdfbox/filter/
main/java/org/apache/pdfbox/pdmodel/common/
main/java/org/apache/pdfbox/pdmodel/graphics/color/
main/java/org/apache/pdfbox/p...
Author: jahewson
Date: Sun Feb 23 20:25:09 2014
New Revision: 1571082
URL: http://svn.apache.org/r1571082
Log:
Added image filter repair mechanism for PDFBOX-1893
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DecodeResult.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterFactory.java
- copied, changed from r1570339, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterManager.java
Removed:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterManager.java
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSBase.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSStream.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCII85Filter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCIIHexFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CryptFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FlateFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/IdentityFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWDictionary.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWNode.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/RunLengthDecodeFilter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/TIFFFaxDecoder.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/common/PDStream.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDJPXColorSpace.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDInlineImage.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/SampledImageReader.java
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/cos/TestCOSBase.java
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/filter/TestFilters.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSBase.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSBase.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSBase.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSBase.java Sun Feb 23 20:25:09 2014
@@ -16,7 +16,6 @@
*/
package org.apache.pdfbox.cos;
-import org.apache.pdfbox.filter.FilterManager;
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.exceptions.COSVisitorException;
@@ -24,35 +23,19 @@ import org.apache.pdfbox.exceptions.COSV
/**
* The base object that all objects in the PDF document will extend.
*
- * @author <a href="ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.14 $
+ * @author Ben Litchfield
*/
public abstract class COSBase implements COSObjectable
{
- /**
- * Constructor.
- */
-
private boolean needToBeUpdate;
-
private boolean direct;
-
- public COSBase()
- {
- needToBeUpdate = false;
- }
/**
- * This will get the filter manager to use to filter streams.
- *
- * @return The filter manager.
+ * Constructor.
*/
- public FilterManager getFilterManager()
+ public COSBase()
{
- /**
- * @todo move this to PDFdocument or something better
- */
- return new FilterManager();
+ needToBeUpdate = false;
}
/**
@@ -65,8 +48,6 @@ public abstract class COSBase implements
return this;
}
-
-
/**
* visitor pattern double dispatch method.
*
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSDictionary.java Sun Feb 23 20:25:09 2014
@@ -1435,7 +1435,7 @@ public class COSDictionary extends COSBa
/**
* Returns an unmodifiable view of this dictionary.
- * @return
+ * @return an unmodifiable view of this dictionary
*/
public COSDictionary asUnmodifiableDictionary()
{
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSStream.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSStream.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSStream.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSStream.java Sun Feb 23 20:25:09 2014
@@ -26,8 +26,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.filter.DecodeResult;
import org.apache.pdfbox.filter.Filter;
-import org.apache.pdfbox.filter.FilterManager;
+import org.apache.pdfbox.filter.FilterFactory;
import org.apache.pdfbox.io.*;
import org.apache.pdfbox.pdfparser.PDFStreamParser;
import org.apache.pdfbox.exceptions.COSVisitorException;
@@ -57,6 +58,7 @@ public class COSStream extends COSDictio
* The stream with no filters, this contains the useful data.
*/
private RandomAccessFileOutputStream unFilteredStream;
+ private DecodeResult decodeResult;
private RandomAccess clone (RandomAccess file) {
if (file == null) {
@@ -217,6 +219,29 @@ public class COSStream extends COSDictio
}
/**
+ * Returns the repaired stream parameters dictionary.
+ *
+ * @return the repaired stream parameters dictionary
+ * @throws IOException when encoding/decoding causes an exception
+ */
+ public DecodeResult getDecodeResult() throws IOException
+ {
+ if (unFilteredStream == null)
+ {
+ doDecode();
+ }
+
+ if (unFilteredStream == null)
+ {
+ throw new IOException("Stream was not read");
+ }
+ else
+ {
+ return decodeResult;
+ }
+ }
+
+ /**
* visitor pattern double dispatch method.
*
* @param visitor The object to notify when visiting this object.
@@ -272,8 +297,7 @@ public class COSStream extends COSDictio
*/
private void doDecode( COSName filterName, int filterIndex ) throws IOException
{
- FilterManager manager = getFilterManager();
- Filter filter = manager.getFilter( filterName );
+ Filter filter = FilterFactory.INSTANCE.getFilter( filterName );
boolean done = false;
IOException exception = null;
@@ -305,8 +329,7 @@ public class COSStream extends COSDictio
new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
IOUtils.closeQuietly(unFilteredStream);
unFilteredStream = new RandomAccessFileOutputStream( file );
- filter.decode( input, unFilteredStream, this.asUnmodifiableDictionary(),
- filterIndex );
+ decodeResult = filter.decode( input, unFilteredStream, this, filterIndex );
done = true;
}
catch( IOException io )
@@ -334,8 +357,7 @@ public class COSStream extends COSDictio
new RandomAccessFileInputStream( file, position, length ), BUFFER_SIZE );
IOUtils.closeQuietly(unFilteredStream);
unFilteredStream = new RandomAccessFileOutputStream( file );
- filter.decode( input, unFilteredStream, this.asUnmodifiableDictionary(),
- filterIndex );
+ decodeResult = filter.decode( input, unFilteredStream, this, filterIndex);
done = true;
}
catch( IOException io )
@@ -396,8 +418,7 @@ public class COSStream extends COSDictio
*/
private void doEncode( COSName filterName, int filterIndex ) throws IOException
{
- FilterManager manager = getFilterManager();
- Filter filter = manager.getFilter( filterName );
+ Filter filter = FilterFactory.INSTANCE.getFilter( filterName );
InputStream input = new BufferedInputStream(
new RandomAccessFileInputStream( file, filteredStream.getPosition(),
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCII85Filter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCII85Filter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCII85Filter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCII85Filter.java Sun Feb 23 20:25:09 2014
@@ -24,56 +24,49 @@ import org.apache.pdfbox.io.ASCII85Input
import org.apache.pdfbox.io.ASCII85OutputStream;
import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.io.IOUtils;
/**
- * This is the used for the ASCIIHexDecode filter.
- *
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.8 $
+ * Decodes data encoded in an ASCII base-85 representation, reproducing the original binary data.
+ * @author Ben Litchfield
*/
-public class ASCII85Filter implements Filter
+final class ASCII85Filter extends Filter
{
- /**
- * {@inheritDoc}
- */
- public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
ASCII85InputStream is = null;
try
{
- is = new ASCII85InputStream(compressedData);
+ is = new ASCII85InputStream(encoded);
byte[] buffer = new byte[1024];
- int amountRead = 0;
- while( (amountRead = is.read( buffer, 0, 1024) ) != -1 )
+ int amountRead;
+ while((amountRead = is.read(buffer, 0, 1024))!= -1)
{
- result.write(buffer, 0, amountRead);
+ decoded.write(buffer, 0, amountRead);
}
- result.flush();
+ decoded.flush();
}
finally
{
- if( is != null )
- {
- is.close();
- }
+ IOUtils.closeQuietly(is);
}
+ return new DecodeResult(parameters);
}
- /**
- * {@inheritDoc}
- */
- public void encode( InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
throws IOException
{
- ASCII85OutputStream os = new ASCII85OutputStream(result);
+ ASCII85OutputStream os = new ASCII85OutputStream(encoded);
byte[] buffer = new byte[1024];
- int amountRead = 0;
- while( (amountRead = rawData.read( buffer, 0, 1024 )) != -1 )
+ int amountRead;
+ while((amountRead = input.read(buffer, 0, 1024))!= -1)
{
- os.write( buffer, 0, amountRead );
+ os.write(buffer, 0, amountRead);
}
os.close();
- result.flush();
+ encoded.flush();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCIIHexFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCIIHexFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCIIHexFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/ASCIIHexFilter.java Sun Feb 23 20:25:09 2014
@@ -27,204 +27,98 @@ import org.apache.pdfbox.cos.COSDictiona
import org.apache.pdfbox.persistence.util.COSHEXTable;
/**
- * This is the used for the ASCIIHexDecode filter.
- *
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.9 $
+ * Decodes data encoded in an ASCII hexadecimal form, reproducing the original binary data.
+ * @author Ben Litchfield
*/
-public class ASCIIHexFilter implements Filter
+final class ASCIIHexFilter extends Filter
{
-
- /**
- * Log instance.
- */
private static final Log log = LogFactory.getLog(ASCIIHexFilter.class);
- /**
- * Whitespace.
- * 0 0x00 Null (NUL)
- * 9 0x09 Tab (HT)
- * 10 0x0A Line feed (LF)
- * 12 0x0C Form feed (FF)
- * 13 0x0D Carriage return (CR)
- * 32 0x20 Space (SP)
- */
- private boolean isWhitespace(int c)
- {
- return c == 0 || c == 9 || c == 10 || c == 12 || c == 13 || c == 32;
- }
-
- private boolean isEOD(int c)
- {
- return (c == 62); // '>' - EOD
- }
-
- /**
- * {@inheritDoc}
- */
- public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ private static final int[] REVERSE_HEX = {
+ /* 0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 20 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 30 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 40 */ -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
+ /* 50 */ 2, 3, 4, 5, 6, 7, 8, 9, -1, -1,
+ /* 60 */ -1, -1, -1, -1, -1, 10, 11, 12, 13, 14,
+ /* 70 */ 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 80 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 90 */ -1, -1, -1, -1, -1, -1, -1, 10, 11, 12,
+ /* 100 */ 13, 14, 15
+ };
+
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
- int value = 0;
- int firstByte = 0;
- int secondByte = 0;
- while ((firstByte = compressedData.read()) != -1)
+ int value, firstByte, secondByte;
+ while ((firstByte = encoded.read()) != -1)
{
// always after first char
- while(isWhitespace(firstByte))
+ while (isWhitespace(firstByte))
{
- firstByte = compressedData.read();
+ firstByte = encoded.read();
}
- if(isEOD(firstByte))
+ if (isEOD(firstByte))
{
break;
}
- if(REVERSE_HEX[firstByte] == -1)
+ if (REVERSE_HEX[firstByte] == -1)
{
- log.error("Invalid Hex Code; int: " + firstByte + " char: " + (char) firstByte);
+ log.error("Invalid hex, int: " + firstByte + " char: " + (char)firstByte);
}
value = REVERSE_HEX[firstByte] * 16;
- secondByte = compressedData.read();
+ secondByte = encoded.read();
- if(isEOD(secondByte))
+ if (isEOD(secondByte))
{
// second value behaves like 0 in case of EOD
- result.write( value );
+ decoded.write(value);
break;
}
- if(secondByte >= 0)
+ if (secondByte >= 0)
{
- if(REVERSE_HEX[secondByte] == -1)
+ if (REVERSE_HEX[secondByte] == -1)
{
- log.error("Invalid Hex Code; int: " + secondByte + " char: " + (char) secondByte);
+ log.error("Invalid hex, int: " + secondByte + " char: " + (char)secondByte);
}
value += REVERSE_HEX[secondByte];
}
- result.write( value );
+ decoded.write(value);
}
- result.flush();
+ decoded.flush();
+ return new DecodeResult(parameters);
}
- private static final int[] REVERSE_HEX =
+ // whitespace
+ // 0 0x00 Null (NUL)
+ // 9 0x09 Tab (HT)
+ // 10 0x0A Line feed (LF)
+ // 12 0x0C Form feed (FF)
+ // 13 0x0D Carriage return (CR)
+ // 32 0x20 Space (SP)
+ private boolean isWhitespace(int c)
{
- -1, //0
- -1, //1
- -1, //2
- -1, //3
- -1, //4
- -1, //5
- -1, //6
- -1, //7
- -1, //8
- -1, //9
- -1, //10
- -1, //11
- -1, //12
- -1, //13
- -1, //14
- -1, //15
- -1, //16
- -1, //17
- -1, //18
- -1, //19
- -1, //20
- -1, //21
- -1, //22
- -1, //23
- -1, //24
- -1, //25
- -1, //26
- -1, //27
- -1, //28
- -1, //29
- -1, //30
- -1, //31
- -1, //32
- -1, //33
- -1, //34
- -1, //35
- -1, //36
- -1, //37
- -1, //38
- -1, //39
- -1, //40
- -1, //41
- -1, //42
- -1, //43
- -1, //44
- -1, //45
- -1, //46
- -1, //47
- 0, //48
- 1, //49
- 2, //50
- 3, //51
- 4, //52
- 5, //53
- 6, //54
- 7, //55
- 8, //56
- 9, //57
- -1, //58
- -1, //59
- -1, //60
- -1, //61
- -1, //62
- -1, //63
- -1, //64
- 10, //65
- 11, //66
- 12, //67
- 13, //68
- 14, //69
- 15, //70
- -1, //71
- -1, //72
- -1, //73
- -1, //74
- -1, //75
- -1, //76
- -1, //77
- -1, //78
- -1, //79
- -1, //80
- -1, //81
- -1, //82
- -1, //83
- -1, //84
- -1, //85
- -1, //86
- -1, //87
- -1, //88
- -1, //89
- -1, //90
- -1, //91
- -1, //92
- -1, //93
- -1, //94
- -1, //95
- -1, //96
- 10, //97
- 11, //98
- 12, //99
- 13, //100
- 14, //101
- 15, //102
- };
+ return c == 0 || c == 9 || c == 10 || c == 12 || c == 13 || c == 32;
+ }
+
+ private boolean isEOD(int c)
+ {
+ return (c == 62); // '>' - EOD
+ }
- /**
- * {@inheritDoc}
- */
- public void encode( InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
+ @Override
+ public void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
throws IOException
{
- int byteRead = 0;
- while( (byteRead = rawData.read()) != -1 )
+ int byteRead;
+ while ((byteRead = input.read()) != -1)
{
- int value = (byteRead+256)%256;
- result.write( COSHEXTable.TABLE[value] );
+ int value = (byteRead + 256) % 256;
+ encoded.write(COSHEXTable.TABLE[value]);
}
- result.flush();
+ encoded.flush();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java Sun Feb 23 20:25:09 2014
@@ -39,42 +39,28 @@ import org.apache.pdfbox.io.ccitt.FillOr
* @author Marcel Kammer
* @author Paul King
*/
-public final class CCITTFaxFilter implements Filter
+final class CCITTFaxFilter extends Filter
{
private static final Log log = LogFactory.getLog(CCITTFaxFilter.class);
- /**
- * Constructor.
- */
- public CCITTFaxFilter()
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
- }
+ DecodeResult result = new DecodeResult(new COSDictionary());
+ result.getParameters().addAll(parameters);
- /**
- * {@inheritDoc}
- */
- public void decode(InputStream compressedData, OutputStream result, COSDictionary options,
- int filterIndex) throws IOException
- {
// get decode parameters
- COSBase decodeP = options.getDictionaryObject(COSName.DECODE_PARMS, COSName.DP);
- COSDictionary decodeParms = null;
- if (decodeP instanceof COSDictionary)
- {
- decodeParms = (COSDictionary)decodeP;
- }
- else if (decodeP instanceof COSArray)
- {
- decodeParms = (COSDictionary)((COSArray)decodeP).getObject(filterIndex);
- }
+ COSDictionary decodeParms = (COSDictionary)
+ parameters.getDictionaryObject(COSName.DECODE_PARMS, COSName.DP);
// get compressed data
- int length = options.getInt(COSName.LENGTH, -1);
- byte[] compressed = null;
+ int length = parameters.getInt(COSName.LENGTH, -1);
+ byte[] compressed;
if (length != -1)
{
compressed = new byte[length];
- long written = IOUtils.populateBuffer(compressedData, compressed);
+ long written = IOUtils.populateBuffer(encoded, compressed);
if (written != compressed.length)
{
log.warn("Buffer for compressed data did not match the length"
@@ -86,13 +72,13 @@ public final class CCITTFaxFilter implem
// inline images don't provide the length of the stream so that
// we have to read until the end of the stream to find out the length
// the streams inline images are stored in are mostly small ones
- compressed = IOUtils.toByteArray(compressedData);
+ compressed = IOUtils.toByteArray(encoded);
}
// parse dimensions
int cols = decodeParms.getInt(COSName.COLUMNS, 1728);
int rows = decodeParms.getInt(COSName.ROWS, 0);
- int height = options.getInt(COSName.HEIGHT, COSName.H, 0);
+ int height = parameters.getInt(COSName.HEIGHT, COSName.H, 0);
if (rows > 0 && height > 0)
{
// ensure that rows doesn't contain implausible data, see PDFBOX-771
@@ -141,7 +127,14 @@ public final class CCITTFaxFilter implem
invertBitmap(decompressed);
}
- result.write(decompressed);
+ // repair missing color space
+ if (!parameters.containsKey(COSName.COLORSPACE))
+ {
+ result.getParameters().setName(COSName.COLORSPACE, COSName.DEVICEGRAY.getName());
+ }
+
+ decoded.write(decompressed);
+ return new DecodeResult(parameters);
}
private void invertBitmap(byte[] bufferData)
@@ -152,11 +145,9 @@ public final class CCITTFaxFilter implem
}
}
- /**
- * {@inheritDoc}
- */
- public void encode(InputStream rawData, OutputStream result, COSDictionary options,
- int filterIndex) throws IOException
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
+ throws IOException
{
log.warn("CCITTFaxDecode.encode is not implemented yet, skipping this stream.");
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CryptFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CryptFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CryptFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/CryptFilter.java Sun Feb 23 20:25:09 2014
@@ -23,46 +23,43 @@ import org.apache.pdfbox.cos.COSDictiona
import org.apache.pdfbox.cos.COSName;
/**
- *
- * @author adam.nichols
+ * Decrypts data encrypted by a security handler, reproducing the data as it was before encryption.
+ * @author Adam Nichols
*/
-public class CryptFilter implements Filter
+final class CryptFilter extends Filter
{
- /**
- * {@inheritDoc}
- */
- public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
- COSName encryptionName = (COSName)options.getDictionaryObject(COSName.NAME);
+ COSName encryptionName = (COSName) parameters.getDictionaryObject(COSName.NAME);
if(encryptionName == null || encryptionName.equals(COSName.IDENTITY))
{
// currently the only supported implementation is the Identity crypt filter
Filter identityFilter = new IdentityFilter();
- identityFilter.decode(compressedData, result, options, filterIndex);
+ identityFilter.decode(encoded, decoded, parameters);
+ return new DecodeResult(parameters);
}
else
{
- throw new IOException("Unsupported crypt filter "+encryptionName.getName());
+ throw new IOException("Unsupported crypt filter " + encryptionName.getName());
}
}
-
- /**
- * {@inheritDoc}
- */
- public void encode( InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
+ throws IOException
{
- COSName encryptionName = (COSName)options.getDictionaryObject(COSName.NAME);
+ COSName encryptionName = (COSName) parameters.getDictionaryObject(COSName.NAME);
if(encryptionName == null || encryptionName.equals(COSName.IDENTITY))
{
// currently the only supported implementation is the Identity crypt filter
Filter identityFilter = new IdentityFilter();
- identityFilter.encode(rawData, result, options, filterIndex);
+ identityFilter.encode(input, encoded, parameters);
}
else
{
- throw new IOException("Unsupported crypt filter "+encryptionName.getName());
+ throw new IOException("Unsupported crypt filter " + encryptionName.getName());
}
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DCTFilter.java Sun Feb 23 20:25:09 2014
@@ -40,16 +40,15 @@ import javax.imageio.stream.ImageInputSt
* Decompresses data encoded using a DCT (discrete cosine transform)
* technique based on the JPEG standard.
*
- * This filter is called {@code DCTDecode} in the PDF Reference.
- *
* @author John Hewson
*/
-public final class DCTFilter implements Filter
+final class DCTFilter extends Filter
{
private static final Log LOG = LogFactory.getLog(DCTFilter.class);
- public void decode(InputStream input, OutputStream output,
- COSDictionary options, int filterIndex) throws IOException
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
// find suitable image reader
Iterator readers = ImageIO.getImageReadersByFormatName("JPEG");
@@ -70,7 +69,7 @@ public final class DCTFilter implements
ImageInputStream iis = null;
try
{
- iis = ImageIO.createImageInputStream(input);
+ iis = ImageIO.createImageInputStream(encoded);
reader.setInput(iis);
// get the raster using horrible JAI workarounds
@@ -122,7 +121,7 @@ public final class DCTFilter implements
}
DataBufferByte dataBuffer = (DataBufferByte)raster.getDataBuffer();
- output.write(dataBuffer.getData());
+ decoded.write(dataBuffer.getData());
}
finally
{
@@ -132,12 +131,7 @@ public final class DCTFilter implements
}
reader.dispose();
}
- }
-
- public void encode(InputStream rawData, OutputStream result,
- COSDictionary options, int filterIndex) throws IOException
- {
- LOG.warn("DCTFilter#encode is not implemented yet, skipping this stream.");
+ return new DecodeResult(parameters);
}
// reads the APP14 Adobe transform tag
@@ -222,4 +216,11 @@ public final class DCTFilter implements
{
return (int)((value < 0) ? 0 : ((value > 255) ? 255 : value));
}
+
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
+ throws IOException
+ {
+ LOG.warn("DCTFilter#encode is not implemented yet, skipping this stream.");
+ }
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DecodeResult.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DecodeResult.java?rev=1571082&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DecodeResult.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/DecodeResult.java Sun Feb 23 20:25:09 2014
@@ -0,0 +1,67 @@
+/*
+ * 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.filter;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.pdmodel.graphics.color.PDJPXColorSpace;
+
+/**
+ * The result of a filter decode operation. Allows information such as color space to be
+ * extracted from image streams, and for stream parameters to be repaired during reading.
+ *
+ * @author John Hewson
+ */
+public final class DecodeResult
+{
+ private COSDictionary parameters;
+ private PDJPXColorSpace colorSpace;
+
+ DecodeResult(COSDictionary parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ DecodeResult(COSDictionary parameters, PDJPXColorSpace colorSpace)
+ {
+ this.parameters = parameters;
+ this.colorSpace = colorSpace;
+ }
+
+ /**
+ * Returns the stream parameters, repaired using the embedded stream data.
+ * @return the repaired stream parameters, or an empty dictionary
+ */
+ public COSDictionary getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Returns the embedded JPX color space, if any.
+ * @return the the embedded JPX color space, or null if there is none.
+ */
+ public PDJPXColorSpace getJPXColorSpace()
+ {
+ return colorSpace;
+ }
+
+ // Sets the JPX color space
+ void setColorSpace(PDJPXColorSpace colorSpace)
+ {
+ this.colorSpace = colorSpace;
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java Sun Feb 23 20:25:09 2014
@@ -20,39 +20,87 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
/**
- * This is the interface that will be used to apply filters to a byte stream.
+ * A filter for stream data.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.7 $
+ * @author Ben Litchfield
+ * @author John Hewson
*/
-public interface Filter
+public abstract class Filter
{
+ private static final Log log = LogFactory.getLog(Filter.class);
+
+ protected Filter()
+ {
+ }
+
/**
- * This will decode some compressed data.
- *
- * @param compressedData The compressed byte stream.
- * @param result The place to write the uncompressed byte stream.
- * @param options The options to use to encode the data.
- * @param filterIndex The index to the filter being decoded.
- *
- * @throws IOException If there is an error decompressing the stream.
+ * Decodes data, producing the original non-encoded data.
+ * @param encoded the encoded byte stream
+ * @param decoded the stream where decoded data will be written
+ * @param parameters the parameters used for decoding
+ * @return repaired parameters dictionary, or the original parameters dictionary
+ * @throws IOException if the stream cannot be decoded
*/
- public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException;
+ public final DecodeResult decode(InputStream encoded, OutputStream decoded, COSDictionary parameters,
+ int index) throws IOException
+ {
+ COSDictionary params = new COSDictionary();
+ params.addAll(parameters);
+ params.setItem(COSName.DECODE_PARMS, getDecodeParams(params, index));
+ return decode(encoded, decoded, params.asUnmodifiableDictionary());
+ }
+
+ // implemented in subclasses
+ protected abstract DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException;
/**
- * This will encode some data.
- *
- * @param rawData The raw data to encode.
- * @param result The place to write to encoded results to.
- * @param options The options to use to encode the data.
- * @param filterIndex The index to the filter being encoded.
- *
- * @throws IOException If there is an error compressing the stream.
+ * Encodes data.
+ * @param input the byte stream to encode
+ * @param encoded the stream where encoded data will be written
+ * @param parameters the parameters used for encoding
+ * @throws IOException if the stream cannot be encoded
*/
- public void encode( InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException;
+ public final void encode(InputStream input, OutputStream encoded, COSDictionary parameters,
+ int index) throws IOException
+ {
+ encode(input, encoded, parameters.asUnmodifiableDictionary());
+ }
+
+ // implemented in subclasses
+ protected abstract void encode(InputStream input, OutputStream encoded,
+ COSDictionary parameters) throws IOException;
+
+ // gets the decode params for a specific filter index, this is used to
+ // normalise the DecodeParams entry so that it is always a dictionary
+ private COSDictionary getDecodeParams(COSDictionary dictionary, int index)
+ {
+ COSBase obj = dictionary.getDictionaryObject(COSName.DECODE_PARMS, COSName.DP);
+ if (obj instanceof COSDictionary)
+ {
+ return (COSDictionary)obj;
+ }
+ else if (obj instanceof COSArray)
+ {
+ COSArray array = (COSArray)obj;
+ if (index < array.size())
+ {
+ return (COSDictionary)array.getObject(index);
+ }
+ }
+ else if (obj != null)
+ {
+ log.error("Expected DecodeParams to be an Array or Dictionary but found " +
+ obj.getClass().getName());
+ }
+ return new COSDictionary();
+ }
}
Copied: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterFactory.java (from r1570339, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterManager.java)
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterFactory.java?p2=pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterFactory.java&p1=pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterManager.java&r1=1570339&r2=1571082&rev=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterManager.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FilterFactory.java Sun Feb 23 20:25:09 2014
@@ -25,103 +25,81 @@ import java.util.Map;
import org.apache.pdfbox.cos.COSName;
/**
- * This will contain manage all the different types of filters that are available.
+ * Factory for Filter classes.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.13 $
+ * @author Ben Litchfield
*/
-public class FilterManager
+public final class FilterFactory
{
- private Map<COSName, Filter> filters = new HashMap<COSName, Filter>();
-
/**
- * Constructor.
+ * Singleton instance.
*/
- public FilterManager()
- {
- Filter flateFilter = new FlateFilter();
- Filter dctFilter = new DCTFilter();
- Filter ccittFaxFilter = new CCITTFaxFilter();
- Filter lzwFilter = new LZWFilter();
- Filter asciiHexFilter = new ASCIIHexFilter();
- Filter ascii85Filter = new ASCII85Filter();
- Filter runLengthFilter = new RunLengthDecodeFilter();
- Filter cryptFilter = new CryptFilter();
- Filter jpxFilter = new JPXFilter();
- Filter jbig2Filter = new JBIG2Filter();
-
- addFilter( COSName.FLATE_DECODE, flateFilter );
- addFilter( COSName.FLATE_DECODE_ABBREVIATION, flateFilter );
- addFilter( COSName.DCT_DECODE, dctFilter );
- addFilter( COSName.DCT_DECODE_ABBREVIATION, dctFilter );
- addFilter( COSName.CCITTFAX_DECODE, ccittFaxFilter );
- addFilter( COSName.CCITTFAX_DECODE_ABBREVIATION, ccittFaxFilter );
- addFilter( COSName.LZW_DECODE, lzwFilter );
- addFilter( COSName.LZW_DECODE_ABBREVIATION, lzwFilter );
- addFilter( COSName.ASCII_HEX_DECODE, asciiHexFilter );
- addFilter( COSName.ASCII_HEX_DECODE_ABBREVIATION, asciiHexFilter );
- addFilter( COSName.ASCII85_DECODE, ascii85Filter );
- addFilter( COSName.ASCII85_DECODE_ABBREVIATION, ascii85Filter );
- addFilter( COSName.RUN_LENGTH_DECODE, runLengthFilter );
- addFilter( COSName.RUN_LENGTH_DECODE_ABBREVIATION, runLengthFilter );
- addFilter( COSName.CRYPT, cryptFilter );
- addFilter( COSName.JPX_DECODE, jpxFilter );
- addFilter( COSName.JBIG2_DECODE, jbig2Filter );
-
- }
+ public static FilterFactory INSTANCE = new FilterFactory();
- /**
- * This will get all of the filters that are available in the system.
- *
- * @return All available filters in the system.
- */
- public Collection<Filter> getFilters()
+ private Map<COSName, Filter> filters = new HashMap<COSName, Filter>();
+
+ private FilterFactory()
{
- return filters.values();
+ Filter flate = new FlateFilter();
+ Filter dct = new DCTFilter();
+ Filter ccittFax = new CCITTFaxFilter();
+ Filter lzw = new LZWFilter();
+ Filter asciiHex = new ASCIIHexFilter();
+ Filter ascii85 = new ASCII85Filter();
+ Filter runLength = new RunLengthDecodeFilter();
+ Filter crypt = new CryptFilter();
+ Filter jpx = new JPXFilter();
+ Filter jbig2 = new JBIG2Filter();
+
+ filters.put(COSName.FLATE_DECODE, flate);
+ filters.put(COSName.FLATE_DECODE_ABBREVIATION, flate);
+ filters.put(COSName.DCT_DECODE, dct);
+ filters.put(COSName.DCT_DECODE_ABBREVIATION, dct);
+ filters.put(COSName.CCITTFAX_DECODE, ccittFax);
+ filters.put(COSName.CCITTFAX_DECODE_ABBREVIATION, ccittFax);
+ filters.put(COSName.LZW_DECODE, lzw);
+ filters.put(COSName.LZW_DECODE_ABBREVIATION, lzw);
+ filters.put(COSName.ASCII_HEX_DECODE, asciiHex);
+ filters.put(COSName.ASCII_HEX_DECODE_ABBREVIATION, asciiHex);
+ filters.put(COSName.ASCII85_DECODE, ascii85);
+ filters.put(COSName.ASCII85_DECODE_ABBREVIATION, ascii85);
+ filters.put(COSName.RUN_LENGTH_DECODE, runLength);
+ filters.put(COSName.RUN_LENGTH_DECODE_ABBREVIATION, runLength);
+ filters.put(COSName.CRYPT, crypt);
+ filters.put(COSName.JPX_DECODE, jpx);
+ filters.put(COSName.JBIG2_DECODE, jbig2);
}
/**
- * This will add an available filter.
- *
- * @param filterName The name of the filter.
- * @param filter The filter to use.
+ * Returns a filter instance given its name as a string.
+ * @param filterName the name of the filter to retrieve
+ * @return the filter that matches the name
+ * @throws IOException if the filter name was invalid
*/
- public void addFilter( COSName filterName, Filter filter )
+ public Filter getFilter(String filterName) throws IOException
{
- filters.put( filterName, filter );
+ return getFilter(COSName.getPDFName(filterName));
}
/**
- * This will get a filter by name.
- *
- * @param filterName The name of the filter to retrieve.
- *
- * @return The filter that matches the name.
- *
- * @throws IOException If the filter could not be found.
+ * Returns a filter instance given its COSName.
+ * @param filterName the name of the filter to retrieve
+ * @return the filter that matches the name
+ * @throws IOException if the filter name was invalid
*/
- public Filter getFilter( COSName filterName ) throws IOException
+ public Filter getFilter(COSName filterName) throws IOException
{
- Filter filter = (Filter)filters.get( filterName );
- if( filter == null )
+ Filter filter = filters.get(filterName);
+ if (filter == null)
{
- throw new IOException( "Unknown stream filter:" + filterName );
+ throw new IOException("Invalid filter: " + filterName);
}
-
return filter;
}
- /**
- * This will get a filter by name.
- *
- * @param filterName The name of the filter to retrieve.
- *
- * @return The filter that matches the name.
- *
- * @throws IOException If the filter could not be found.
- */
- public Filter getFilter( String filterName ) throws IOException
+ // returns all available filters, for testing
+ Collection<Filter> getAllFilters()
{
- return getFilter( COSName.getPDFName( filterName ) );
+ return filters.values();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FlateFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FlateFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FlateFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/FlateFilter.java Sun Feb 23 20:25:09 2014
@@ -27,117 +27,91 @@ import java.util.zip.Inflater;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.pdfbox.cos.COSArray;
-import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
/**
- * This is the used for the FlateDecode filter.
+ * Decompresses data encoded using the zlib/deflate compression method,
+ * reproducing the original text or binary data.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
+ * @author Ben Litchfield
* @author Marcel Kammer
- * @version $Revision: 1.12 $
*/
-public class FlateFilter implements Filter
+final class FlateFilter extends Filter
{
-
- /**
- * Log instance.
- */
private static final Log LOG = LogFactory.getLog(FlateFilter.class);
-
private static final int BUFFER_SIZE = 16348;
- /**
- * {@inheritDoc}
- */
- public void decode(InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
- COSBase baseObj = options.getDictionaryObject(COSName.DECODE_PARMS, COSName.DP);
- COSDictionary dict = null;
- if( baseObj instanceof COSDictionary )
- {
- dict = (COSDictionary)baseObj;
- }
- else if( baseObj instanceof COSArray )
- {
- COSArray paramArray = (COSArray)baseObj;
- if( filterIndex < paramArray.size() )
- {
- dict = (COSDictionary)paramArray.getObject( filterIndex );
- }
- }
- else if( baseObj != null )
- {
- throw new IOException( "Error: Expected COSArray or COSDictionary and not "
- + baseObj.getClass().getName() );
- }
-
-
int predictor = -1;
int colors = -1;
int bitsPerPixel = -1;
int columns = -1;
- ByteArrayInputStream bais = null;
- ByteArrayOutputStream baos = null;
- if (dict!=null)
+
+ COSDictionary decodeParams = (COSDictionary)
+ parameters.getDictionaryObject(COSName.DECODE_PARMS, COSName.DP);
+
+ if (decodeParams != null)
{
- predictor = dict.getInt(COSName.PREDICTOR);
- if(predictor > 1)
+ predictor = decodeParams.getInt(COSName.PREDICTOR);
+ if (predictor > 1)
{
- colors = dict.getInt(COSName.COLORS);
- bitsPerPixel = dict.getInt(COSName.BITS_PER_COMPONENT);
- columns = dict.getInt(COSName.COLUMNS);
+ colors = decodeParams.getInt(COSName.COLORS);
+ bitsPerPixel = decodeParams.getInt(COSName.BITS_PER_COMPONENT);
+ columns = decodeParams.getInt(COSName.COLUMNS);
}
}
+ ByteArrayInputStream bais = null;
+ ByteArrayOutputStream baos = null;
try
{
- baos = decompress(compressedData);
- // Decode data using given predictor
- if (predictor==-1 || predictor == 1 )
+ baos = decompress(encoded);
+
+ // decode data using given predictor
+ if (predictor == -1 || predictor == 1)
{
- result.write(baos.toByteArray());
+ decoded.write(baos.toByteArray());
}
else
{
- /*
- * Reverting back to default values
- */
- if( colors == -1 )
+ // reverting back to default values
+ if (colors == -1)
{
colors = 1;
}
- if( bitsPerPixel == -1 )
+
+ if (bitsPerPixel == -1)
{
bitsPerPixel = 8;
}
- if( columns == -1 )
+
+ if (columns == -1)
{
columns = 1;
}
- // Copy data to ByteArrayInputStream for reading
+ // copy data to ByteArrayInputStream for reading
bais = new ByteArrayInputStream(baos.toByteArray());
byte[] decodedData = decodePredictor(predictor, colors, bitsPerPixel, columns, bais);
bais.close();
bais = null;
- result.write(decodedData);
+ decoded.write(decodedData);
}
- result.flush();
+ decoded.flush();
}
- catch (DataFormatException exception)
+ catch (DataFormatException e)
{
// if the stream is corrupt a DataFormatException may occur
LOG.error("FlateFilter: stop reading corrupt stream due to a DataFormatException");
- // re-throw the exception, caller has to handle it
- IOException io = new IOException();
- io.initCause(exception);
- throw io;
+
+ // re-throw the exception
+ throw new IOException(e);
}
finally
{
@@ -150,29 +124,30 @@ public class FlateFilter implements Filt
baos.close();
}
}
+ return new DecodeResult(parameters);
}
- // Use Inflater instead of InflateInputStream to avoid an EOFException due to a probably
+ // Use Inflater instead of InflateInputStream to avoid an EOFException due to a probably
// missing Z_STREAM_END, see PDFBOX-1232 for details
private ByteArrayOutputStream decompress(InputStream in) throws IOException, DataFormatException
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[2048];
int read = in.read(buf);
- if(read > 0)
+ if (read > 0)
{
Inflater inflater = new Inflater();
inflater.setInput(buf,0,read);
byte[] res = new byte[2048];
- while(true)
+ while (true)
{
int resRead = inflater.inflate(res);
- if(resRead != 0)
+ if (resRead != 0)
{
out.write(res,0,resRead);
continue;
}
- if(inflater.finished() || inflater.needsDictionary() || in.available() == 0)
+ if (inflater.finished() || inflater.needsDictionary() || in.available() == 0)
{
break;
}
@@ -189,10 +164,10 @@ public class FlateFilter implements Filt
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
- if (predictor == 1 )
+ if (predictor == 1)
{
- // No prediction
- int i = 0;
+ // no prediction
+ int i;
while ((i = data.read(buffer)) != -1)
{
baos.write(buffer, 0, i);
@@ -202,10 +177,9 @@ public class FlateFilter implements Filt
{
// calculate sizes
int bitsPerPixel = colors * bitsPerComponent;
- int bytesPerPixel = (bitsPerPixel + 7 ) / 8;
+ int bytesPerPixel = (bitsPerPixel + 7) / 8;
int rowlength = (columns * bitsPerPixel + 7) / 8;
byte[] actline = new byte[rowlength];
- // Initialize lastline with Zeros according to PNG-specification
byte[] lastline = new byte[rowlength];
boolean done = false;
@@ -230,22 +204,19 @@ public class FlateFilter implements Filt
}
// read line
- int i = 0;
- int offset = 0;
+ int i, offset = 0;
while (offset < rowlength && ((i = data.read(actline, offset, rowlength - offset)) != -1))
{
offset += i;
}
- // Do prediction as specified in PNG-Specification 1.2
+ // do prediction as specified in PNG-Specification 1.2
switch (linepredictor)
{
case 2:// PRED TIFF SUB
- /**
- * @TODO decode tiff with bitsPerComponent != 8;
- * e.g. for 4 bpc each nibble must be subtracted separately
- */
- if ( bitsPerComponent != 8 )
+ // TODO decode tiff with bitsPerComponent != 8;
+ // e.g. for 4 bpc each nibble must be subtracted separately
+ if (bitsPerComponent != 8)
{
throw new IOException("TIFF-Predictor with " + bitsPerComponent
+ " bits per component not supported");
@@ -283,7 +254,7 @@ public class FlateFilter implements Filt
int avg = actline[p] & 0xff;
int left = p - bytesPerPixel >= 0 ? actline[p - bytesPerPixel] & 0xff: 0;
int up = lastline[p] & 0xff;
- actline[p] = (byte) ((avg + (int)Math.floor( (left + up)/2 ) ) & 0xff);
+ actline[p] = (byte) ((avg + (int)Math.floor((left + up)/2)) & 0xff);
}
break;
case 14:// PRED PAETH
@@ -322,24 +293,22 @@ public class FlateFilter implements Filt
return baos.toByteArray();
}
- /**
- * {@inheritDoc}
- */
- public void encode(InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
+ throws IOException
{
- DeflaterOutputStream out = new DeflaterOutputStream(result);
- int amountRead = 0;
- int mayRead = rawData.available();
+ DeflaterOutputStream out = new DeflaterOutputStream(encoded);
+ int amountRead;
+ int mayRead = input.available();
if (mayRead > 0)
{
byte[] buffer = new byte[Math.min(mayRead,BUFFER_SIZE)];
- while ((amountRead = rawData.read(buffer, 0, Math.min(mayRead,BUFFER_SIZE))) != -1)
+ while ((amountRead = input.read(buffer, 0, Math.min(mayRead,BUFFER_SIZE))) != -1)
{
out.write(buffer, 0, amountRead);
}
}
out.close();
- result.flush();
+ encoded.flush();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/IdentityFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/IdentityFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/IdentityFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/IdentityFilter.java Sun Feb 23 20:25:09 2014
@@ -22,43 +22,40 @@ import java.io.OutputStream;
import org.apache.pdfbox.cos.COSDictionary;
/**
- * The IdentityFilter filter just passes the data through without any modifications.
- * This is defined in section 7.6.5 of the PDF 1.7 spec and also stated in table
- * 26.
+ * The IdentityFilter filter passes the data through without any modifications.
+ * It is defined in section 7.6.5 of the PDF 1.7 spec and also stated in table 26.
*
- * @author adam.nichols
+ * @author Adam Nichols
*/
-public class IdentityFilter implements Filter
+final class IdentityFilter extends Filter
{
private static final int BUFFER_SIZE = 1024;
- /**
- * {@inheritDoc}
- */
- public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters)
throws IOException
{
byte[] buffer = new byte[BUFFER_SIZE];
- int amountRead = 0;
- while( (amountRead = compressedData.read( buffer, 0, BUFFER_SIZE )) != -1 )
+ int amountRead;
+ while((amountRead = encoded.read(buffer, 0, BUFFER_SIZE)) != -1)
{
- result.write( buffer, 0, amountRead );
+ decoded.write(buffer, 0, amountRead);
}
- result.flush();
+ decoded.flush();
+ return new DecodeResult(parameters);
}
-
- /**
- * {@inheritDoc}
- */
- public void encode( InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
+
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
throws IOException
{
byte[] buffer = new byte[BUFFER_SIZE];
- int amountRead = 0;
- while( (amountRead = rawData.read( buffer, 0, BUFFER_SIZE )) != -1 )
+ int amountRead;
+ while((amountRead = input.read(buffer, 0, BUFFER_SIZE)) != -1)
{
- result.write( buffer, 0, amountRead );
+ encoded.write(buffer, 0, amountRead);
}
- result.flush();
+ encoded.flush();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java Sun Feb 23 20:25:09 2014
@@ -39,7 +39,7 @@ import org.apache.pdfbox.cos.COSStream;
/**
* Decompresses data encoded using the JBIG2 standard, reproducing the original
- * monochrome (1 bit per pixel) image data (or an approximation of that data).
+ * monochrome (1 bit per pixel) image data (or an approximation of that data).
*
* Requires a JBIG2 plugin for Java Image I/O to be installed. A known working
* plug-in is <a href="http://code.google.com/p/jbig2-imageio/">jbig2-imageio</a>
@@ -47,18 +47,13 @@ import org.apache.pdfbox.cos.COSStream;
*
* @author Timo Boehme
*/
-public class JBIG2Filter implements Filter
+final class JBIG2Filter extends Filter
{
private static final Log LOG = LogFactory.getLog(JBIG2Filter.class);
- /**
- * Decode JBIG2 data using Java ImageIO library.
- *
- * {@inheritDoc}
- */
@Override
- public void decode(InputStream compressedData, OutputStream result, COSDictionary options,
- int filterIndex) throws IOException
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
// find suitable image reader
Iterator readers = ImageIO.getImageReadersByFormatName("JBIG2");
@@ -76,8 +71,11 @@ public class JBIG2Filter implements Filt
"jbig2-imageio is not installed");
}
- COSInteger bits = (COSInteger) options.getDictionaryObject(COSName.BITS_PER_COMPONENT);
- COSDictionary params = (COSDictionary) options.getDictionaryObject(COSName.DECODE_PARMS);
+ DecodeResult result = new DecodeResult(new COSDictionary());
+ result.getParameters().addAll(parameters);
+
+ COSInteger bits = (COSInteger) parameters.getDictionaryObject(COSName.BITS_PER_COMPONENT);
+ COSDictionary params = (COSDictionary) parameters.getDictionaryObject(COSName.DECODE_PARMS);
COSStream globals = null;
if (params != null)
@@ -91,12 +89,12 @@ public class JBIG2Filter implements Filt
if (globals != null)
{
iis = ImageIO.createImageInputStream(
- new SequenceInputStream(globals.getFilteredStream(), compressedData));
+ new SequenceInputStream(globals.getFilteredStream(), encoded));
reader.setInput(iis);
}
else
{
- iis = ImageIO.createImageInputStream(compressedData);
+ iis = ImageIO.createImageInputStream(encoded);
reader.setInput(iis);
}
@@ -130,7 +128,7 @@ public class JBIG2Filter implements Filt
DataBuffer dBuf = image.getData().getDataBuffer();
if (dBuf.getDataType() == DataBuffer.TYPE_BYTE)
{
- result.write(((DataBufferByte) dBuf).getData());
+ decoded.write(((DataBufferByte) dBuf).getData());
}
else
{
@@ -145,11 +143,19 @@ public class JBIG2Filter implements Filt
}
reader.dispose();
}
+
+ // repair missing color space
+ if (!parameters.containsKey(COSName.COLORSPACE))
+ {
+ result.getParameters().setName(COSName.COLORSPACE, COSName.DEVICEGRAY.getName());
+ }
+
+ return new DecodeResult(parameters);
}
@Override
- public void encode(InputStream rawData, OutputStream result, COSDictionary options,
- int filterIndex) throws IOException
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
+ throws IOException
{
throw new UnsupportedOperationException("JBIG2 encoding not implemented");
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/JPXFilter.java Sun Feb 23 20:25:09 2014
@@ -30,6 +30,7 @@ import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.pdmodel.graphics.color.PDJPXColorSpace;
@@ -48,17 +49,15 @@ import org.apache.pdfbox.pdmodel.graphic
* @author John Hewson
* @author Timo Boehme
*/
-public class JPXFilter implements Filter
+public final class JPXFilter extends Filter
{
- /**
- * Decode JPEG 2000 data using Java ImageIO library.
- *
- * {@inheritDoc}
- */
- public void decode(InputStream compressedData, OutputStream result, COSDictionary options,
- int filterIndex) throws IOException
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
- BufferedImage image = readJPX(compressedData);
+ DecodeResult result = new DecodeResult(new COSDictionary());
+ result.getParameters().addAll(parameters);
+ BufferedImage image = readJPX(encoded, result);
WritableRaster raster = image.getRaster();
if (raster.getDataBuffer().getDataType() != DataBuffer.TYPE_BYTE)
@@ -66,11 +65,13 @@ public class JPXFilter implements Filter
throw new IOException("Not implemented: greater than 8-bit depth");
}
DataBufferByte buffer = (DataBufferByte)raster.getDataBuffer();
- result.write(buffer.getData());
+ decoded.write(buffer.getData());
+
+ return result;
}
// try to read using JAI Image I/O
- private static BufferedImage readJPX(InputStream input) throws IOException
+ private static BufferedImage readJPX(InputStream input, DecodeResult result) throws IOException
{
// find suitable image reader
Iterator readers = ImageIO.getImageReadersByFormatName("JPEG2000");
@@ -105,6 +106,28 @@ public class JPXFilter implements Filter
throw new IOException("Could not read JPEG 2000 (JPX) image", e);
}
+ COSDictionary parameters = result.getParameters();
+
+ // "If the image stream uses the JPXDecode filter, this entry is optional
+ // and shall be ignored if present"
+ parameters.setInt(COSName.BITS_PER_COMPONENT, image.getColorModel().getComponentSize(0));
+
+ // "Decode shall be ignored, except in the case where the image is treated as a mask"
+ if (!parameters.getBoolean(COSName.IMAGE_MASK, false))
+ {
+ parameters.setItem(COSName.DECODE, null);
+ }
+
+ // override dimensions, see PDFBOX-1735
+ parameters.setInt(COSName.WIDTH, image.getWidth());
+ parameters.setInt(COSName.HEIGHT, image.getHeight());
+
+ // extract embedded color space
+ if (!parameters.containsKey(COSName.COLORSPACE))
+ {
+ result.setColorSpace(new PDJPXColorSpace(image.getColorModel().getColorSpace()));
+ }
+
return image;
}
finally
@@ -117,22 +140,9 @@ public class JPXFilter implements Filter
}
}
- /**
- * Returns the embedded color space from a JPX file.
- * @param input The JPX input stream
- */
- // TODO this method is something of a hack, we'd rather be able to return info from decode(...)
- public static PDColorSpace getColorSpace(InputStream input) throws IOException
- {
- BufferedImage image = readJPX(input);
- return new PDJPXColorSpace(image.getColorModel().getColorSpace());
- }
-
- /**
- * {@inheritDoc}
- */
- public void encode(InputStream rawData, OutputStream result, COSDictionary options,
- int filterIndex) throws IOException
+ @Override
+ protected final void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
+ throws IOException
{
throw new UnsupportedOperationException("JPX encoding not implemented");
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWDictionary.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWDictionary.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWDictionary.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWDictionary.java Sun Feb 23 20:25:09 2014
@@ -22,16 +22,15 @@ import java.util.HashMap;
import java.util.Map;
/**
- * This is the used for the LZWDecode filter. This represents the dictionary mappings
+ * This is the used for the LZWDecode filter. This represents the dictionary mappings
* between codes and their values.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.4 $
+ * @author Ben Litchfield
*/
final class LZWDictionary
{
private Map<Long,byte[]> codeToData = new HashMap<Long,byte[]>();
- private LZWNode root = new LZWNode( 0 );
+ private LZWNode root = new LZWNode(0);
private byte[] buffer = new byte[8];
private int bufferNextWrite = 0;
@@ -41,50 +40,35 @@ final class LZWDictionary
private LZWNode previous = null;
private LZWNode current = root;
- /**
- * This will get the value for the code. It will return null if the code is not
- * defined.
- *
- * @param code The key to the data.
- *
- * @return The data that is mapped to the code.
+ /*
+ * This will get the value for the code. It will return null if the code is not defined.
*/
- public byte[] getData( long code )
+ public byte[] getData(long code)
{
- byte[] result = codeToData.get( code );
+ byte[] result = codeToData.get(code);
if (result == null && code < 256)
{
- addRootNode( (byte) code );
- result = codeToData.get( code );
+ addRootNode((byte) code);
+ result = codeToData.get(code);
}
return result;
}
- /**
- * This will take a visit from a byte[]. This will create new code entries as
- * necessary.
- *
- * @param data The byte to get a visit from.
- *
- * @throws IOException If there is an error visiting this data.
+ /*
+ * This will take a visit from a byte[]. This will create new code entries as necessary.
*/
- public void visit( byte[] data ) throws IOException
+ public void visit(byte[] data) throws IOException
{
- for( int i=0; i<data.length; i++ )
+ for(int i=0; i<data.length; i++)
{
- visit( data[i] );
+ visit(data[i]);
}
}
- /**
- * This will take a visit from a byte. This will create new code entries as
- * necessary.
- *
- * @param data The byte to get a visit from.
- *
- * @throws IOException If there is an error visiting this data.
+ /*
+ * This will take a visit from a byte. This will create new code entries as necessary.
*/
- public void visit( byte data ) throws IOException
+ public void visit(byte data) throws IOException
{
if (buffer.length == bufferNextWrite)
{
@@ -94,11 +78,11 @@ final class LZWDictionary
}
buffer[bufferNextWrite++] = data;
previous = current;
- current = current.getNode( data );
+ current = current.getNode(data);
if (current == null)
{
final long code;
- if ( previous == root )
+ if (previous == root)
{
code = data & 0xFF;
}
@@ -106,28 +90,28 @@ final class LZWDictionary
{
code = nextCode++;
}
- current = new LZWNode( code );
- previous.setNode( data, current );
+ current = new LZWNode(code);
+ previous.setNode(data, current);
byte[] sav = new byte[bufferNextWrite];
System.arraycopy(buffer, 0, sav, 0, bufferNextWrite);
- codeToData.put( code, sav);
+ codeToData.put(code, sav);
- /**
- System.out.print( "Adding " + code + "='" );
- for( int i=0; i<bufferNextWrite; i++ )
+ /*
+ System.out.print("Adding " + code + "='");
+ for(int i=0; i<bufferNextWrite; i++)
{
- String hex = Integer.toHexString( ((buffer[i]&0xFF );
- if( hex.length() <=1 )
+ String hex = Integer.toHexString(((buffer[i]&0xFF);
+ if(hex.length() <=1)
{
hex = "0" + hex;
}
- if( i != bufferNextWrite -1 )
+ if(i != bufferNextWrite -1)
{
hex += " ";
}
- System.out.print( hex.toUpperCase() );
+ System.out.print(hex.toUpperCase());
}
- System.out.println( "'" );
+ System.out.println("'");
**/
bufferNextWrite = 0;
current = root;
@@ -136,9 +120,8 @@ final class LZWDictionary
}
}
- /**
+ /*
* This will get the next code that will be created.
- *
* @return The next code to be created.
*/
public long getNextCode()
@@ -146,30 +129,28 @@ final class LZWDictionary
return nextCode;
}
- /**
+ /*
* This will get the size of the code in bits, 9, 10, or 11.
- *
- * @return The size of the code in bits.
*/
public int getCodeSize()
{
return codeSize;
}
- /**
- * This will determine the code size.
+ /*
+ * This will return the code size.
*/
private void resetCodeSize()
{
- if ( nextCode < 512)
+ if (nextCode < 512)
{
codeSize = 9;
}
- else if ( nextCode < 1024 )
+ else if (nextCode < 1024)
{
codeSize = 10;
}
- else if ( nextCode < 2048 )
+ else if (nextCode < 2048)
{
codeSize = 11;
}
@@ -179,7 +160,7 @@ final class LZWDictionary
}
}
- /**
+ /*
* This will clear the internal buffer that the dictionary uses.
*/
public void clear()
@@ -189,16 +170,12 @@ final class LZWDictionary
previous = null;
}
- /**
- * This will folow the path to the data node.
- *
- * @param data The path to the node.
- *
- * @return The node that resides at that path.
+ /*
+ * This will follow the path to the data node.
*/
- public LZWNode getNode( byte[] data )
+ public LZWNode getNode(byte[] data)
{
- LZWNode result = root.getNode( data );
+ LZWNode result = root.getNode(data);
if (result == null && data.length == 1)
{
result = addRootNode(data[0]);
@@ -206,12 +183,12 @@ final class LZWDictionary
return result;
}
- private LZWNode addRootNode( byte b)
+ private LZWNode addRootNode(byte b)
{
long code = b & 0xFF;
- LZWNode result = new LZWNode( code );
- root.setNode( b, result );
- codeToData.put( code, new byte[] { b } );
+ LZWNode result = new LZWNode(code);
+ root.setNode(b, result);
+ codeToData.put(code, new byte[] { b });
return result;
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java Sun Feb 23 20:25:09 2014
@@ -31,133 +31,120 @@ import org.apache.pdfbox.io.NBitOutputSt
/**
* This is the used for the LZWDecode filter.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.15 $
+ * @author Ben Litchfield
*/
-public class LZWFilter implements Filter
+final class LZWFilter extends Filter
{
-
- /**
- * The LZW clear table code.
- */
public static final long CLEAR_TABLE = 256;
- /**
- * The LZW end of data code.
- */
public static final long EOD = 257;
- /**
- * {@inheritDoc}
- */
- public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ @Override
+ protected final DecodeResult decode(InputStream encoded, OutputStream decoded,
+ COSDictionary parameters) throws IOException
{
- //log.debug("decode( )");
- NBitInputStream in = null;
- in = new NBitInputStream( compressedData );
- in.setBitsInChunk( 9 );
+ //log.debug("decode()");
+ NBitInputStream in = new NBitInputStream(encoded);
+ in.setBitsInChunk(9);
LZWDictionary dic = new LZWDictionary();
byte firstByte = 0;
- long nextCommand = 0;
- while( (nextCommand = in.read() ) != EOD )
+ long nextCommand;
+ while ((nextCommand = in.read()) != EOD)
{
- // log.debug( "decode - nextCommand=" + nextCommand + ", bitsInChunk: " + in.getBitsInChunk());
+ // log.debug("decode - nextCommand=" + nextCommand + ", bitsInChunk: " + in.getBitsInChunk());
- if( nextCommand == CLEAR_TABLE )
+ if (nextCommand == CLEAR_TABLE)
{
- in.setBitsInChunk( 9 );
+ in.setBitsInChunk(9);
dic = new LZWDictionary();
}
else
{
- byte[] data = dic.getData( nextCommand );
- if( data == null )
+ byte[] data = dic.getData(nextCommand);
+ if (data == null)
{
- dic.visit( firstByte );
- data = dic.getData( nextCommand );
+ dic.visit(firstByte);
+ data = dic.getData(nextCommand);
dic.clear();
}
- if( data == null )
+ if (data == null)
{
- throw new StreamCorruptedException( "Error: data is null" );
+ throw new StreamCorruptedException("Error: data is null");
}
dic.visit(data);
- //log.debug( "decode - dic.getNextCode(): " + dic.getNextCode());
+ //log.debug("decode - dic.getNextCode(): " + dic.getNextCode());
- if( dic.getNextCode() >= 2047 )
+ if (dic.getNextCode() >= 2047)
{
- in.setBitsInChunk( 12 );
+ in.setBitsInChunk(12);
}
- else if( dic.getNextCode() >= 1023 )
+ else if (dic.getNextCode() >= 1023)
{
- in.setBitsInChunk( 11 );
+ in.setBitsInChunk(11);
}
- else if( dic.getNextCode() >= 511 )
+ else if (dic.getNextCode() >= 511)
{
- in.setBitsInChunk( 10 );
+ in.setBitsInChunk(10);
}
else
{
- in.setBitsInChunk( 9 );
+ in.setBitsInChunk(9);
}
/**
- if( in.getBitsInChunk() != dic.getCodeSize() )
+ if (in.getBitsInChunk() != dic.getCodeSize())
{
- in.unread( nextCommand );
- in.setBitsInChunk( dic.getCodeSize() );
- System.out.print( "Switching " + nextCommand + " to " );
+ in.unread(nextCommand);
+ in.setBitsInChunk(dic.getCodeSize());
+ System.out.print("Switching " + nextCommand + " to ");
nextCommand = in.read();
- System.out.println( "" + nextCommand );
- data = dic.getData( nextCommand );
+ System.out.println("" + nextCommand);
+ data = dic.getData(nextCommand);
}**/
firstByte = data[0];
- result.write( data );
+ decoded.write(data);
}
}
- result.flush();
+ decoded.flush();
+ return new DecodeResult(parameters);
}
-
- /**
- * {@inheritDoc}
- */
- public void encode( InputStream rawData, OutputStream result, COSDictionary options, int filterIndex )
- throws IOException
+ @Override
+ protected final void encode(InputStream rawData, OutputStream encoded, COSDictionary parameters)
+ throws IOException
{
- //log.debug("encode( )");
- PushbackInputStream input = new PushbackInputStream( rawData, 4096 );
+ //log.debug("encode()");
+ PushbackInputStream input = new PushbackInputStream(rawData, 4096);
LZWDictionary dic = new LZWDictionary();
- NBitOutputStream out = new NBitOutputStream( result );
- out.setBitsInChunk( 9 ); //initially nine
- out.write( CLEAR_TABLE );
+ NBitOutputStream out = new NBitOutputStream(encoded);
+ out.setBitsInChunk(9); //initially nine
+ out.write(CLEAR_TABLE);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int byteRead = 0;
- for( int i=0; (byteRead = input.read()) != -1; i++ )
+ for (int i = 0; (byteRead = input.read()) != -1; i++)
{
- //log.debug( "byteRead = '" + (char)byteRead + "' (0x" + Integer.toHexString(byteRead) + "), i=" + i);
- buffer.write( byteRead );
- dic.visit( (byte)byteRead );
- out.setBitsInChunk( dic.getCodeSize() );
+ //log.debug("byteRead = '" + (char)byteRead + "' (0x" + Integer.toHexString(byteRead) + "), i=" + i);
+ buffer.write(byteRead);
+ dic.visit((byte)byteRead);
+ out.setBitsInChunk(dic.getCodeSize());
- //log.debug( "Getting node '" + new String( buffer.toByteArray() ) + "', buffer.size = " + buffer.size() );
- LZWNode node = dic.getNode( buffer.toByteArray() );
+ //log.debug("Getting node '" + new String(buffer.toByteArray()) + "', buffer.size = " + buffer.size());
+ LZWNode node = dic.getNode(buffer.toByteArray());
int nextByte = input.read();
- if( nextByte != -1 )
+ if (nextByte != -1)
{
- //log.debug( "nextByte = '" + (char)nextByte + "' (0x" + Integer.toHexString(nextByte) + ")");
- LZWNode next = node.getNode( (byte)nextByte );
- if( next == null )
+ //log.debug("nextByte = '" + (char)nextByte + "' (0x" + Integer.toHexString(nextByte) + ")");
+ LZWNode next = node.getNode((byte)nextByte);
+ if (next == null)
{
//log.debug("encode - No next node, writing node and resetting buffer (" +
// " node.getCode: " + node.getCode() + ")" +
// " bitsInChunk: " + out.getBitsInChunk() +
// ")");
- out.write( node.getCode() );
+ out.write(node.getCode());
buffer.reset();
}
- input.unread( nextByte );
+ input.unread(nextByte);
}
else
{
@@ -165,47 +152,47 @@ public class LZWFilter implements Filter
// " node.getCode: " + node.getCode() + ")" +
// " bitsInChunk: " + out.getBitsInChunk() +
// ")");
- out.write( node.getCode() );
+ out.write(node.getCode());
buffer.reset();
break;
}
- if( dic.getNextCode() == 4096 )
+ if (dic.getNextCode() == 4096)
{
//log.debug("encode - Clearing dictionary and unreading pending buffer data (" +
// " bitsInChunk: " + out.getBitsInChunk() +
// ")");
- out.write( CLEAR_TABLE );
+ out.write(CLEAR_TABLE);
dic = new LZWDictionary();
- input.unread( buffer.toByteArray() );
+ input.unread(buffer.toByteArray());
buffer.reset();
}
}
// Fix the code size based on the fact that we are writing the EOD
//
- if( dic.getNextCode() >= 2047 )
+ if (dic.getNextCode() >= 2047)
{
- out.setBitsInChunk( 12 );
+ out.setBitsInChunk(12);
}
- else if( dic.getNextCode() >= 1023 )
+ else if (dic.getNextCode() >= 1023)
{
- out.setBitsInChunk( 11 );
+ out.setBitsInChunk(11);
}
- else if( dic.getNextCode() >= 511 )
+ else if (dic.getNextCode() >= 511)
{
- out.setBitsInChunk( 10 );
+ out.setBitsInChunk(10);
}
else
{
- out.setBitsInChunk( 9 );
+ out.setBitsInChunk(9);
}
//log.debug("encode - Writing EOD (" +
// " bitsInChunk: " + out.getBitsInChunk() +
// ")");
- out.write( EOD );
+ out.write(EOD);
out.close();
- result.flush();
+ encoded.flush();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWNode.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWNode.java?rev=1571082&r1=1571081&r2=1571082&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWNode.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWNode.java Sun Feb 23 20:25:09 2014
@@ -22,77 +22,61 @@ import java.util.Map;
/**
* This is the used for the LZWDecode filter.
*
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.4 $
+ * @author Ben Litchfield
*/
-class LZWNode
+final class LZWNode
{
private final long code;
- private final Map<Byte,LZWNode> subNodes = new HashMap<Byte,LZWNode>();
+ private final Map<Byte, LZWNode> subNodes = new HashMap<Byte, LZWNode>();
- public LZWNode( long codeValue )
+ public LZWNode(long codeValue)
{
code = codeValue;
}
- /**
+ /*
* This will get the number of children.
- *
- * @return The number of children.
*/
public int childCount()
{
return subNodes.size();
}
- /**
+ /*
* This will set the node for a particular byte.
- *
- * @param b The byte for that node.
- * @param node The node to add.
*/
- public void setNode( byte b, LZWNode node )
+ public void setNode(byte b, LZWNode node)
{
- subNodes.put( b, node );
+ subNodes.put(b, node);
}
- /**
+ /*
* This will get the node that is a direct sub node of this node.
- *
- * @param data The byte code to the node.
- *
- * @return The node at that value if it exists.
*/
- public LZWNode getNode( byte data )
+ public LZWNode getNode(byte data)
{
- return subNodes.get( data );
+ return subNodes.get(data);
}
-
- /**
+ /*
* This will traverse the tree until it gets to the sub node.
* This will return null if the node does not exist.
- *
- * @param data The path to the node.
- *
- * @return The node that resides at the data path.
*/
- public LZWNode getNode( byte[] data )
+ public LZWNode getNode(byte[] data)
{
LZWNode current = this;
- for( int i=0; i<data.length && current != null; i++ )
+ for (int i = 0; i < data.length && current != null; i++)
{
- current = current.getNode( data[i] );
+ current = current.getNode(data[i]);
}
return current;
}
- /** Getter for property code.
- * @return Value of property code.
+ /*
+ * Returns the property code
*/
public long getCode()
{
return code;
}
-
}