summaryrefslogtreecommitdiff
path: root/3dc/win95/iff_ILBM.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3dc/win95/iff_ILBM.cpp')
-rw-r--r--3dc/win95/iff_ILBM.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/3dc/win95/iff_ILBM.cpp b/3dc/win95/iff_ILBM.cpp
new file mode 100644
index 0000000..128f7ad
--- /dev/null
+++ b/3dc/win95/iff_ILBM.cpp
@@ -0,0 +1,327 @@
+#include "advwin32.h"
+#include "iff_ILBM.hpp"
+
+IFF_IMPLEMENT_DYNCREATE("ILBM","BMHD",IlbmBmhdChunk)
+IFF_IMPLEMENT_DYNCREATE("ILBM","CMAP",IlbmCmapChunk)
+IFF_IMPLEMENT_DYNCREATE("ILBM","BODY",IlbmBodyChunk)
+IFF_IMPLEMENT_DYNCREATE("ILBM","GRAB",IlbmGrabChunk)
+
+namespace IFF
+{
+ void IlbmBmhdChunk::Serialize(Archive * pArchv)
+ {
+ pArchv->Transfer(width);
+ pArchv->Transfer(height);
+ pArchv->Transfer(xTopLeft);
+ pArchv->Transfer(yTopLeft);
+ pArchv->Transfer(nBitPlanes);
+ pArchv->Transfer(eMasking);
+ pArchv->Transfer(eCompression);
+ pArchv->Transfer(flags);
+ pArchv->Transfer(iTranspCol);
+ pArchv->Transfer(xAspectRatio);
+ pArchv->Transfer(yAspectRatio);
+ pArchv->Transfer(xMax);
+ pArchv->Transfer(yMax);
+ }
+
+ void IlbmCmapChunk::Serialize(Archive * pArchv)
+ {
+ if (pArchv->m_bIsLoading)
+ {
+ nEntries = pArchv->GetSize()/3;
+ if (pTable) delete[] pTable;
+ pTable = new RGBTriple [nEntries];
+ }
+
+ for (unsigned i=0; i<nEntries; ++i)
+ pArchv->Transfer(pTable[i]);
+ }
+
+ IlbmCmapChunk::~IlbmCmapChunk()
+ {
+ if (pTable) delete[] pTable;
+ }
+
+ void IlbmBodyChunk::Serialize(Archive * pArchv)
+ {
+ if (pArchv->m_bIsLoading)
+ {
+ nSize = pArchv->GetSize();
+ if (pData) delete[] pData;
+ pData = new UBYTE [nSize];
+ }
+
+ pArchv->TransferBlock(pData,nSize);
+ }
+
+ bool IlbmBodyChunk::GetHeaderInfo() const
+ {
+ Chunk * pHdr = GetProperty("BMHD");
+ if (!pHdr)
+ {
+ return false;
+ }
+ nWidth = static_cast<IlbmBmhdChunk *>(pHdr)->width;
+ eCompression = static_cast<IlbmBmhdChunk *>(pHdr)->eCompression;
+ nBitPlanes = static_cast<IlbmBmhdChunk *>(pHdr)->nBitPlanes;
+ return true;
+ }
+
+ #ifndef IFF_READ_ONLY
+ bool IlbmBodyChunk::BeginEncode()
+ {
+ if (!GetHeaderInfo())
+ {
+ return false;
+ }
+
+ pEncodeDst = new DataBlock;
+ pEncodeSrc = new UBYTE [(nWidth+7)/8];
+
+ nSizeNonCprss = 0;
+ nSizeCprss = 0;
+
+ return true;
+ }
+
+// The uninitialised part of byte is shifted out.
+#ifdef _MSC_VER
+#pragma warning(disable: 4701)
+#endif
+ bool IlbmBodyChunk::EncodeNextRow(unsigned const * pRow)
+ {
+ if (!pEncodeDst) return false;
+
+ for (unsigned b=0; b<nBitPlanes; ++b)
+ {
+ UBYTE * pBuf = pEncodeSrc;
+
+ unsigned byte;
+ for (unsigned x=0; x<nWidth; ++x)
+ {
+ byte <<= 1;
+ byte |= pRow[x]>>b & 1;
+
+ if (7==(x&7)) *pBuf++ = static_cast<UBYTE>(byte);
+ }
+ if (nWidth & 7)
+ {
+ byte <<= 8-(nWidth & 7);
+ *pBuf = static_cast<UBYTE>(byte);
+ }
+
+ if (eCompression)
+ {
+ nSizeNonCprss += (nWidth+7)/8;
+
+ UBYTE const * pBuf = pEncodeSrc;
+ unsigned i=(nWidth+7)/8;
+
+ while (i)
+ {
+ if (1==i)
+ {
+ pEncodeDst->Append(0);
+ pEncodeDst->Append(*pBuf);
+ nSizeCprss += 2;
+ i=0;
+ }
+ else if (i>1)
+ {
+ if (pBuf[0]==pBuf[1])
+ {
+ unsigned j=2;
+ while (j<i && j<0x80 && pBuf[j-1]==pBuf[j])
+ ++j;
+ pEncodeDst->Append(static_cast<UBYTE>(0x101-j));
+ pEncodeDst->Append(*pBuf);
+ pBuf += j;
+ i -= j;
+ nSizeCprss += 2;
+ }
+ else
+ {
+ unsigned j=2;
+ while (j<i && j<0x80 && (pBuf[j]!=pBuf[j-1] || pBuf[j-1]!=pBuf[j-2]))
+ ++j;
+ if (j<i && pBuf[j]==pBuf[j-1] && pBuf[j-1]==pBuf[j-2])
+ j-=2;
+ pEncodeDst->Append(static_cast<UBYTE>(j-1));
+ pEncodeDst->Append(pBuf,j);
+ pBuf += j;
+ i -= j;
+ nSizeCprss += j+1;
+ }
+ }
+ }
+
+ }
+ else
+ {
+ pEncodeDst->Append(pEncodeSrc,(nWidth+7)/8);
+ }
+ }
+
+ return true;
+ }
+#ifdef _MSC_VER
+#pragma warning(default: 4701)
+#endif
+
+ bool IlbmBodyChunk::EndEncode()
+ {
+ if (!pEncodeDst) return false;
+
+ if (pData) delete[] pData;
+ nSize = pEncodeDst->GetDataSize();
+ pData = new UBYTE[nSize];
+
+ memcpy(pData,pEncodeDst->GetDataPtr(),nSize);
+
+ delete pEncodeDst;
+ delete[] pEncodeSrc;
+
+ pEncodeDst = NULL;
+ pEncodeSrc = NULL;
+
+ return true;
+ }
+ #endif
+
+ bool IlbmBodyChunk::BeginDecode() const
+ {
+ if (pDecodeDst) delete[] pDecodeDst;
+ if (!pData || !GetHeaderInfo())
+ {
+ pDecodeSrc = NULL;
+ pDecodeDst = NULL;
+ return false;
+ }
+
+ pDecodeSrc = pData;
+ nRemaining = nSize;
+
+ pDecodeDst = new unsigned [nWidth];
+
+ return pData != NULL;
+ }
+
+// The uninitialised part of pDecodeDst is shifted out.
+#ifdef _MSC_VER
+#pragma warning(disable: 4701)
+#endif
+ unsigned const * IlbmBodyChunk::DecodeNextRow() const
+ {
+ if (!pDecodeSrc || !pDecodeDst) return NULL;
+
+ for (unsigned x=0; x<nWidth; ++x)
+ pDecodeDst[x]=0;
+
+ if (eCompression)
+ {
+ unsigned repcnt = 0;
+ unsigned rawcnt = 0;
+
+ for (unsigned b=0; b<nBitPlanes; ++b)
+ {
+ unsigned byte;
+ for (unsigned x=0; x<nWidth; ++x)
+ {
+ if (!(x&7))
+ {
+ if (!nRemaining) return NULL;
+
+ REPEAT_SKIP:
+ byte = *pDecodeSrc;
+
+ if (rawcnt)
+ {
+ --rawcnt;
+ ++pDecodeSrc;
+ --nRemaining;
+ }
+ else if (repcnt)
+ {
+ --repcnt;
+ if (!repcnt)
+ {
+ ++pDecodeSrc;
+ --nRemaining;
+ }
+ }
+ else // byte is control byte
+ {
+ ++pDecodeSrc;
+ --nRemaining;
+
+ if (!nRemaining) return NULL;
+
+ if (byte<0x80)
+ {
+ rawcnt = byte;
+ byte = *pDecodeSrc++;
+ --nRemaining;
+ }
+ else if (byte>0x80)
+ {
+ repcnt = 0x100 - byte;
+ byte = *pDecodeSrc;
+ }
+ else goto REPEAT_SKIP;
+ }
+ }
+
+ pDecodeDst[x] |= (byte>>7 & 1)<<b;
+
+ byte <<= 1;
+ }
+
+ }
+ }
+ else
+ {
+ for (unsigned b=0; b<nBitPlanes; ++b)
+ {
+ unsigned byte;
+ for (unsigned x=0; x<nWidth; ++x)
+ {
+ if (!(x&7))
+ {
+ if (!nRemaining) return NULL;
+
+ byte = *pDecodeSrc++;
+ --nRemaining;
+ }
+
+ pDecodeDst[x] |= (byte>>7 & 1)<<b;
+
+ byte <<= 1;
+ }
+
+ }
+ }
+
+
+ return pDecodeDst;
+ }
+#ifdef _MSC_VER
+#pragma warning(default: 4701)
+#endif
+
+ IlbmBodyChunk::~IlbmBodyChunk()
+ {
+ if (pData) delete[] pData;
+ if (pDecodeDst) delete[] pDecodeDst;
+ #ifndef IFF_READ_ONLY
+ if (pEncodeDst) delete pEncodeDst;
+ if (pEncodeSrc) delete[] pEncodeSrc;
+ #endif
+ }
+
+ void IlbmGrabChunk::Serialize(Archive * pArchv)
+ {
+ pArchv->Transfer(xHotSpot);
+ pArchv->Transfer(yHotSpot);
+ }
+}