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() );
+ }
+
}