/******************************************************** ** Copyright 2003 Earth Resource Mapping Pty Ltd. ** This document contains unpublished source code of ** Earth Resource Mapping Pty Ltd. This notice does ** not indicate any intention to publish the source ** code contained herein. ** ** FILE: $Archive: /NCS/Source/include/NCSJPCBuffer.h $ ** CREATED: 14/03/2003 3:27:34 PM ** AUTHOR: Simon Cope ** PURPOSE: CNCSJPCBuffer class header ** EDITS: [xx] ddMmmyy NAME COMMENTS *******************************************************/ #ifndef NCSJPCBUFFER_H #define NCSJPCBUFFER_H #ifndef NCSJPCRECT_H #include "NCSJPCRect.h" #endif // NCSJPCRECT_H #ifndef NCSMISC_H #include "NCSMisc.h" #endif #ifndef NCSECWCLIENT_H #include "NCSEcwClient.h" #endif #ifndef NCSMEMPOOL_H #include "NCSMemPool.h" #endif // NCSMEMPOOL_H #include /** * CNCSJPCBuffer class - the base JPC scanline buffer. * * @author Simon Cope * @version $Revision$ $Author$ $Date$ */ class NCSJPC_EXPORT_ALL CNCSJPCBuffer: public CNCSJPCRect { public: static const UINT32 MAXUINT8; static const UINT32 MAXUINT16; static const UINT32 MAXUINT32; static const UINT32 MINUINT8; static const UINT32 MINUINT16; static const UINT32 MINUINT32; static const UINT32 MAXINT8; static const UINT32 MAXINT16; static const UINT32 MAXINT32; static const INT32 MININT8; static const INT32 MININT16; static const INT32 MININT32; class NCSJPC_EXPORT_ALL SystemInfo { public: bool m_bMMXPresent; bool m_bSSEPresent; bool m_bSSE2Present; bool m_b3DNowPresent; UINT64 m_nPhysicalMemBytes; SystemInfo(); static NCSTimeStampUs GetTime(); #ifdef WIN32 private: static LARGE_INTEGER sm_iFrequency; #endif }; static SystemInfo sm_SystemInfo; static NCSTimeStampUs sm_usCopy; static UINT64 sm_nCopyBytes; static NCSTimeStampUs sm_usClear; static UINT64 sm_nClearBytes; static NCSTimeStampUs sm_usAlloc; static UINT64 sm_nAllocBytes; static NCSTimeStampUs sm_usFree; typedef enum { BT_INT16 = NCSCT_INT16, BT_INT32 = NCSCT_INT32, BT_IEEE4 = NCSCT_IEEE4 } Type; static const UINT32 AT_OWNER; // This buffer owns resources static const UINT32 AT_CHILD; // A child node returned the buffer and will free it later static const UINT32 AT_LOCKED; // Buffer is locked and can't be assigned to. class CNCSJPCBufferPool { public: NCSPool *m_pPool; UINT32 m_nSize; CNCSJPCBufferPool(); ~CNCSJPCBufferPool(); void SetCBSize(Type eType, UINT32 nWidth, UINT32 nHeight); void *Alloc(); void Free(void *p); }; Type m_eType; UINT32 m_Flags; void *m_pBuffer; CNCSJPCBufferPool *m_pPool; int m_nStep; /** Default constructor, initialises members */ CNCSJPCBuffer(); /** Copy constructor */ CNCSJPCBuffer::CNCSJPCBuffer( const class CNCSJPCBuffer& src ); /** constructor, specify rect values */ CNCSJPCBuffer(UINT32 nWidth, Type eType); /** constructor, specify rect values */ CNCSJPCBuffer(UINT32 nWidth, UINT32 nHeight, Type eType); /** constructor, specify rect values */ CNCSJPCBuffer(INT32 nX0, INT32 nY0, INT32 nX1, INT32 nY1, Type eType); /** constructor, specify rect values */ CNCSJPCBuffer(INT32 nX0, INT32 nY0, UINT32 nWidth, UINT32 nHeight, Type eType); /** Virtual destructor */ virtual ~CNCSJPCBuffer(); class CNCSJPCBuffer& CNCSJPCBuffer::operator=( const class CNCSJPCBuffer& src ); bool Alloc(UINT32 nWidth, Type eType); bool Alloc(UINT32 nWidth, UINT32 nHeight, Type eType); bool Alloc(INT32 nX0, INT32 nY0, INT32 nX1, INT32 nY1, Type eType); bool Alloc(INT32 nX0, INT32 nY0, UINT32 nWidth, UINT32 nHeight, Type eType); void Free(); bool Assign(Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); bool Assign(UINT32 nWidth, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); bool Assign(UINT32 nWidth, UINT32 nHeight, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); bool Assign(INT32 nX0, INT32 nY0, INT32 nX1, INT32 nY1, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); bool Assign(INT32 nX0, INT32 nY0, UINT32 nWidth, UINT32 nHeight, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); void Release(); void SetFlag(UINT32 Flag) { m_Flags |= Flag; }; void UnSetFlags(UINT32 Flags) { m_Flags &= ~Flags; }; UINT32 GetFlags() { return(m_Flags); }; bool TestFlags(UINT32 Flag) { return((m_Flags & Flag) ? true : false); }; /** * Return the size of a buffer in bytes (default 1 cell). * @param eType Type of buffer * @param nWidth Number of pixels in buffer. * @return UINT32 calculated buffer size in bytes. */ static NCS_INLINE UINT32 Size(Type eType, UINT32 nWidth = 1, UINT32 nHeight = 1) { UINT32 nLineSize = 0; switch(eType) { case BT_INT16: nLineSize = sizeof(INT16) * nWidth; break; case BT_INT32: nLineSize = sizeof(INT32) * nWidth; break; case BT_IEEE4: nLineSize = sizeof(IEEE4) * nWidth; break; } if(nHeight != 1 && nLineSize % 32) { // Pad scanlines to 32 byte multiples for performance // when the buffer is > 1 line high nLineSize = (1 + nLineSize / 32) * 32; } return(nLineSize * nHeight); } NCS_INLINE UINT32 GetStep() { return(m_nStep); }; NCS_INLINE UINT32 GetStepBytes() { return(m_nStep * Size(m_eType)); }; NCS_INLINE Type GetType() { return(m_eType); }; NCS_INLINE void *GetPtr() { return(m_pBuffer); }; NCS_INLINE void *GetPtr(INT32 x, INT32 y) { return((UINT8*)m_pBuffer + (y - GetY0()) * (INT32)GetStepBytes() + (x - GetX0()) * (INT32)Size(GetType())); }; /** * Return the size of the Wavelet Tranform border for the specified pipeline type. * @param eType Type of buffer * @return UINT32 Width/Height of border in CELLS. */ static NCS_INLINE UINT32 Border(Type eType) { switch(eType) { case BT_INT16: case BT_INT32: return(1); break; case BT_IEEE4: return(2); break; } return(0); } void Clear(); /** * Convert a line to a line of type T. * @param pDst Pointer to Destination buffer * @return bool true on succes, else false. */ template bool Convert(T *pDst, UINT8 nStep = 1) { if(m_pBuffer && pDst) { UINT32 x = 0; UINT32 nWidth = GetWidth(); if(nStep == 1) { // Single band switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: FLT_TO_INT_INIT(); for(x = 0; x < nWidth; x++) { pDst[x] = (T)NCSfloatToInt32_RM(((IEEE4*)m_pBuffer)[x]); // pDst[x] = (T)NCSFloor(((IEEE4*)m_pBuffer)[x]); } FLT_TO_INT_FINI(); break; } } else if(nStep == 3) { // 3 band - eg RGB switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x * 3] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x * 3] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: FLT_TO_INT_INIT(); for(x = 0; x < nWidth; x++) { pDst[x*3] = (T)NCSfloatToInt32_RM(((IEEE4*)m_pBuffer)[x]); } FLT_TO_INT_FINI(); break; } } else if(nStep == 4) { // 4 band, eg RGBA switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x * 4] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x * 4] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: FLT_TO_INT_INIT(); for(x = 0; x < nWidth; x++) { pDst[x*4] = (T)NCSfloatToInt32_RM(((IEEE4*)m_pBuffer)[x]); } FLT_TO_INT_FINI(); } } else { switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x * nStep] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x * nStep] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: FLT_TO_INT_INIT(); for(x = 0; x < nWidth; x++) { pDst[x*nStep] = (T)NCSfloatToInt32_RM(((IEEE4*)m_pBuffer)[x]); } FLT_TO_INT_FINI(); break; } } return(true); } return(false); } /** * Convert a line to a line of type T. * @param pDst Pointer to Destination buffer * @return bool true on succes, else false. */ template bool ConvertFLT(T *pDst, UINT8 nStep = 1) { if(m_pBuffer && pDst) { UINT32 x = 0; UINT32 nWidth = GetWidth(); if(nStep == 1) { // Single band switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: for(x = 0; x < nWidth; x++) { pDst[x] = (T)((IEEE4*)m_pBuffer)[x]; } break; } } else if(nStep == 3) { // 3 band - eg RGB switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x * 3] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x * 3] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: for(x = 0; x < nWidth; x++) { pDst[x * 3] = (T)((IEEE4*)m_pBuffer)[x]; } break; } } else if(nStep == 4) { // 4 band, eg RGBA switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x * 4] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x * 4] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: for(x = 0; x < nWidth; x++) { pDst[x * 4] = (T)((IEEE4*)m_pBuffer)[x]; } break; } } else { switch(GetType()) { case CNCSJPCBuffer::BT_INT16: for(x = 0; x < nWidth; x++) { pDst[x * nStep] = (T)((INT16*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_INT32: for(x = 0; x < nWidth; x++) { pDst[x * nStep] = (T)((INT32*)m_pBuffer)[x]; } break; case CNCSJPCBuffer::BT_IEEE4: for(x = 0; x < nWidth; x++) { pDst[x * nStep] = (T)((IEEE4*)m_pBuffer)[x]; } break; } } return(true); } return(false); } /** * Read buffer to a type T. * @param pDst Pointer to Destination buffer * @return bool true on succes, else false. */ template bool Read(T *pDst, UINT8 nStep = 1) { for(UINT32 y = 0; y < GetHeight(); y++) { Convert(pDst, nStep); } return(true); } /** * Read buffer to a (IEEE4/IEEE8) type T. * @param pDst Pointer to Destination buffer * @return bool true on succes, else false. */ template bool ReadFLT(T *pDst, UINT8 nStep = 1) { for(UINT32 y = 0; y < GetHeight(); y++) { ConvertFLT(pDst, nStep); } return(true); } NCS_INLINE bool Read(void *pValue, INT32 nX, INT32 nY = 0, UINT32 nWidth = 1, UINT32 nHeight = 1, UINT32 nStep = 1) { UINT32 x, y; switch(m_eType) { case BT_INT16: for(y = 0; y < nHeight; y++) { for(x = 0; x < nWidth; x++) { *((INT16*)pValue + nStep * y + x) = *((INT16*)m_pBuffer + m_nStep * ((nY - m_Y0) + y) + (nX - m_X0) + x); } } break; case BT_INT32: for(y = 0; y < nHeight; y++) { for(x = 0; x < nWidth; x++) { *((INT32*)pValue + nStep * y + x) = *((INT32*)m_pBuffer + m_nStep * ((nY - m_Y0) + y) + (nX - m_X0) + x); } } break; case BT_IEEE4: for(y = 0; y < nHeight; y++) { for(x = 0; x < nWidth; x++) { *((IEEE4*)pValue + nStep * y + x) = *((IEEE4*)m_pBuffer + m_nStep * ((nY - m_Y0) + y) + (nX - m_X0) + x); } } break; } return(true); } NCS_INLINE bool Read(CNCSJPCBuffer *pDst) { CNCSJPCRect r(NCSMax(GetX0(), pDst->GetX0()), NCSMax(GetY0(), pDst->GetY0()), NCSMin(GetX1(), pDst->GetX1()), NCSMin(GetY1(), pDst->GetY1())); if(pDst->GetType() == GetType()) { return(Copy(r.GetWidth(), r.GetHeight(), (UINT8*)pDst->GetPtr() + (r.GetY0() - pDst->GetY0()) * pDst->GetStepBytes() + Size(m_eType, r.GetX0() - pDst->GetX0()), pDst->GetStepBytes(), (UINT8*)GetPtr() + (r.GetY0() - GetY0()) * GetStepBytes() + Size(m_eType, r.GetX0() - GetX0()), GetStepBytes(), m_eType)); } else { for(UINT32 y = 0; y < r.GetHeight(); y++) { CNCSJPCBuffer tmp; tmp.Assign(r.GetX0(), r.GetY0(), r.GetWidth(), r.GetHeight(), GetType(), (UINT8*)GetPtr() + (y + r.GetY0() - GetY0()) * GetStepBytes() + Size(m_eType, r.GetX0() - GetX0())); switch(pDst->GetType()) { case BT_INT16: tmp.Convert((INT16*)((UINT8*)pDst->GetPtr() + (y + r.GetY0() - pDst->GetY0()) * pDst->GetStepBytes() + Size(m_eType, r.GetX0() - pDst->GetX0()))); break; case BT_INT32: tmp.Convert((INT32*)((UINT8*)pDst->GetPtr() + (y + r.GetY0() - pDst->GetY0()) * pDst->GetStepBytes() + Size(m_eType, r.GetX0() - pDst->GetX0()))); break; case BT_IEEE4: tmp.ConvertFLT((IEEE4*)((UINT8*)pDst->GetPtr() + (y + r.GetY0() - pDst->GetY0()) * pDst->GetStepBytes() + Size(m_eType, r.GetX0() - pDst->GetX0()))); break; } tmp.Release(); } } return(true); } /** * Clip valus in the buffer to the specified range. * @param nMin Min value * @param nMax Max value * @return bool true on success, else false & error set. */ bool Clip(INT32 nMin, INT32 nMax); /** * Clip valus in a buffer to the specified range. * @param fMin Min value * @param fMax Max value * @return bool true on success, else false & error set. */ bool Clip(IEEE4 fMin, IEEE4 fMax); /** * Add a constant value to the buffer. * @param nValue Constant value to add * @param nScale Scale factor, *= NCS2Pow(-nScale) * @return bool true on succes, else false. */ bool Add(const INT32 nValue, INT16 nScale = 0); /** * Add a constant value to the line. * @param fValue Constant value to add * @param nScale Scale factor, *= fScale * @return bool true on succes, else false. */ bool Add(const IEEE4 fValue, INT16 nScale = 0); /** * Change bit depth (data range) of a buffer * @param nCurrentBits Current bit depth * @param nNewBits New bit depth * @return bool true on succes, else false. */ bool OffsetShift(const INT32 nValue, UINT8 nCurrentBits, UINT8 nNewBits); /** * Copy from one pointer to another (may overlap). * @param nWidth Width in pixels. * @param nHeight Height in pixels. * @param pDst Dest buffer * @param nDstStep Dest buffer step size * @param pSrc Src buffer * @param nSrcStep Src buffer step size * @param eType Buffer Type * @return bool true on success, else false & error set. */ static bool Copy(UINT32 nWidth, UINT32 nHeight, void *pDst, INT32 nDstStep, const void *pSrc, INT32 nSrcStep, Type eType); protected: private: static CNCSJPCBufferPool sm_Pool; bool Alloc(); }; typedef std::vector CNCSJPCBufferVector; class NCSJPC_EXPORT_ALL CNCSJPCBufferCache { public: virtual ~CNCSJPCBufferCache() {}; virtual void SetBuffers(UINT32 nBuffers); virtual CNCSJPCBuffer *GetBuffer(UINT32 nBuffer); virtual CNCSJPCBuffer *FindBuffer(UINT32 &nBuffer, CNCSJPCRect &r, bool &bFound, CNCSJPCBuffer::Type eType); private: CNCSJPCBufferVector m_Buffers; }; #endif // !NCSJPCBUFFER_H