Hi,
Here are four patches which I've been sitting on for a couple of months.
The important one is rle.patch, which corrects a signed char bug in RLE
decoding, much like the one that Michael Marsella reported this week in
PdfString. In addition to fixing that bug, the patch also buffers
output to minimise I/O.
The imgextract.patch adds support for indexed colour tables to
podofoimgextract.
The codingstyle.patch clarifies the relationship between DLL-style
shared libraries and problems which result from different
implementations of malloc/free between DLL and client.
Finally, there's a potential infinite loop in podofoimpose. The
impose-translator.patch adds an exception for that case.
Regards,
David
diff -r -u -w podofo-devel.orig/CODINGSTYLE.txt podofo-devel/CODINGSTYLE.txt
--- podofo-devel.orig/CODINGSTYLE.txt 2010-05-29 05:41:57.000000000 +0930
+++ podofo-devel/CODINGSTYLE.txt 2010-05-29 04:21:54.000000000 +0930
@@ -262,12 +262,13 @@
3.7 Memory allocations in inlined methods
It's not safe to (directly) allocate or free
- heap memory in an inlined function, because it only works if the same
- runtime library is used in the shared library and the executable linking
- to the library. Using malloc and/or new in inlined methods will lead to
- crashes on MS Windows systems. It might be undetected on Linux systems
- (even though it is bad style on Linux, too), because most processes and
- libraries use the same runtime library on a Linux system.
+ heap memory in an inlined function, because it can cause crashes on
+ MS Windows systems if the runtime library used in the shared library
+ is different from the one used by the executable calling that DLL.
+ Using malloc and/or new in inlined methods will lead to
+ crashes on MS Windows systems. This is only an issue for OSes which
+ run shared libraries as independant processes. (Neither Linux nor
+ UNIX do this.)
There's also no point inlining functions that call new / delete /
malloc / free, because the memory allocation is dramatically more
diff -r -u -w podofo-devel.orig/tools/podofoimgextract/ImageExtractor.cpp podofo-devel/tools/podofoimgextract/ImageExtractor.cpp
--- podofo-devel.orig/tools/podofoimgextract/ImageExtractor.cpp 2010-05-29 05:41:57.000000000 +0930
+++ podofo-devel/tools/podofoimgextract/ImageExtractor.cpp 2010-05-29 05:24:48.000000000 +0930
@@ -61,26 +65,18 @@
{
if( (*it)->IsDictionary() )
{
+ // Type is optional, but must be XObject if present. SubType is mandatory and must be Image
PdfObject* pObjType = (*it)->GetDictionary().GetKey( PdfName::KeyType );
PdfObject* pObjSubType = (*it)->GetDictionary().GetKey( PdfName::KeySubtype );
- if( ( pObjType && pObjType->IsName() && ( pObjType->GetName().GetName() == "XObject" ) ) ||
- ( pObjSubType && pObjSubType->IsName() && ( pObjSubType->GetName().GetName() == "Image" ) ) )
+ if( ( !pObjType || (pObjType->IsName() && ( pObjType->GetName() == "XObject" ))) &&
+ ( pObjSubType && pObjSubType->IsName() && ( pObjSubType->GetName() == "Image" ) ) )
{
pObj = (*it)->GetDictionary().GetKey( PdfName::KeyFilter );
- if( pObj && pObj->IsArray() && pObj->GetArray().GetSize() == 1 &&
- pObj->GetArray()[0].IsName() && (pObj->GetArray()[0].GetName().GetName() == "DCTDecode") )
+ if( pObj && pObj->IsArray() && pObj->GetArray().GetSize() == 1 )
pObj = &pObj->GetArray()[0];
- if( pObj && pObj->IsName() && ( pObj->GetName().GetName() == "DCTDecode" ) )
- {
// The only filter is JPEG -> create a JPEG file
- ExtractImage( *it, true );
- }
- else
- {
- ExtractImage( *it, false );
- }
-
+ ExtractImage( *it, pObj && pObj->IsName() && ( pObj->GetName() == "DCTDecode" ) );
document.FreeObjectMemory( *it );
}
}
@@ -114,22 +110,80 @@
}
else
{
- //long lBitsPerComponent = pObject->GetDictionary().GetKey( PdfName("BitsPerComponent" ) )->GetNumber();
- // TODO: Handle colorspaces
-
// Create a ppm image
const char* pszPpmHeader = "P6\n# Image extracted by PoDoFo\n%li %li\n%li\n";
+ pdf_long width = pObject->GetDictionary().GetKey( PdfName("Width" ) )->GetNumber();
+ pdf_long height = pObject->GetDictionary().GetKey( PdfName("Height" ) )->GetNumber();
-
- fprintf( hFile, pszPpmHeader,
- pObject->GetDictionary().GetKey( PdfName("Width" ) )->GetNumber(),
- pObject->GetDictionary().GetKey( PdfName("Height" ) )->GetNumber(),
- 255 );
+ fprintf( hFile, pszPpmHeader, width, height, 255 );
char* pBuffer;
pdf_long lLen;
pObject->GetStream()->GetFilteredCopy( &pBuffer, &lLen );
+
+ // indexed DeviceGray or DeviceRGB colorspace
+ PdfObject* pColorSpace = pObject->GetDictionary().GetKey( PdfName("ColorSpace"));
+ if ( pColorSpace && pColorSpace->IsArray() && pColorSpace->GetArray().GetSize() == 4 &&
+ pColorSpace->GetArray()[0].GetName() == "Indexed" )
+ try {
+ // using proper, English spelling of "colour"
+ // TODO: colour table from stream
+ const char* pColourTable(pColorSpace->GetArray()[3].GetString().GetString());
+ unsigned maxColour(pColorSpace->GetArray()[2].GetNumber());
+ unsigned nColours = 0; // nColours = width of each entry in colour table
+ pColorSpace = &pColorSpace->GetArray()[1];
+
+ if (!pColorSpace)
+ ;
+ else if ( pColorSpace->GetName() == "DeviceRGB" )
+ nColours = 3;
+ else if ( pColorSpace->GetName() == "DeviceGray" )
+ nColours = 1;
+
+ if (!nColours)
+ PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor );
+
+ unsigned char *samples = reinterpret_cast<unsigned char*>(pBuffer);
+ unsigned nBits;
+ if (maxColour < 2)
+ nBits = 1;
+ else if (maxColour < 4)
+ nBits = 2;
+ else if (maxColour < 16)
+ nBits = 4;
+ else if (maxColour < 256)
+ nBits = 8;
+ else
+ PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
+
+ unsigned colsLeft = 0;
+ while (lLen--)
+ {
+ int rshift = 8 - nBits;
+ unsigned char datum = *samples++;
+ unsigned char mask = static_cast<unsigned char>(0xff << rshift);
+ if (colsLeft == 0)
+ colsLeft = width;
+ for ( ; mask && colsLeft ; mask >>= nBits, rshift -= nBits, colsLeft--)
+ {
+ unsigned idx = (datum & mask) >> rshift;
+ if (idx > maxColour)
+ PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange );
+ fwrite( pColourTable + idx * nColours, nColours, sizeof(char), hFile );
+ }
+ }
+ } catch (PdfError &e) {
+ fclose(hFile);
+ free(pBuffer);
+ throw e;
+ }
+
+ //long lBitsPerComponent = pObject->GetDictionary().GetKey( PdfName("BitsPerComponent" ) )->GetNumber();
+ // TODO: Handle more colorspaces
+
+ else
fwrite( pBuffer, lLen, sizeof(char), hFile );
+
free( pBuffer );
}
diff -r -u -w podofo-devel.orig/tools/podofoimpose/pdftranslator.cpp podofo-devel/tools/podofoimpose/pdftranslator.cpp
--- podofo-devel.orig/tools/podofoimpose/pdftranslator.cpp 2010-05-29 05:41:57.000000000 +0930
+++ podofo-devel/tools/podofoimpose/pdftranslator.cpp 2010-05-28 23:47:20.000000000 +0930
@@ -278,6 +278,8 @@
co->GetStream()->GetFilteredCopy ( &outMemStream );
break;
}
+ else // XXX
+ throw std::logic_error ( "Infinite loop ensues" );
}
}
diff -r -u -w podofo-devel.orig/src/PdfFiltersPrivate.cpp podofo-devel/src/PdfFiltersPrivate.cpp
--- podofo-devel.orig/src/PdfFiltersPrivate.cpp 2010-05-29 05:41:55.000000000 +0930
+++ podofo-devel/src/PdfFiltersPrivate.cpp 2010-05-27 20:35:58.000000000 +0930
@@ -570,32 +570,34 @@
void PdfRLEFilter::BeginDecodeImpl( const PdfDictionary* )
{
- m_nCodeLen = 0;
+ m_nCodeLen = -1;
}
void PdfRLEFilter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen )
{
while( lLen-- )
{
- if( !m_nCodeLen )
+ if( m_nCodeLen == -1)
{
- m_nCodeLen = static_cast<int>(*pBuffer);
+ m_nCodeLen = static_cast<unsigned char>(*pBuffer++);
} else if( m_nCodeLen == 128 )
break;
else if( m_nCodeLen <= 127 )
{
- GetStream()->Write( pBuffer, 1 );
- m_nCodeLen--;
+ unsigned xfer = ((m_nCodeLen < lLen) ? m_nCodeLen : lLen) + 1;
+ GetStream()->Write( pBuffer, xfer );
+ lLen -= xfer - 1; // already subtracted 1 from lLen in while() test
+ pBuffer += xfer;
+ m_nCodeLen -= xfer;
}
else if( m_nCodeLen >= 129 )
{
m_nCodeLen = 257 - m_nCodeLen;
-
- while( m_nCodeLen-- )
- GetStream()->Write( pBuffer, 1 );
+ char buf[m_nCodeLen];
+ memset(buf, *pBuffer++, m_nCodeLen);
+ GetStream()->Write( buf, m_nCodeLen );
+ m_nCodeLen = -1;
}
-
- ++pBuffer;
}
}
------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the
lucky parental unit. See the prize list and enter to win:
http://p.sf.net/sfu/thinkgeek-promo
_______________________________________________
Podofo-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/podofo-users