summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2017-03-30 21:10:46 +0100
committerCaolán McNamara <caolanm@redhat.com>2017-03-30 21:14:48 +0100
commitbb3715b6283f0d828be92065016d7b65d8671088 (patch)
tree4aca5e6c9f954b93a3f0efe34866e8780bffb529 /filter
parent30d58306a93d4325f6388b8d05b9db91026c7c55 (diff)
ofz#967 optimize tiff import if line is the same as previous line
Change-Id: Ided61679a579a73481320f85c05b03e3ce3d762a
Diffstat (limited to 'filter')
-rw-r--r--filter/qa/cppunit/data/tiff/pass/multi-page-1.tiffbin0 -> 1202 bytes
-rw-r--r--filter/source/graphicfilter/itiff/ccidecom.cxx37
-rw-r--r--filter/source/graphicfilter/itiff/ccidecom.hxx18
-rw-r--r--filter/source/graphicfilter/itiff/itiff.cxx22
4 files changed, 53 insertions, 24 deletions
diff --git a/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff b/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff
new file mode 100644
index 000000000000..8eb7c8078054
--- /dev/null
+++ b/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff
Binary files differ
diff --git a/filter/source/graphicfilter/itiff/ccidecom.cxx b/filter/source/graphicfilter/itiff/ccidecom.cxx
index b5f3ab4cf529..a7d0ffc49f14 100644
--- a/filter/source/graphicfilter/itiff/ccidecom.cxx
+++ b/filter/source/graphicfilter/itiff/ccidecom.cxx
@@ -624,18 +624,17 @@ void CCIDecompressor::StartDecompression( SvStream & rIStream )
return;
}
-
-bool CCIDecompressor::DecompressScanline( sal_uInt8 * pTarget, sal_uLong nTargetBits, bool bLastLine )
+DecompressStatus CCIDecompressor::DecompressScanline( sal_uInt8 * pTarget, sal_uLong nTargetBits, bool bLastLine )
{
//Read[1|2]DScanlineData take a sal_uInt16, so its either limit here or expand there
if (nTargetBits > SAL_MAX_UINT16)
- return false;
+ return DecompressStatus(false, true);
if ( nEOLCount >= 5 ) // RTC (Return To Controller)
- return true;
+ return DecompressStatus(true, true);
if ( !bStatus )
- return false;
+ return DecompressStatus(false, true);
// If EOL-Codes exist, the EOL-Code also appeared in front of the first line.
// (and I thought it means 'End of Line'...)
@@ -660,13 +659,13 @@ bool CCIDecompressor::DecompressScanline( sal_uInt8 * pTarget, sal_uLong nTarget
{
if ( !ReadEOL( nTargetBits ) )
{
- return bStatus;
+ return DecompressStatus(bStatus, true);
}
}
}
if ( nEOLCount >= 5 ) // RTC (Return To Controller)
- return true;
+ return DecompressStatus(true, true);
// should the situation arise, generate a white previous line for 2D:
if ( nOptions & CCI_OPTION_2D )
@@ -696,11 +695,12 @@ bool CCIDecompressor::DecompressScanline( sal_uInt8 * pTarget, sal_uLong nTarget
else
b2D = false;
+ bool bUnchanged;
// read scanline:
if ( b2D )
- Read2DScanlineData( pTarget, (sal_uInt16)nTargetBits );
+ bUnchanged = Read2DScanlineData(pTarget, nTargetBits);
else
- Read1DScanlineData( pTarget, (sal_uInt16)nTargetBits );
+ bUnchanged = Read1DScanlineData(pTarget, nTargetBits);
// if we're in 2D mode we have to remember the line:
if ( nOptions & CCI_OPTION_2D && bStatus )
@@ -717,7 +717,7 @@ bool CCIDecompressor::DecompressScanline( sal_uInt8 * pTarget, sal_uLong nTarget
if ( pIStream->GetError() )
bStatus = false;
- return bStatus;
+ return DecompressStatus(bStatus, bUnchanged);
}
@@ -923,8 +923,9 @@ sal_uInt16 CCIDecompressor::CountBits(const sal_uInt8 * pData, sal_uInt16 nDataS
return nPos-nBitPos;
}
-void CCIDecompressor::Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits)
+bool CCIDecompressor::Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nBitsToRead)
{
+ sal_uInt16 nTargetBits = nBitsToRead;
sal_uInt16 nCode,nCodeBits,nDataBits,nTgtFreeByteBits;
sal_uInt8 nByte;
sal_uInt8 nBlackOrWhite; // is 0xff for black or 0x00 for white
@@ -962,11 +963,11 @@ void CCIDecompressor::Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTarget
// is that an invalid code?
if ( nDataBits == 9999 )
{
- return;
+ return nTargetBits == nBitsToRead;
}
if ( nCodeBits == 0 )
{
- return; // could be filling bits now
+ return nTargetBits == nBitsToRead; // could be filling bits now
}
nEOLCount = 0;
// too much data?
@@ -1017,10 +1018,11 @@ void CCIDecompressor::Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTarget
if (bTerminatingCode) nBlackOrWhite = ~nBlackOrWhite;
} while (nTargetBits>0 || !bTerminatingCode);
-}
+ return nTargetBits == nBitsToRead;
+}
-void CCIDecompressor::Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits)
+bool CCIDecompressor::Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits)
{
sal_uInt16 n2DMode,nBitPos,nUncomp,nRun,nRun2,nt;
sal_uInt8 nBlackOrWhite;
@@ -1032,7 +1034,7 @@ void CCIDecompressor::Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTarget
n2DMode=ReadCodeAndDecode(p2DModeLookUp,10);
if (!bStatus)
- return;
+ return nBitPos == 0;
if (n2DMode==CCI2DMODE_UNCOMP) {
for (;;) {
@@ -1114,7 +1116,8 @@ void CCIDecompressor::Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTarget
nBlackOrWhite=~nBlackOrWhite;
}
}
-}
+ return nBitPos == 0;
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/itiff/ccidecom.hxx b/filter/source/graphicfilter/itiff/ccidecom.hxx
index c92769df6576..02c7a16acf8a 100644
--- a/filter/source/graphicfilter/itiff/ccidecom.hxx
+++ b/filter/source/graphicfilter/itiff/ccidecom.hxx
@@ -45,6 +45,16 @@ struct CCILookUpTableEntry {
class SvStream;
+struct DecompressStatus
+{
+ bool m_bSuccess;
+ bool m_bBufferUnchanged;
+ DecompressStatus(bool bSuccess, bool bBufferUnchanged)
+ : m_bSuccess(bSuccess), m_bBufferUnchanged(bBufferUnchanged)
+ {
+ }
+};
+
class CCIDecompressor {
public:
@@ -54,7 +64,7 @@ public:
void StartDecompression( SvStream & rIStream );
- bool DecompressScanline(sal_uInt8 * pTarget, sal_uLong nTargetBits, bool bLastLine );
+ DecompressStatus DecompressScanline(sal_uInt8 * pTarget, sal_uLong nTargetBits, bool bLastLine);
private:
@@ -80,9 +90,9 @@ private:
static sal_uInt16 CountBits(const sal_uInt8 * pData, sal_uInt16 nDataSizeBits,
sal_uInt16 nBitPos, sal_uInt8 nBlackOrWhite);
- void Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits);
-
- void Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits);
+ //returns true if pTarget was unmodified
+ bool Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits);
+ bool Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits);
bool bTableBad;
diff --git a/filter/source/graphicfilter/itiff/itiff.cxx b/filter/source/graphicfilter/itiff/itiff.cxx
index 560056c6fa85..6fd5448e55a6 100644
--- a/filter/source/graphicfilter/itiff/itiff.cxx
+++ b/filter/source/graphicfilter/itiff/itiff.cxx
@@ -598,8 +598,10 @@ bool TIFFReader::ReadMap()
aCCIDecom.StartDecompression( *pTIFF );
+ bool bDifferentToPrev;
for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
{
+ bDifferentToPrev = ny == 0;
for (sal_uLong np = 0; np < nPlanes; np++ )
{
if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
@@ -615,13 +617,27 @@ bool TIFFReader::ReadMap()
}
if (np >= SAL_N_ELEMENTS(pMap))
return false;
- if ( !aCCIDecom.DecompressScanline( pMap[ np ], nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes ) )
+ DecompressStatus aResult = aCCIDecom.DecompressScanline(pMap[np],nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes);
+ if (!aResult.m_bSuccess)
return false;
+ bDifferentToPrev |= !aResult.m_bBufferUnchanged;
if ( pTIFF->GetError() )
return false;
}
- if ( !ConvertScanline( ny ) )
- return false;
+ if (!bDifferentToPrev)
+ {
+ //if the buffer for this line didn't change, then just copy the
+ //previous scanline instead of painfully decoding and setting
+ //each pixel one by one again
+ pAcc->CopyScanline(ny, pAcc->GetScanline(ny-1),
+ pAcc->GetScanlineFormat(),
+ pAcc->GetScanlineSize());
+ }
+ else
+ {
+ if (!ConvertScanline(ny))
+ return false;
+ }
}
}
else if ( nCompression == 5 )