|
|
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 |
|