You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2014/07/20 10:37:31 UTC

svn commit: r1612055 - in /pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox: cos/COSName.java filter/LZWFilter.java

Author: tilman
Date: Sun Jul 20 08:37:30 2014
New Revision: 1612055

URL: http://svn.apache.org/r1612055
Log:
PDFBOX-2228: support LZW decoder EarlyChange parameter

Modified:
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java

Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1612055&r1=1612054&r2=1612055&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Sun Jul 20 08:37:30 2014
@@ -521,6 +521,11 @@ public final class COSName extends COSBa
     /**
      * A common COSName value.
      */
+    public static final COSName EARLY_CHANGE = new COSName("EarlyChange");
+
+    /**
+     * A common COSName value.
+     */
     public static final COSName EMBEDDED_FILES = new COSName( "EmbeddedFiles" );
 
     /**

Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java?rev=1612055&r1=1612054&r2=1612055&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/filter/LZWFilter.java Sun Jul 20 08:37:30 2014
@@ -86,9 +86,15 @@ public class LZWFilter implements Filter
         }
 
         int predictor = -1;
+        int earlyChange = 1;
         if (decodeParams != null)
         {
             predictor = decodeParams.getInt(COSName.PREDICTOR);
+            earlyChange = decodeParams.getInt(COSName.EARLY_CHANGE, 1);
+            if (earlyChange != 0 && earlyChange != 1)
+            {
+                earlyChange = 1;
+            }
         }
         if (predictor > 1)
         {
@@ -96,7 +102,7 @@ public class LZWFilter implements Filter
             int bitsPerPixel = decodeParams.getInt(COSName.BITS_PER_COMPONENT, 8);
             int columns = decodeParams.getInt(COSName.COLUMNS, 1);
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            doLZWDecode(compressedData, baos);
+            doLZWDecode(compressedData, baos, earlyChange);
             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
             Predictor.decodePredictor(predictor, colors, bitsPerPixel, columns, bais, result);
             result.flush();
@@ -105,11 +111,11 @@ public class LZWFilter implements Filter
         }
         else
         {
-            doLZWDecode(compressedData, result);
+            doLZWDecode(compressedData, result, earlyChange);
         }
     }
 
-    private void doLZWDecode(InputStream compressedData, OutputStream result) throws IOException
+    private void doLZWDecode(InputStream compressedData, OutputStream result, int earlyChange) throws IOException
     {
         ArrayList<byte[]> codeTable = null;
         int chunk = 9;
@@ -159,7 +165,7 @@ public class LZWFilter implements Filter
                         codeTable.add(newData);
                     }
 
-                    chunk = calculateChunk(codeTable.size());
+                    chunk = calculateChunk(codeTable.size(), earlyChange);
                     prevCommand = nextCommand;
                 }
             }
@@ -209,7 +215,7 @@ public class LZWFilter implements Filter
                 if (newFoundCode == -1)
                 {
                     // use previous
-                    chunk = calculateChunk(codeTable.size() - 1);
+                    chunk = calculateChunk(codeTable.size() - 1, 1);
                     out.writeBits(foundCode, chunk);
                     // create new table entry
                     codeTable.add(inputPattern);
@@ -236,7 +242,7 @@ public class LZWFilter implements Filter
         }
         if (foundCode != -1)
         {
-            chunk = calculateChunk(codeTable.size() - 1);
+            chunk = calculateChunk(codeTable.size() - 1, 1);
             out.writeBits(foundCode, chunk);
         }
 
@@ -245,7 +251,7 @@ public class LZWFilter implements Filter
         // possibly adjusted the chunk. Therefore, the encoder must behave as 
         // if the code table had just grown and thus it must be checked it is
         // needed to adjust the chunk, based on an increased table size parameter
-        chunk = calculateChunk(codeTable.size());
+        chunk = calculateChunk(codeTable.size(), 1);
 
         out.writeBits(EOD, chunk);
         out.writeBits(0, 7); // pad with 0
@@ -314,20 +320,21 @@ public class LZWFilter implements Filter
      * Calculate the appropriate chunk size
      *
      * @param tabSize the size of the code table
+     * @param earlyChange 0 or 1 for early chunk increase
      *
      * @return a value between 9 and 12
      */
-    private int calculateChunk(int tabSize)
+    private int calculateChunk(int tabSize, int earlyChange)
     {
-        if (tabSize >= 2047)
+        if (tabSize >= 2048 - earlyChange)
         {
             return 12;
         }
-        if (tabSize >= 1023)
+        if (tabSize >= 1024 - earlyChange)
         {
             return 11;
         }
-        if (tabSize >= 511)
+        if (tabSize >= 512 - earlyChange)
         {
             return 10;
         }