Blame SOURCES/0005-ClarisWorks-parser-try-to-reconstruct-compressed-bit.patch

b5c349
From b814213e898e9f394fac3dc07102baae1aba5304 Mon Sep 17 00:00:00 2001
b5c349
From: osnola <alonso@loria.fr>
b5c349
Date: Sun, 1 Dec 2013 09:38:52 +0100
b5c349
Subject: [PATCH 5/8] ClarisWorks parser: try to reconstruct compressed bitmap
b5c349
 ...
b5c349
b5c349
(cherry picked from commit ecbabfcc912700602abba3c56543845d1cd243a8)
b5c349
Signed-off-by: osnola <alonso@loria.fr>
b5c349
b5c349
Conflicts:
b5c349
	src/lib/CWGraph.cxx
b5c349
---
b5c349
 src/lib/CWGraph.cxx | 89 ++++++++++++++++++++++++++++++++++++++++-------------
b5c349
 1 file changed, 67 insertions(+), 22 deletions(-)
b5c349
b5c349
diff --git a/src/lib/CWGraph.cxx b/src/lib/CWGraph.cxx
b5c349
index 01109f6..52f2a5c 100644
b5c349
--- a/src/lib/CWGraph.cxx
b5c349
+++ b/src/lib/CWGraph.cxx
b5c349
@@ -311,20 +311,24 @@ struct ZonePict : public Zone {
b5c349
 struct Bitmap : public CWStruct::DSET {
b5c349
   //! constructor
b5c349
   Bitmap(CWStruct::DSET const &dset = CWStruct::DSET()) :
b5c349
-    DSET(dset), m_bitmapType(-1), m_bitmapSize(0,0), m_entry(), m_colorMap() {
b5c349
+    DSET(dset), m_numBytesPerPixel(0), m_bitmapSize(0,0), m_bitmapRowSize(0), m_entry(), m_colorMap()
b5c349
+  {
b5c349
   }
b5c349
 
b5c349
   //! operator<<
b5c349
   friend std::ostream &operator<<(std::ostream &o, Bitmap const &bt) {
b5c349
     o << static_cast<CWStruct::DSET const &>(bt);
b5c349
-    if (bt.m_bitmapType >= 0) o << "type=" << bt.m_bitmapType << ",";
b5c349
+    if (bt.m_numBytesPerPixel > 0) o << "type=" << bt.m_numBytesPerPixel << ",";
b5c349
+    else if (bt.m_numBytesPerPixel < 0) o << "type=1/" << (-bt.m_numBytesPerPixel) << ",";
b5c349
     return o;
b5c349
   }
b5c349
 
b5c349
-  //! the bitmap type
b5c349
-  int m_bitmapType;
b5c349
+  //! the number of bite by pixel
b5c349
+  int m_numBytesPerPixel;
b5c349
   //! the bitmap size
b5c349
   Vec2i m_bitmapSize;
b5c349
+  //! the bitmap row size in the file ( with potential alignement)
b5c349
+  int m_bitmapRowSize;
b5c349
   //! the bitmap entry
b5c349
   MWAWEntry m_entry;
b5c349
   //! the color map
b5c349
@@ -1992,33 +1996,52 @@ bool CWGraph::readBitmapData(CWGraphInternal::Bitmap &zone)
b5c349
     MWAW_DEBUG_MSG(("CWGraph::readBitmapData: file is too short\n"));
b5c349
     return false;
b5c349
   }
b5c349
-  /* Fixme: this code can not works for the packed bitmap*/
b5c349
-  long numColors = zone.m_bitmapSize[0]*zone.m_bitmapSize[1];
b5c349
-  int numBytes = numColors ? int(sz/numColors) : 0;
b5c349
-  if (sz != numBytes*numColors) {
b5c349
+
b5c349
+  long numPixels = zone.m_bitmapSize[0]*zone.m_bitmapSize[1];
b5c349
+  if (numPixels<=0) {
b5c349
+    MWAW_DEBUG_MSG(("CWGraph::readBitmapData: unexpected empty size\n"));
b5c349
+    return false;
b5c349
+  }
b5c349
+
b5c349
+  int numBytesPerPixel = int(sz/numPixels);
b5c349
+  int bitmapRowSize=zone.m_bitmapSize[0]*numBytesPerPixel;
b5c349
+  if (sz < numPixels) {
b5c349
+    int nHalfPixel=(zone.m_bitmapSize[0]+1)/2;
b5c349
+    for (int align=1; align <= 4; align*=2) {
b5c349
+      int diffToAlign=align==1 ? 0 : align-(nHalfPixel%align);
b5c349
+      if (diffToAlign==align) continue;
b5c349
+      if (sz == (nHalfPixel+diffToAlign)*zone.m_bitmapSize[1]) {
b5c349
+        bitmapRowSize=(nHalfPixel+diffToAlign);
b5c349
+        numBytesPerPixel=-2;
b5c349
+        break;
b5c349
+      }
b5c349
+    }
b5c349
+  }
b5c349
+  else if (sz > numBytesPerPixel*numPixels) {
b5c349
     // check for different row alignement: 2 and 4
b5c349
     for (int align=2; align <= 4; align*=2) {
b5c349
       int diffToAlign=align-(zone.m_bitmapSize[0]%align);
b5c349
       if (diffToAlign==align) continue;
b5c349
-      numColors = (zone.m_bitmapSize[0]+diffToAlign)*zone.m_bitmapSize[1];
b5c349
-      numBytes = numColors ? int(sz/numColors) : 0;
b5c349
-      if (sz == numBytes*numColors) {
b5c349
-        zone.m_bitmapSize[0]+=diffToAlign;
b5c349
-        MWAW_DEBUG_MSG(("CWGraph::readBitmapData: increase width to %d\n",zone.m_bitmapSize[0]));
b5c349
+      numPixels = (zone.m_bitmapSize[0]+diffToAlign)*zone.m_bitmapSize[1];
b5c349
+      numBytesPerPixel = int(sz/numPixels);
b5c349
+      if (sz == numBytesPerPixel*numPixels) {
b5c349
+        bitmapRowSize=(zone.m_bitmapSize[0]+diffToAlign)*numBytesPerPixel;
b5c349
         break;
b5c349
       }
b5c349
     }
b5c349
   }
b5c349
-  if (sz != numBytes*numColors) {
b5c349
+
b5c349
+  if (sz != bitmapRowSize*zone.m_bitmapSize[1]) {
b5c349
     MWAW_DEBUG_MSG(("CWGraph::readBitmapData: unexpected size\n"));
b5c349
     return false;
b5c349
   }
b5c349
-  zone.m_bitmapType = numBytes;
b5c349
+  zone.m_numBytesPerPixel = numBytesPerPixel;
b5c349
+  zone.m_bitmapRowSize = bitmapRowSize;
b5c349
   zone.m_entry.setBegin(pos+4);
b5c349
   zone.m_entry.setEnd(endPos);
b5c349
   libmwaw::DebugFile &ascFile = m_parserState->m_asciiFile;
b5c349
   libmwaw::DebugStream f;
b5c349
-  f << "Entries(BitmapData):nBytes=" << numBytes;
b5c349
+  f << "Entries(BitmapData):[" << numBytesPerPixel << "]";
b5c349
   ascFile.addPos(pos);
b5c349
   ascFile.addNote(f.str().c_str());
b5c349
   ascFile.skipZone(pos+4, endPos-1);
b5c349
@@ -2615,9 +2638,13 @@ bool CWGraph::sendBitmap(int number, bool asGraphic, MWAWPosition const &pos)
b5c349
 
b5c349
 bool CWGraph::sendBitmap(CWGraphInternal::Bitmap &bitmap, bool asGraphic, MWAWPosition pos)
b5c349
 {
b5c349
-  if (!bitmap.m_entry.valid() || !bitmap.m_bitmapType)
b5c349
+  if (!bitmap.m_entry.valid() || !bitmap.m_numBytesPerPixel)
b5c349
     return false;
b5c349
-
b5c349
+  int bytesPerPixel = bitmap.m_numBytesPerPixel;
b5c349
+  if (bytesPerPixel<0 && (bytesPerPixel!=-2 && bytesPerPixel!=-4)) {
b5c349
+    MWAW_DEBUG_MSG(("CWGraph::sendBitmap: unknown group of color\n"));
b5c349
+    return false;
b5c349
+  }
b5c349
   if (asGraphic) {
b5c349
     if  (!m_parserState->m_graphicListener ||
b5c349
          !m_parserState->m_graphicListener->isDocumentStarted()) {
b5c349
@@ -2637,21 +2664,38 @@ bool CWGraph::sendBitmap(CWGraphInternal::Bitmap &bitmap, bool asGraphic, MWAWPo
b5c349
     bmapIndexed->setColors(bitmap.m_colorMap);
b5c349
     bmap.reset(bmapIndexed);
b5c349
     indexed = true;
b5c349
-  } else
b5c349
+  }
b5c349
+  else {
b5c349
+    if (bytesPerPixel<0) {
b5c349
+      MWAW_DEBUG_MSG(("CWGraph::sendBitmap: unexpected mode for compressed bitmap. Bitmap ignored.\n"));
b5c349
+      return false;
b5c349
+    }
b5c349
     bmap.reset((bmapColor=new MWAWPictBitmapColor(bitmap.m_bitmapSize)));
b5c349
+  }
b5c349
 
b5c349
+  bool const isCompressed =  bytesPerPixel<0;
b5c349
+  int const numColorByData= isCompressed ? -bytesPerPixel : 1;
b5c349
+  long const colorMask= !isCompressed ? 0 : numColorByData==2 ? 0xF : 0x3;
b5c349
+  int const numColorBytes = isCompressed ? 8/numColorByData : 8*bytesPerPixel;
b5c349
   //! let go
b5c349
-  int fSz = bitmap.m_bitmapType;
b5c349
   MWAWInputStreamPtr &input= m_parserState->m_input;
b5c349
   input->seek(bitmap.m_entry.begin(), WPX_SEEK_SET);
b5c349
   for (int r = 0; r < bitmap.m_bitmapSize[1]; r++) {
b5c349
+    long rPos=input->tell();
b5c349
+    int numRead=0;
b5c349
+    long read=0;
b5c349
     for (int c = 0; c < bitmap.m_bitmapSize[0]; c++) {
b5c349
-      long val = (long) input->readULong(fSz);
b5c349
+      if (numRead==0) {
b5c349
+        read=(long) input->readULong(isCompressed ? 1 : bytesPerPixel);
b5c349
+        numRead=numColorByData;
b5c349
+      }
b5c349
+      --numRead;
b5c349
+      long val=!isCompressed ? read : (read>>(numColorBytes*numRead))&colorMask;
b5c349
       if (indexed) {
b5c349
         bmapIndexed->set(c,r,(int)val);
b5c349
         continue;
b5c349
       }
b5c349
-      switch(fSz) {
b5c349
+      switch (bytesPerPixel) {
b5c349
       case 1:
b5c349
         bmapColor->set(c,r, MWAWColor((unsigned char)val,(unsigned char)val,(unsigned char)val));
b5c349
         break;
b5c349
@@ -2671,6 +2715,7 @@ bool CWGraph::sendBitmap(CWGraphInternal::Bitmap &bitmap, bool asGraphic, MWAWPo
b5c349
       }
b5c349
       }
b5c349
     }
b5c349
+    input->seek(rPos+bitmap.m_bitmapRowSize, WPX_SEEK_SET);
b5c349
   }
b5c349
 
b5c349
   WPXBinaryData data;
b5c349
-- 
b5c349
1.9.0
b5c349