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