diff options
| author | Steven Fuller <relnev@icculus.org> | 2001-07-01 00:55:22 +0000 |
|---|---|---|
| committer | Patryk Obara <dreamer.tan@gmail.com> | 2019-08-20 02:09:04 +0200 |
| commit | 2186d5f3f95cd74a070a490d899291648d58667a (patch) | |
| tree | 55241a1afa3e1a22e0b6593a8dead0b703800f44 /3dc/win95/awIffLd.cpp | |
| parent | 218ca90543758a20ac326e444ca0643174ca7384 (diff) | |
Initial revision
Diffstat (limited to '3dc/win95/awIffLd.cpp')
| -rw-r--r-- | 3dc/win95/awIffLd.cpp | 507 |
1 files changed, 0 insertions, 507 deletions
diff --git a/3dc/win95/awIffLd.cpp b/3dc/win95/awIffLd.cpp deleted file mode 100644 index de3be19..0000000 --- a/3dc/win95/awIffLd.cpp +++ /dev/null @@ -1,507 +0,0 @@ -#include "advwin32.h" -#ifndef DB_LEVEL -#define DB_LEVEL 4 -#endif -#include "db.h" -#ifndef DB_COMMA - #define DB_COMMA , -#endif - -#pragma warning(disable: 4701) -#include "awTexLd.hpp" -#pragma warning(default: 4701) - -#include "iff.hpp" -#include "iff_ILBM.hpp" - -#include "list_tem.hpp" - -#include <limits.h> - -// conversion functors for IFF loader -class AwIffConvNull -{ - public: - static inline unsigned DoConv (unsigned const * _colP, AwTl::Colour const * db_code1(DB_COMMA unsigned)) - { - db_assert1(AwTl::pixelFormat.palettizedB); - return *_colP; - } -}; - -class AwIffConvNonTransp : public AwTl::Colour::ConvNonTransp -{ - public: - static inline unsigned DoConv(unsigned const * pCol, AwTl::Colour const * pPalette db_code1(DB_COMMA unsigned nPaletteSize)) - { - db_assert1(pPalette); - db_onlyassert1(*pCol < nPaletteSize); - return AwTl::Colour::ConvNonTransp::DoConv(&pPalette[*pCol]); - } -}; - -class AwIffConvTransp -{ - public: - static unsigned iTranspCol; // the index of the transparent colour - static unsigned rawTranspCol; // the value of a transparent pixel on the surface - - static inline unsigned DoConv(unsigned const * pCol, AwTl::Colour const * pPalette db_code1(DB_COMMA unsigned nPaletteSize)) - { - using namespace AwTl; - - if (*pCol == iTranspCol) return rawTranspCol; - unsigned rv = AwIffConvNonTransp::DoConv(pCol,pPalette db_code1(DB_COMMA nPaletteSize)); - if (rv != rawTranspCol) return rv; - - // make the colour non-transparent (nb: only an occasional case) - - // OK, Here's the plan: - - // First, suppose that I were to decrease either the Red, Green or Blue - // component in order to make the colour non-transparent. - // Taking Red as an example, I'll work out what the resultant red value - // will be if I decrease red to achieve a non-transparent colour - // I'll compare this to the actual red value of the colour in question - // The lower the difference, the better it'll be (ie. closer to the - // original colour). - // Obviously, I'll do the same for Green and Blue - // Then I'll repeat the process but this time considering increasing - // the components. - // I'll then have six values which are scores (the lower the better) - // for what colour component to change and how to change it. - // If any of the components cannot be decreased (ie. their resulting - // value is already zero) or increased (ie. their resulting value - // is at maximum), then I'll set the corresponding score to - // UINT_MAX so that that colour-changing operation won't be selected - // (because that'll be the one that buggers everything up). - - unsigned nRedDiffDown = - (pPalette[*pCol].r < 1<<pixelFormat.redRightShift ) ? UINT_MAX - : (pPalette[*pCol].r & (1<<pixelFormat.redRightShift )-1) + ((1<<pixelFormat.redRightShift )+1)/2; - - unsigned nGreenDiffDown = - (pPalette[*pCol].g < 1<<pixelFormat.greenRightShift) ? UINT_MAX - : (pPalette[*pCol].g & (1<<pixelFormat.greenRightShift)-1) + ((1<<pixelFormat.greenRightShift)+1)/2; - - unsigned nBlueDiffDown = - (pPalette[*pCol].b < 1<<pixelFormat.blueRightShift ) ? UINT_MAX - : (pPalette[*pCol].b & (1<<pixelFormat.blueRightShift )-1) + ((1<<pixelFormat.blueRightShift )+1)/2; - - unsigned nRedDiffUp = - (pPalette[*pCol].r >= (255 & ~((1<<pixelFormat.redRightShift )-1) ) ? UINT_MAX - : (1<<pixelFormat.redRightShift )*3/2 - (pPalette[*pCol].r & (1<<pixelFormat.redRightShift )-1)); - - unsigned nGreenDiffUp = - (pPalette[*pCol].g >= (255 & ~((1<<pixelFormat.greenRightShift)-1) ) ? UINT_MAX - : (1<<pixelFormat.greenRightShift)*3/2 - (pPalette[*pCol].g & (1<<pixelFormat.greenRightShift)-1)); - - unsigned nBlueDiffUp = - (pPalette[*pCol].b >= (255 & ~((1<<pixelFormat.blueRightShift )-1) ) ? UINT_MAX - : (1<<pixelFormat.blueRightShift )*3/2 - (pPalette[*pCol].b & (1<<pixelFormat.blueRightShift )-1)); - - // Pick lowest value and do the business - - Colour colAdj = pPalette[*pCol]; - - #if defined(_MSC_VER) && _MSC_VER >= 1100 - // VC5.0 gives inane warnings when += type operators - // are used on types smaller than int (even with - // explicit casting!) - #pragma warning(disable:4244) - #endif - if - ( - nBlueDiffUp <= nBlueDiffDown - && nBlueDiffUp <= nRedDiffUp - && nBlueDiffUp <= nRedDiffDown - && nBlueDiffUp <= nGreenDiffUp - && nBlueDiffUp <= nGreenDiffDown - ) - { - colAdj.b += static_cast<unsigned char>(1<<pixelFormat.blueRightShift); - } - else if - ( - nBlueDiffDown <= nRedDiffUp - && nBlueDiffDown <= nRedDiffDown - && nBlueDiffDown <= nGreenDiffUp - && nBlueDiffDown <= nGreenDiffDown - ) - { - colAdj.b -= static_cast<unsigned char>(1<<pixelFormat.blueRightShift); - } - else if - ( - nRedDiffUp <= nRedDiffDown - && nRedDiffUp <= nGreenDiffUp - && nRedDiffUp <= nGreenDiffDown - ) - { - colAdj.r += static_cast<unsigned char>(1<<pixelFormat.redRightShift); - } - else if - ( - nRedDiffDown <= nGreenDiffUp - && nRedDiffDown <= nGreenDiffDown - ) - { - colAdj.r -= static_cast<unsigned char>(1<<pixelFormat.redRightShift); - } - else if (nGreenDiffUp <= nGreenDiffDown) - { - colAdj.g += static_cast<unsigned char>(1<<pixelFormat.greenRightShift); - } - else - { - colAdj.g -= static_cast<unsigned char>(1<<pixelFormat.greenRightShift); - } - #if defined(_MSC_VER) && _MSC_VER == 1100 - // VC5.0 gives inane warnings when += type operators - // are used on types smaller than int (even with - // explicit casting!) - #pragma warning(default:4244) - #endif - - return Colour::ConvNonTransp::DoConv(&colAdj); - } -}; - -unsigned AwIffConvTransp::iTranspCol; -unsigned AwIffConvTransp::rawTranspCol; - -// IFF Loader - -class AwIffLoader : public AwTl::TexFileLoader -{ - public: - AwIffLoader() : m_pPalette(NULL), m_bDecoding(false) {} - protected: - virtual ~AwIffLoader(); - - virtual void LoadHeaderInfo(MediaMedium * pMedium); - - virtual unsigned GetNumColours(); - - virtual unsigned GetMinPaletteSize(); - - virtual bool HasTransparentMask(bool bDefault); - - virtual void AllocateBuffers(bool bWantBackup, unsigned nMaxPaletteSize); - - virtual void OnBeginRestoring(unsigned nMaxPaletteSize); - - virtual AwTl::Colour * GetPalette(); - - - virtual AwTl::PtrUnion GetRowPtr(unsigned nRow); - - virtual void LoadNextRow(AwTl::PtrUnion pRow); - - virtual void ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize)); - - virtual DWORD GetTransparentColour(); - - virtual void OnFinishLoading(bool bSuccess); - - virtual void OnFinishRestoring(bool bSuccess); - - virtual AwBackupTexture * CreateBackupTexture(); - - private: - static bool Enumerator(IFF::Chunk * pChunk, void * pData); - // list of chunks found by enumerator - List<IFF::IlbmBodyChunk *> m_listBodyChunks; - - // smallest and largest palette sizes of versions of this image - unsigned m_nMaxPaletteSize; - unsigned m_nMinPaletteSize; - - // buffer for palette - - // since the IFF cmap table is in a different format to what the Aw loaders require - // (maybe should think about standardizing the data types?) - AwTl::Colour * m_pPalette; - - // iff data - IFF::File m_ifData; - IFF::IlbmBmhdChunk * m_pHdr; - IFF::IlbmCmapChunk * m_pCmap; - IFF::IlbmBodyChunk * m_pBody; - - bool m_bDecoding; -}; - -AwIffLoader::~AwIffLoader() -{ - if (m_pPalette) delete[] m_pPalette; -} - -void AwIffLoader::LoadHeaderInfo(MediaMedium * pMedium) -{ - db_log4("\tLoading an IFF file"); - - while (m_listBodyChunks.size()) - m_listBodyChunks.delete_first_entry(); - - if (!m_ifData.Load(pMedium) || !m_ifData.GetContents()) - { - if (NO_ERROR == (awTlLastWinErr = GetLastError())) - awTlLastErr = AW_TLE_BADFILEDATA; - else - awTlLastErr = AW_TLE_CANTREADFILE; - - db_log3("AwCreateTexture(): ERROR: IFF file load failed"); - } - else - { - m_nMinPaletteSize = UINT_MAX; - m_nMaxPaletteSize = 0; - m_ifData.GetContents()->EnumChildren("ILBM","BODY",Enumerator,this); - } -} - -unsigned AwIffLoader::GetNumColours() -{ - return m_nMaxPaletteSize; -} - -unsigned AwIffLoader::GetMinPaletteSize() -{ - return m_nMinPaletteSize; -} - -void AwIffLoader::AllocateBuffers(bool /*bWantBackup*/, unsigned nMaxPaletteSize) -{ - // we will need to allocate buffers when restoring as well as first-time loading - // so allocate buffers in OnBeginRestoring() which we'll call here - - OnBeginRestoring(nMaxPaletteSize); -} - -bool AwIffLoader::Enumerator(IFF::Chunk * pChunk, void * pData) -{ - db_assert1(pChunk); - db_assert1(pData); - AwIffLoader * pThis = static_cast<AwIffLoader *>(pData); - - IFF::Chunk * pCmap = pChunk->GetProperty("CMAP"); - IFF::Chunk * pHdr = pChunk->GetProperty("BMHD"); - if (pCmap && pHdr) // must have these two properties - { - unsigned nThisPaletteSize = static_cast<IFF::IlbmCmapChunk *>(pCmap)->nEntries; - db_logf4(("\tfound a %u colour %scompressed IFF body chunk",nThisPaletteSize,static_cast<IFF::IlbmBmhdChunk *>(pHdr)->eCompression ? "" : "un")); - - pThis->m_listBodyChunks.add_entry(static_cast<IFF::IlbmBodyChunk *>(pChunk)); - - if (nThisPaletteSize < pThis->m_nMinPaletteSize) - pThis->m_nMinPaletteSize = nThisPaletteSize; - - if (nThisPaletteSize > pThis->m_nMaxPaletteSize) - pThis->m_nMaxPaletteSize = nThisPaletteSize; - } - else db_log3("AwCreateTexture(): WARNING: IFF body chunk found with insufficient associated property chunks"); - - return true; // continue enumeration -} - -void AwIffLoader::OnBeginRestoring(unsigned nMaxPaletteSize) -{ - using namespace AwTl; - - if (m_listBodyChunks.size()) - { - // if decodeing, m_pBody will be valid - if (m_bDecoding) - { - m_pBody->EndDecode(); - m_bDecoding = false; - } - - m_pBody = NULL; - unsigned nBestPaletteSize = 0; - - for (LIF<IFF::IlbmBodyChunk *> itChunks(&m_listBodyChunks); !itChunks.done(); itChunks.next()) - { - IFF::IlbmCmapChunk * pCmap = static_cast<IFF::IlbmCmapChunk *>(itChunks()->GetProperty("CMAP")); - db_assert1(pCmap); - - if ((!nMaxPaletteSize || pCmap->nEntries <= nMaxPaletteSize) && pCmap->nEntries > nBestPaletteSize) - { - m_pBody = itChunks(); - m_pCmap = pCmap; - nBestPaletteSize = pCmap->nEntries; - } - } - - if (m_pBody) - { - m_pHdr = static_cast<IFF::IlbmBmhdChunk *>(m_pBody->GetProperty("BMHD")); - // delete old buffers - if (m_pPalette) delete[] m_pPalette; - // allocate buffer for palette, make it extra big to cope with corrupt files - unsigned nAllocPaletteSize = m_pCmap->nEntries; - unsigned nAllocPaletteSizeShift = 0; - while (0!=(nAllocPaletteSize >>= 1)) - { - ++nAllocPaletteSizeShift; - } - m_pPalette = new Colour [2<<nAllocPaletteSizeShift]; // prevent corrupt data causing a crash - //m_pPalette = new Colour [m_pCmap->nEntries]; - // copy the palette - for (unsigned i=0; i<m_pCmap->nEntries; ++i) - { - // hacked testa - m_pPalette[i].r = m_pCmap->pTable[i].r; - m_pPalette[i].g = m_pCmap->pTable[i].g; - m_pPalette[i].b = m_pCmap->pTable[i].b; - } - // set the width height and palette size in the base class - m_nPaletteSize = m_pCmap->nEntries; - m_nWidth = m_pHdr->width; - m_nHeight = m_pHdr->height; - // prepare to decode the data - m_pBody->BeginDecode(); - m_bDecoding = true; - // set the transparent mask colours - switch (m_pHdr->eMasking) - { - case IFF::IlbmBmhdChunk::MASK_NONE: - break; - case IFF::IlbmBmhdChunk::MASK_TRANSPARENTCOL: - AwIffConvTransp::iTranspCol = m_pHdr->iTranspCol; - if (pixelFormat.palettizedB) - AwIffConvTransp::rawTranspCol = AwIffConvTransp::iTranspCol; - else - AwIffConvTransp::rawTranspCol = - static_cast<unsigned>(m_pPalette[AwIffConvTransp::iTranspCol].r)>>pixelFormat.redRightShift<<pixelFormat.redLeftShift - |static_cast<unsigned>(m_pPalette[AwIffConvTransp::iTranspCol].g)>>pixelFormat.greenRightShift<<pixelFormat.greenLeftShift - |static_cast<unsigned>(m_pPalette[AwIffConvTransp::iTranspCol].b)>>pixelFormat.blueRightShift<<pixelFormat.blueLeftShift; - break; - default: - db_log3("AwCreateTexture(): ERROR: IFF mask field wrong"); - awTlLastErr = AW_TLE_BADFILEDATA; - } - } - else - { - awTlLastErr = AW_TLE_CANTPALETTIZE; // no suitable chunk found - db_log3("AwCreateTexture(): ERROR: No suitable IFF body chunk found"); - } - } - else - { - awTlLastErr = AW_TLE_BADFILEDATA; - db_log3("AwCreateTexture(): ERROR: IFF file not loaded or contains no image data"); - } -} - -AwTl::Colour * AwIffLoader::GetPalette() -{ - return m_pPalette; -} - -bool AwIffLoader::HasTransparentMask(bool bDefault) -{ - if (m_listBodyChunks.size()) - { - IFF::IlbmBmhdChunk * pHdr = static_cast<IFF::IlbmBmhdChunk *>(m_listBodyChunks.first_entry()->GetProperty("BMHD")); - db_assert1(pHdr); - return (IFF::IlbmBmhdChunk::MASK_TRANSPARENTCOL == pHdr->eMasking); - } - else - return bDefault; -} - -DWORD AwIffLoader::GetTransparentColour() -{ - return AwIffConvTransp::rawTranspCol; -} - -AwTl::PtrUnion AwIffLoader::GetRowPtr(unsigned /*nRow*/) -{ - // the iff object has an internal buffer to which a pointer - // is returned when we decode each row - // unfortunately we have to cast constness away, but never mind - return const_cast<unsigned *>(m_pBody->DecodeNextRow()); -} - -void AwIffLoader::LoadNextRow(AwTl::PtrUnion /*pRow*/) -{ - // GetRowPtr() has called DecodeNextRow() - // which has filled in the data already - // so do nothing here -} - -void AwIffLoader::ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize)) -{ - using namespace AwTl; - - // we have overridden this function for two reasons: - // 1. The data type for each texel in the row is unsigned int - // to allow for the fact that all images are palettized - // with no limit on the palette size. The default - // implementation would assume BYTE (unsigned char) - // 2. The transparency flag and colour is stored in the - // file and the transparency flag passed to AwCreateTexture() - // is ignored. The transparent colour does not have to be 0,0,0 - // either - - db_assert1(pPalette); - db_assert1(pPalette == m_pPalette); - // we can still use GenericConvertRow though, using the conversion functors above - - if (pixelFormat.palettizedB) - { - GenericConvertRow<AwIffConvNull,unsigned>::Do(pDest, nDestWidth, pSrc.uintP+nSrcOffset, nSrcWidth); - } - else - { - switch (m_pHdr->eMasking) - { - case IFF::IlbmBmhdChunk::MASK_NONE: - GenericConvertRow<AwIffConvNonTransp,unsigned>::Do(pDest, nDestWidth, pSrc.uintP+nSrcOffset, nSrcWidth, pPalette db_code1(DB_COMMA nPaletteSize)); - break; - case IFF::IlbmBmhdChunk::MASK_TRANSPARENTCOL: - GenericConvertRow<AwIffConvTransp,unsigned>::Do(pDest, nDestWidth, pSrc.uintP+nSrcOffset, nSrcWidth, pPalette db_code1(DB_COMMA nPaletteSize)); - break; - default: - db_log3("AwCreateTexture(): ERROR: IFF mask field wrong"); - awTlLastErr = AW_TLE_BADFILEDATA; - } - } -} - -void AwIffLoader::OnFinishLoading(bool /*bSuccess*/) -{ - if (m_bDecoding) - { - m_pBody->EndDecode(); - m_bDecoding = false; - } -} - -void AwIffLoader::OnFinishRestoring(bool /*bSuccess*/) -{ - if (m_bDecoding) - { - m_pBody->EndDecode(); - m_bDecoding = false; - } -} - -AwBackupTexture * AwIffLoader::CreateBackupTexture() -{ - // use the same object for restoring - AddRef(); - return this; -} - -// Valid file ID fields: 'FORM' 'LIST' 'CAT ' - we can load them all -#ifdef _MSC_VER - // VC5.0 tries to compile out code that is in a library - // and it thinks isn't being used - #line 427 -#endif -AWTEXLD_IMPLEMENT_DYNCREATE("FORM",AwIffLoader) -AWTEXLD_IMPLEMENT_DYNCREATE("LIST",AwIffLoader) -AWTEXLD_IMPLEMENT_DYNCREATE("CAT ",AwIffLoader) |
