[Libreoffice-commits] core.git: filter/qa filter/source

Caolán McNamara caolanm at redhat.com
Thu Mar 30 20:15:55 UTC 2017


 filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff |binary
 filter/source/graphicfilter/itiff/ccidecom.cxx     |   37 +++++++++++----------
 filter/source/graphicfilter/itiff/ccidecom.hxx     |   18 +++++++---
 filter/source/graphicfilter/itiff/itiff.cxx        |   22 ++++++++++--
 4 files changed, 53 insertions(+), 24 deletions(-)

New commits:
commit bb3715b6283f0d828be92065016d7b65d8671088
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Mar 30 21:10:46 2017 +0100

    ofz#967 optimize tiff import if line is the same as previous line
    
    Change-Id: Ided61679a579a73481320f85c05b03e3ce3d762a

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
Binary files /dev/null and b/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff 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 )


More information about the Libreoffice-commits mailing list