You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2014/01/02 18:00:02 UTC

svn commit: r1554847 - /pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java

Author: lehmi
Date: Thu Jan  2 17:00:02 2014
New Revision: 1554847

URL: http://svn.apache.org/r1554847
Log:
PDFBOX-1794: fixed a problem with the parsing of inline images based on a proposal by Tilman Hausherr

Modified:
    pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java

Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java?rev=1554847&r1=1554846&r2=1554847&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFStreamParser.java Thu Jan  2 17:00:02 2014
@@ -41,13 +41,12 @@ import org.apache.pdfbox.util.PDFOperato
  * This will parse a PDF byte stream and extract operands and such.
  *
  * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.32 $
+ * 
  */
 public class PDFStreamParser extends BaseParser
 {
     private List<Object> streamObjects = new ArrayList<Object>( 100 );
     private RandomAccess file;
-    private PDFOperator lastBIToken = null;
 
     /**
      * Constructor that takes a stream to parse.
@@ -355,12 +354,11 @@ public class PDFStreamParser extends Bas
             {
                 String next = readString();
                 retval = PDFOperator.getOperator( next );
-
                 if( next.equals( "BI" ) )
                 {
-                    lastBIToken = (PDFOperator)retval;
+                	PDFOperator beginImageOP = (PDFOperator)retval;
                     COSDictionary imageParams = new COSDictionary();
-                    lastBIToken.setImageParameters( new ImageParameters( imageParams ) );
+                    beginImageOP.setImageParameters( new ImageParameters( imageParams ) );
                     Object nextToken = null;
                     while( (nextToken = parseNextToken()) instanceof COSName )
                     {
@@ -369,16 +367,12 @@ public class PDFStreamParser extends Bas
                     }
                     //final token will be the image data, maybe??
                     PDFOperator imageData = (PDFOperator)nextToken;
-                    lastBIToken.setImageData( imageData.getImageData() );
+                    beginImageOP.setImageData( imageData.getImageData() );
                 }
                 break;
             }
             case 'I':
             {
-                //ImageParameters imageParams = lastBIToken.getImageParameters();
-
-                //int expectedBytes = (int)Math.ceil(imageParams.getHeight() * imageParams.getWidth() *
-                //                    (imageParams.getBitsPerComponent()/8) );
                 //Special case for ID operator
                 String id = "" + (char)pdfSource.read() + (char)pdfSource.read();
                 if( !id.equals( "ID" ) )
@@ -386,40 +380,29 @@ public class PDFStreamParser extends Bas
                     throw new IOException( "Error: Expected operator 'ID' actual='" + id + "'" );
                 }
                 ByteArrayOutputStream imageData = new ByteArrayOutputStream();
-                //boolean foundEnd = false;
-                if( this.isWhitespace() )
+                if( isWhitespace() )
                 {
                     //pull off the whitespace character
                     pdfSource.read();
                 }
-                int twoBytesAgo = 0;
                 int lastByte = pdfSource.read();
                 int currentByte = pdfSource.read();
-                int count = 0;
-                //PDF spec is kinda unclear about this.  Should a whitespace
-                //always appear before EI? Not sure, I found a PDF
-                //(UnderstandingWebSphereClassLoaders.pdf) which has EI as part
-                //of the image data and will stop parsing prematurely if there is
-                //not a check for <whitespace>EI<whitespace>.
-                while( !(isWhitespace( twoBytesAgo ) &&
-                         lastByte == 'E' &&
+                // PDF spec is kinda unclear about this. Should a whitespace
+                // always appear before EI? Not sure, so that we just read
+                // until EI<whitespace>.
+                // Be aware not all kind of whitespaces are allowed here. see PDFBOX1561
+                while( !(lastByte == 'E' &&
                          currentByte == 'I' &&
-                         isWhitespace() //&&
-                         //amyuni2_05d__pdf1_3_acro4x.pdf has image data that
-                         //is compressed, so expectedBytes is useless here.
-                         //count >= expectedBytes
-                         ) &&
+                         isSpaceOrReturn()) &&
                        !pdfSource.isEOF() )
                 {
                     imageData.write( lastByte );
-                    twoBytesAgo = lastByte;
                     lastByte = currentByte;
                     currentByte = pdfSource.read();
-                    count++;
                 }
-                pdfSource.unread( 'I' ); //unread the EI operator
-                pdfSource.unread( 'E' );
+                // the EI operator isn't unread, as it won't be processed anyway
                 retval = PDFOperator.getOperator( "ID" );
+                // save the image data to the operator, so that it can be accessed it later
                 ((PDFOperator)retval).setImageData( imageData.toByteArray() );
                 break;
             }
@@ -489,4 +472,21 @@ public class PDFStreamParser extends Bas
         }
         return buffer.toString();
     }
+    
+    private boolean isSpaceOrReturn( int c )
+    {
+        return c == 10 || c == 13 || c == 32;
+    }
+
+    /**
+     * Checks if the next char is a space or a return.
+     * 
+     * @return true if the next char is a space or a return
+     * @throws IOException if something went wrong
+     */
+    private boolean isSpaceOrReturn() throws IOException
+    {
+        return isSpaceOrReturn( pdfSource.peek() );
+    }
+
 }