diff options
Diffstat (limited to '3dc/win95/iff_ILBM.cpp')
| -rw-r--r-- | 3dc/win95/iff_ILBM.cpp | 327 |
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); + } +} |
