/******************************************************** ** Copyright 2003 Earth Resource Mapping Ltd. ** This document contains proprietary source code of ** Earth Resource Mapping Ltd, and can only be used under ** one of the three licenses as described in the ** license.txt file supplied with this distribution. ** See separate license.txt file for license details ** and conditions. ** ** This software is covered by US patent #6,442,298, ** #6,102,897 and #6,633,688. Rights to use these patents ** is included in the license agreements. ** ** 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 ** [01] 12Dec05 tfl lint fixes ** [02] 25Jan06 tfl Added Multiply methods to support CNCSJP2FileView autoscale feature *******************************************************/ #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: 1.25 $ $Author: tom.lynch $ $Date: 2006/01/25 05:55:19 $ */ class NCSJPC_EXPORT_ALL CNCSJPCBuffer: public CNCSJPCRect { public: /** Maximum UINT8 value */ static const UINT32 NCS_MAXUINT8; /** Maximum UINT16 value */ static const UINT32 NCS_MAXUINT16; /** Maximum UINT32 value */ static const UINT32 NCS_MAXUINT32; /** Minimum UINT8 value */ static const UINT32 NCS_MINUINT8; /** Minimum UINT16 value */ static const UINT32 NCS_MINUINT16; /** Minimum UINT32 value */ static const UINT32 NCS_MINUINT32; /** Maximum INT8 value */ static const UINT32 NCS_MAXINT8; /** Maximum INT16 value */ static const UINT32 NCS_MAXINT16; /** Maximum INT32 value */ static const UINT32 NCS_MAXINT32; /** Minimum INT8 value */ static const INT32 NCS_MININT8; /** Minimum INT16 value */ static const INT32 NCS_MININT16; /** Minimum INT32 value */ static const INT32 NCS_MININT32; /** * SystemInfo class - Some basic system capabilities we care about. * * @author Simon Cope * @version $Revision: 1.25 $ $Author: tom.lynch $ $Date: 2006/01/25 05:55:19 $ */ class NCSJPC_EXPORT_ALL SystemInfo { public: /** MMX Is present */ bool m_bMMXPresent; /** SSE is present */ bool m_bSSEPresent; /** SSE2 is present */ bool m_bSSE2Present; /** 3DNow is present */ bool m_b3DNowPresent; /** Bytes of physical memory on system */ UINT64 m_nPhysicalMemBytes; /** Default constructor */ SystemInfo(); /** Current timestamp in US */ static NCSTimeStampUs GetTime(); #ifdef WIN32 private: /** high-resolution Timer frequency */ static LARGE_INTEGER sm_iFrequency; #endif }; /** SystemInfo instance */ static SystemInfo sm_SystemInfo; /** Buffer copy US */ static NCSTimeStampUs sm_usCopy; /** buffer copy bytes */ static UINT64 sm_nCopyBytes; /** buffer clear US */ static NCSTimeStampUs sm_usClear; /** buffer clear bytes */ static UINT64 sm_nClearBytes; /** buffer Alloc US */ static NCSTimeStampUs sm_usAlloc; /** Current buffer alloc bytes */ static UINT64 sm_nAllocBytes; /** buffer free US */ static NCSTimeStampUs sm_usFree; typedef enum { /** s16 integer buffer type */ BT_INT16 = NCSCT_INT16, /** s32 integer buffer type */ BT_INT32 = NCSCT_INT32, /** IEEE4 single precision float buffer type */ BT_IEEE4 = NCSCT_IEEE4 } Type; /** FLAG: This buffer owns resources */ static const UINT32 AT_OWNER; /** FLAG: A child node returned the buffer and will free it later */ static const UINT32 AT_CHILD; /** Buffer is locked and can't be assigned to. */ static const UINT32 AT_LOCKED; /** * CNCSJPCBufferPool class - a rotating pool of buffers * * @author Simon Cope * @version $Revision: 1.25 $ $Author: tom.lynch $ $Date: 2006/01/25 05:55:19 $ */ class CNCSJPCBufferPool { public: /** NCS memory pool */ NCSPool *m_pPool; /** Size */ UINT32 m_nSize; /** Constructor */ CNCSJPCBufferPool(); /** Destructor */ ~CNCSJPCBufferPool(); /** Set the CodeBlock size */ void SetCBSize(Type eType, UINT32 nWidth, UINT32 nHeight); /** Alloc a buffer from the pool */ void *Alloc(); /** Return a buffer to the pool */ void Free(void *p); }; /** Buffer type */ Type m_eType; /** buffer flags */ UINT32 m_Flags; /** Actual buffer pointer */ void *m_pBuffer; /** Pool - optional */ CNCSJPCBufferPool *m_pPool; /** Buffer step size to next line */ int m_nStep; /** Default constructor, initialises members */ CNCSJPCBuffer(); /** Copy constructor */ 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(); /** Assignment operator */ class CNCSJPCBuffer& operator=( const class CNCSJPCBuffer& src ); /** Alloc a buffer the specified width and type */ bool Alloc(UINT32 nWidth, Type eType); /** Alloc a buffer the specified width, height and type */ bool Alloc(UINT32 nWidth, UINT32 nHeight, Type eType); /** Alloc a buffer with the specified TL, BR and type */ bool Alloc(INT32 nX0, INT32 nY0, INT32 nX1, INT32 nY1, Type eType); /** Alloc a buffer with the specified TL, width, height and type */ bool Alloc(INT32 nX0, INT32 nY0, UINT32 nWidth, UINT32 nHeight, Type eType); /** Free the buffer */ void Free(); /** Assign a buffer to this buffer */ bool Assign(Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); /** Assign a buffer to this buffer */ bool Assign(UINT32 nWidth, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); /** Assign a buffer to this buffer */ bool Assign(UINT32 nWidth, UINT32 nHeight, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); /** Assign a buffer to this buffer */ bool Assign(INT32 nX0, INT32 nY0, INT32 nX1, INT32 nY1, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); /** Assign a buffer to this buffer */ bool Assign(INT32 nX0, INT32 nY0, UINT32 nWidth, UINT32 nHeight, Type eType, void *pPtr, INT32 nStep = 0, bool bFree = true); /** Release this buffer */ void Release(); /** Set flags */ void SetFlag(UINT32 Flag) { m_Flags |= Flag; }; /** Unset flags */ void UnSetFlags(UINT32 Flags) { m_Flags &= ~Flags; }; /** Get flags */ UINT32 GetFlags() { return(m_Flags); }; /** test 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); } /** Get buffer step in cells */ NCS_INLINE UINT32 GetStep() { return(m_nStep); }; /** Get buffer step in bytes */ NCS_INLINE UINT32 GetStepBytes() { return(m_nStep * Size(m_eType)); }; /** get buffer type */ NCS_INLINE Type GetType() { return(m_eType); }; /** get pointer to start of buffer (0,0) */ NCS_INLINE void *GetPtr() { return(m_pBuffer); }; /** get pointer to buffer at (x,y) */ 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); } /** Clear buffer to 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); } /** Read value(s) from the buffer at the specified position, size */ 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); } /** Read from the buffer to the destination buffer, copying only the intersecting area */ 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); /** * Multiply the contents of the buffer by an integer. * @param nValue Multiplication factor * @return bool true on success, else false. */ bool Multiply(const IEEE4 fValue); /** * Multiply the contents of the buffer by an integer. * @param nValue Multiplication factor * @return bool true on success, else false. */ bool Multiply(const INT32 nValue); /** * 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