"L. Spiro Engine"
|
00001 00016 #ifndef __LSI_IMAGE_H__ 00017 #define __LSI_IMAGE_H__ 00018 00019 #include "../LSIImageLib.h" 00020 #include "../Dds/LSIDds.h" 00021 #include "Map/LSTLMap.h" 00022 #include "Misc/LSCMisc.h" 00023 #include "Vector/LSTLVectorPoD.h" 00024 #include "Vector/LSTLVector.h" 00025 00026 namespace lsi { 00027 00028 // == Enumerations. 00032 enum LSI_FILTER { 00033 LSI_F_BOX_FILTER, 00034 LSI_F_BILINEAR_FILTER, 00035 LSI_F_KAISER_FILTER, 00036 LSI_F_LANCZOS3_FILTER, 00037 LSI_F_LANCZOS4_FILTER, 00038 LSI_F_LANCZOS6_FILTER, 00039 LSI_F_LANCZOS8_FILTER, 00040 LSI_F_LANCZOS12_FILTER, 00041 LSI_F_LANCZOS64_FILTER, 00042 LSI_F_MITCHELL_FILTER, 00043 LSI_F_CATMULLROM_FILTER, 00044 LSI_F_ANY, 00045 }; 00046 00053 class CImage { 00054 public : 00055 // == Various constructors. 00056 LSE_CALLCTOR CImage(); 00057 LSE_CALLCTOR CImage( const CImage &_iOther ); 00058 00059 00060 // == Enumerations. 00064 enum LSI_COMPRESSIONS { 00065 LSI_C_RAWCOMPRESSION, 00066 LSI_C_CHANNELCOMPRESSION, 00067 LSI_C_RLECOMPRESSION, 00068 LSI_C_INDEXCOMPRESSION, 00069 LSI_C_DTXCOMPRESSION, 00070 }; 00071 00072 00073 // == Operators. 00080 CImage & LSE_CALL operator = ( const CImage &_iOther ); 00081 00082 00083 // == Functions. 00090 LSVOID LSE_CALL SetAllocator( CAllocator * _paAllocator ); 00091 00095 LSVOID LSE_CALL Reset(); 00096 00102 LSE_INLINE LSUINT32 LSE_CALL GetWidth() const; 00103 00109 LSE_INLINE LSUINT32 LSE_CALL GetHeight() const; 00110 00116 LSE_INLINE LSI_PIXEL_FORMAT LSE_CALL GetFormat() const; 00117 00123 LSE_INLINE const LSVOID * LSE_CALL GetBufferData() const; 00124 00130 LSE_INLINE const CImageLib::CTexelBuffer & LSE_CALL 00131 GetBufferDataAsVector() const; 00132 00138 LSE_INLINE const CVector<CImageLib::CTexelBuffer> & LSE_CALL 00139 GetMipMapBuffers() const; 00140 00146 LSE_INLINE LSUINT32 LSE_CALL TotalMipLevels() const; 00147 00154 LSE_INLINE const CImageLib::CTexelBuffer & LSE_CALL 00155 GetMipMapBuffers( LSUINT32 _ui32Level ) const; 00156 00164 LSBOOL LSE_CALL LoadFileFromMemory( const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen ); 00165 00172 LSBOOL LSE_CALL LoadFile( const LSCHAR * _pcFile ); 00173 00182 LSBOOL LSE_CALL CreateBlank( LSI_PIXEL_FORMAT _pfFormat, LSUINT32 _ui32Width, LSUINT32 _ui32Height ); 00183 00193 LSBOOL LSE_CALL CreateFromRgbAndAlpha( const CImage &_iRgb, const CImage &_iAlpha ); 00194 00204 LSE_INLINE LSUINT64 LSE_CALL GetTexelAt( LSI_PIXEL_FORMAT _pfFormat, LSUINT32 _ui32X, LSUINT32 _ui32Y ) const; 00205 00214 LSE_INLINE LSVOID LSE_CALL SetTexelAt( LSUINT64 _ui64Texel, LSI_PIXEL_FORMAT _pfFormat, LSUINT32 _ui32X, LSUINT32 _ui32Y ); 00215 00223 LSBOOL LSE_CALL CompressToBuffer( CMisc::LSC_BUFFER &_bBuffer ); 00224 00228 LSVOID LSE_CALL Flip(); 00229 00236 LSVOID LSE_CALL ConvertToFormat( LSI_PIXEL_FORMAT _pfFormat, CImage &_iDest ) const; 00237 00244 CImage & LSE_CALL ConvertToFormatInPlace( LSI_PIXEL_FORMAT _pfFormat ); 00245 00258 LSBOOL LSE_CALL Resample( LSUINT32 _ui32NewWidth, LSUINT32 _ui32NewHeight, LSI_FILTER _fFilter, CImage &_iDest, 00259 LSFLOAT _fSrcGamma = 2.2f, LSFLOAT _fFilterScale = 1.0f ) const; 00260 00272 LSBOOL LSE_CALL ResampleInPlace( LSUINT32 _ui32NewWidth, LSUINT32 _ui32NewHeight, LSI_FILTER _fFilter, 00273 LSFLOAT _fSrcGamma = 2.2f, LSFLOAT _fFilterScale = 1.0f ); 00274 00280 LSUINT32 LSE_CALL GetCrc32() const; 00281 00287 LSUINT32 LSE_CALL GetCrc32Alt() const; 00288 00297 LSVOID LSE_CALL ConvertToNormalMap( LSFLOAT _fStr, LSBOOL _bWrapX = true, LSBOOL _bWrapY = true ); 00298 00306 LSBOOL LSE_CALL ConvertToDds( LSI_PIXEL_FORMAT _pfFormat, CImage &_iDst ); 00307 00314 LSBOOL LSE_CALL ConvertToDdsInPlace( LSI_PIXEL_FORMAT _pfFormat ); 00315 00323 LSBOOL LSE_CALL IsBlackAndWhite() const; 00324 00334 protected : 00335 // == Enumerations. 00339 enum { 00340 LSI_LINEAR_TO_SRGB_TABLE_SIZE = 4096, 00341 }; 00342 00343 00344 // == Types. 00348 typedef struct LSI_SORTED_PIXEL { 00352 union LSI_COL { 00353 LSUINT8 ui8Rgb[16]; 00354 00355 LSUINT64 ui64Rgb64; 00356 } u; 00357 00361 LSUINT32 ui32Length; 00362 00363 00364 // == Operators. 00371 LSBOOL LSE_CALL operator < ( const LSI_SORTED_PIXEL &_spOther ) const; 00372 00379 LSBOOL LSE_CALL operator == ( const LSI_SORTED_PIXEL &_spOther ) const; 00380 } * LPLSI_SORTED_PIXEL, * const LPCLSI_SORTED_PIXEL; 00381 00385 typedef union LSI_BLOCK { 00386 struct LSI_COLOR { 00387 LSFLOAT fR, fG, fB, fA; 00388 } s; 00389 LSFLOAT fValues[4]; 00390 00391 00392 // == Operators. 00399 LSE_INLINE LSBOOL LSE_CALL operator < ( const LSI_BLOCK &_bOther ) const; 00400 00407 LSE_INLINE LSBOOL LSE_CALL operator == ( const LSI_BLOCK &_bOther ) const; 00408 00415 LSE_INLINE LSBOOL LSE_CALL operator != ( const LSI_BLOCK &_bOther ) const; 00416 } * LPLSI_BLOCK, * const LPCLSI_BLOCK; 00417 00421 typedef struct LSI_DXT_THREAD_DATA { 00425 LSUINT32 ui32SrcX; 00426 00430 LSUINT32 ui32SrcY; 00431 00435 const CImage * piSrcImage; 00436 00440 LSUINT8 * pui8Dest; 00441 00445 LSI_PIXEL_FORMAT pfFormat; 00446 00450 LSBOOL bDone; 00451 } * LPLSI_DXT_THREAD_DATA, * const LPCLSI_DXT_THREAD_DATA; 00452 00453 00454 // == Members. 00458 CImageLib::CTexelBuffer m_tbBuffer; 00459 00463 CVector<CImageLib::CTexelBuffer> m_vMipMapBuffer; 00464 00468 LSUINT32 m_ui32Width; 00469 00473 LSUINT32 m_ui32Height; 00474 00478 LSI_PIXEL_FORMAT m_pfFormat; 00479 00483 LSUINT32 m_ui32RowWidth; 00484 00488 LSUINT32 m_ui32TexelSize; 00489 00490 00491 // == Functions. 00495 LSVOID LSE_CALL PostLoad(); 00496 00505 LSBOOL LSE_CALL CompressChannels( CMisc::LSC_BUFFER &_bBuffer, LSUINT32 _ui32MaxSize = ~0UL ); 00506 00514 LSBOOL LSE_CALL CompressRaw( CMisc::LSC_BUFFER &_bBuffer, LSUINT32 _ui32MaxSize = ~0UL ); 00515 00523 LSBOOL LSE_CALL CompressRle( CMisc::LSC_BUFFER &_bBuffer, LSUINT32 _ui32MaxSize = ~0UL ); 00524 00533 LSBOOL LSE_CALL CompressIndex( CMisc::LSC_BUFFER &_bBuffer, LSUINT32 _ui32MaxSize = ~0UL ); 00534 00541 LSBOOL LSE_CALL CompressDxt( CMisc::LSC_BUFFER &_bBuffer ); 00542 00551 LSBOOL LSE_CALL LoadCompressedChannels( const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen, CImageLib::CTexelBuffer &_tbOut ); 00552 00561 LSBOOL LSE_CALL LoadCompressedRaw( const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen, CImageLib::CTexelBuffer &_tbOut ); 00562 00571 LSBOOL LSE_CALL LoadCompressedBitwiseRle( const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen, CImageLib::CTexelBuffer &_tbOut ); 00572 00581 LSBOOL LSE_CALL LoadCompressedIndices( const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen, CImageLib::CTexelBuffer &_tbOut ); 00582 00593 LSBOOL LSE_CALL LoadDxt( LSUINT8 _ui8MipLevels, const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen, CImageLib::CTexelBuffer &_tbOut, 00594 CVector<CImageLib::CTexelBuffer> &_vMipMaps ); 00595 00603 LSBOOL LSE_CALL LoadLsi( const LSUINT8 * _pui8FileData, LSUINT32 _ui32DataLen ); 00604 00619 static LSVOID LSE_CALL GetKeyColors( const LSI_BLOCK _bBlock[4][4], LSI_BLOCK &_bMax, LSI_BLOCK &_bMin, LSUINT32 _ui32Width, LSUINT32 _ui32Height, 00620 LSFLOAT _fAlphaHigh, LSFLOAT _fAlphaLow, LSI_PIXEL_FORMAT _pfFormat ); 00621 00637 static LSVOID LSE_CALL RefineKeyColors( const CMap<LSFLOAT, LSUINT32> _bUniqueValues[4], const CMap<LSI_BLOCK, LSUINT32> &_bUniqueColors, 00638 const LSI_BLOCK _bBlock[4][4], LSI_BLOCK &_bMax, LSI_BLOCK &_bMin, LSUINT32 _ui32Width, LSUINT32 _ui32Height, 00639 LSUINT32 _ui32Iters, LSFLOAT _fAlphaHigh, LSFLOAT _fAlphaLow, LSI_PIXEL_FORMAT _pfFormat ); 00640 00649 static LSVOID LSE_CALL Get4Colors( const LSI_BLOCK &_bMax, const LSI_BLOCK &_bMin, LSI_BLOCK _bRet[4], LSBOOL _bOmitLast ); 00650 00660 static LSVOID LSE_CALL Get4Colors( LSUINT32 _ui32Channel, const LSI_BLOCK &_bMax, const LSI_BLOCK &_bMin, LSFLOAT _fRet[4], LSBOOL _bOmitLast ); 00661 00670 static LSVOID LSE_CALL MakeDxt1Block( const LSI_BLOCK _bBlock[4][4], const LSI_BLOCK &_bMax, const LSI_BLOCK &_bMin, 00671 LSUINT8 * _pui8Return ); 00672 00685 static LSUINT32 LSE_CALL FindDxt1Match( const LSI_BLOCK &_bColor0, const LSI_BLOCK &_bColor1, 00686 const LSI_BLOCK &_bColor ); 00687 00695 static LSE_INLINE LSFLOAT LSE_CALL GetError( const LSI_BLOCK &_bColor0, const LSI_BLOCK &_bColor1 ); 00696 00710 static LSFLOAT LSE_CALL GetError( const CMap<LSI_BLOCK, LSUINT32> &_bUniqueColors, const LSI_BLOCK &_bMax, const LSI_BLOCK &_bMin, 00711 LSUINT32 _ui32Width, LSUINT32 _ui32Height, LSBOOL _bOmitLast, LSFLOAT _fCurError ); 00712 00724 static LSFLOAT LSE_CALL GetErrorStrict( const LSI_BLOCK _bBlock[4][4], const LSI_BLOCK &_bMax, const LSI_BLOCK &_bMin, 00725 LSUINT32 _ui32Width, LSUINT32 _ui32Height, LSBOOL _bOmitLast ); 00726 00737 static LSE_INLINE LSFLOAT LSE_CALL GetError( LSUINT32 _ui32Channel, 00738 const LSI_BLOCK _bBlocks[4], const LSI_BLOCK &_bSrc, LSUINT32 &_ui32Index, LSBOOL _bOmitLast ); 00739 00750 static LSE_INLINE LSFLOAT LSE_CALL GetError( LSUINT32 _ui32Channel, 00751 const LSI_BLOCK _bBlocks[4], LSFLOAT _fValue, LSUINT32 &_ui32Index, LSBOOL _bOmitLast ); 00752 00759 static LSE_INLINE LSUINT16 LSE_CALL ConvertBlockTexelTo16Bit( const LSI_BLOCK &_bColor ); 00760 00767 static LSE_INLINE LSI_BLOCK LSE_CALL Convert16BitToBlockTexel( LSUINT16 _ui16Color ); 00768 00778 static LSE_INLINE LSBOOL LSE_CALL Offset16BitColorChannel( LSUINT32 _ui32Channel, LSINT32 _i32Amount, LSUINT16 &_ui16Color ); 00779 00792 static LSVOID LSE_CALL FindEndPoints( LSFLOAT _fEndPoint, LSFLOAT _fMidPoint, LSUINT32 _ui32EndIndex, LSUINT32 _ui32MidIndex, 00793 LSUINT32 _ui32Points, LSFLOAT _fRes, LSFLOAT &_fLow, LSFLOAT &_fHigh ); 00794 00802 static LSE_INLINE LSFLOAT LSE_CALL Round( LSFLOAT _fValue, LSFLOAT _fRes ); 00803 00810 static LSUINT32 LSH_CALL DxtThread( LSVOID * _lpParameter ); 00811 00812 }; 00813 00814 00815 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00816 // DEFINITIONS 00817 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00818 // == Operators. 00825 LSE_INLINE LSBOOL LSE_CALL CImage::LSI_BLOCK::operator < ( const LSI_BLOCK &_bOther ) const { 00826 return fValues[0] < _bOther.fValues[0] && fValues[1] < _bOther.fValues[1] && 00827 fValues[2] < _bOther.fValues[2] && fValues[3] < _bOther.fValues[3]; 00828 } 00829 00836 LSE_INLINE LSBOOL LSE_CALL CImage::LSI_BLOCK::operator == ( const LSI_BLOCK &_bOther ) const { 00837 return fValues[0] == _bOther.fValues[0] && fValues[1] == _bOther.fValues[1] && 00838 fValues[2] == _bOther.fValues[2] && fValues[3] == _bOther.fValues[3]; 00839 } 00840 00847 LSE_INLINE LSBOOL LSE_CALL CImage::LSI_BLOCK::operator != ( const LSI_BLOCK &_bOther ) const { 00848 return fValues[0] != _bOther.fValues[0] || fValues[1] != _bOther.fValues[1] || 00849 fValues[2] != _bOther.fValues[2] || fValues[3] != _bOther.fValues[3]; 00850 } 00851 00852 // == Functions. 00858 LSE_INLINE LSUINT32 LSE_CALL CImage::GetWidth() const { 00859 return m_ui32Width; 00860 } 00861 00867 LSE_INLINE LSUINT32 LSE_CALL CImage::GetHeight() const { 00868 return m_ui32Height; 00869 } 00870 00876 LSE_INLINE LSI_PIXEL_FORMAT LSE_CALL CImage::GetFormat() const { 00877 return m_pfFormat; 00878 } 00879 00885 LSE_INLINE const LSVOID * LSE_CALL CImage::GetBufferData() const { 00886 return m_tbBuffer.Length() ? &m_tbBuffer[0] : NULL; 00887 } 00888 00894 LSE_INLINE const CImageLib::CTexelBuffer & LSE_CALL CImage::GetBufferDataAsVector() const { 00895 return m_tbBuffer; 00896 } 00902 LSE_INLINE const CVector<CImageLib::CTexelBuffer> & LSE_CALL CImage::GetMipMapBuffers() const { 00903 return m_vMipMapBuffer; 00904 } 00905 00912 LSE_INLINE const CImageLib::CTexelBuffer & LSE_CALL CImage::GetMipMapBuffers( LSUINT32 _ui32Level ) const { 00913 return _ui32Level == 0UL ? GetBufferDataAsVector() : GetMipMapBuffers()[_ui32Level-1UL]; 00914 } 00915 00921 LSE_INLINE LSUINT32 LSE_CALL CImage::TotalMipLevels() const { 00922 return GetMipMapBuffers().Length() + 1UL; 00923 } 00924 00934 LSE_INLINE LSUINT64 LSE_CALL CImage::GetTexelAt( LSI_PIXEL_FORMAT _pfFormat, LSUINT32 _ui32X, LSUINT32 _ui32Y ) const { 00935 assert( _pfFormat < LSI_PF_TOTAL_INT ); 00936 return CImageLib::IntegerTexelToIntegerTexel( GetFormat(), _pfFormat, (*reinterpret_cast<const LSUINT64 *>(&m_tbBuffer[_ui32Y*m_ui32RowWidth+_ui32X*m_ui32TexelSize])) ); 00937 } 00938 00947 LSE_INLINE LSVOID LSE_CALL CImage::SetTexelAt( LSUINT64 _ui64Texel, LSI_PIXEL_FORMAT _pfFormat, LSUINT32 _ui32X, LSUINT32 _ui32Y ) { 00948 assert( _pfFormat < LSI_PF_TOTAL_INT ); 00949 LSUINT64 ui64Converted = CImageLib::IntegerTexelToIntegerTexel( _pfFormat, GetFormat(), _ui64Texel ); 00950 00951 static const LSUINT64 ui64Mask[] = { 00952 0xFFFFFFFFFFFFFFFFULL, 00953 0xFFFFFFFFFFFFFF00ULL, 00954 0xFFFFFFFFFFFF0000ULL, 00955 0xFFFFFFFFFF000000ULL, 00956 0xFFFFFFFF00000000ULL, 00957 0xFFFFFF0000000000ULL, 00958 0xFFFF000000000000ULL, 00959 0xFF00000000000000ULL, 00960 0x0000000000000000ULL 00961 }; 00962 static const LSUINT64 ui32Sizes[] = { 00963 0x0000000000000000ULL, 00964 0x00000000000000FFULL, 00965 0x000000000000FFFFULL, 00966 0x0000000000FFFFFFULL, 00967 0x00000000FFFFFFFFULL, 00968 0x000000FFFFFFFFFFULL, 00969 0x0000FFFFFFFFFFFFULL, 00970 0x00FFFFFFFFFFFFFFULL, 00971 0xFFFFFFFFFFFFFFFFULL 00972 }; 00973 LSUINT32 ui32Size = CImageLib::GetFormatSize( GetFormat() ); 00974 00975 LSUINT64 * pui64Dst = reinterpret_cast<LSUINT64 *>(&m_tbBuffer[_ui32Y*m_ui32RowWidth+_ui32X*ui32Size]); 00976 (*pui64Dst) = ((*pui64Dst) & ui64Mask[ui32Size]) | (ui64Converted & ui32Sizes[ui32Size]); 00977 } 00978 00986 LSE_INLINE LSFLOAT LSE_CALL CImage::GetError( const LSI_BLOCK &_bColor0, const LSI_BLOCK &_bColor1 ) { 00987 /*LSFLOAT fR0 = _bColor0.s.fR * _bColor0.s.fR;//::powf( _bColor0.s.fR, 2.2f ); 00988 LSFLOAT fR1 = _bColor1.s.fR * _bColor1.s.fR;//::powf( _bColor1.s.fR, 2.2f ); 00989 00990 LSFLOAT fG0 = _bColor0.s.fG * _bColor0.s.fG;//::powf( _bColor0.s.fG, 2.2f ); 00991 LSFLOAT fG1 = _bColor1.s.fG * _bColor1.s.fG;//::powf( _bColor1.s.fG, 2.2f ); 00992 00993 LSFLOAT fB0 = _bColor0.s.fB * _bColor0.s.fB;//::powf( _bColor0.s.fB, 2.2f ); 00994 LSFLOAT fB1 = _bColor1.s.fB * _bColor1.s.fB;//::powf( _bColor1.s.fB, 2.2f ); 00995 00996 return (fR0 - fR1) * (fR0 - fR1) * LSI_R_WEIGHT + 00997 (fG0 - fG1) * (fG0 - fG1) * LSI_G_WEIGHT + 00998 (fB0 - fB1) * (fB0 - fB1) * LSI_B_WEIGHT;*/ 00999 return (_bColor0.s.fR - _bColor1.s.fR) * (_bColor0.s.fR - _bColor1.s.fR) * LSI_R_WEIGHT + 01000 (_bColor0.s.fG - _bColor1.s.fG) * (_bColor0.s.fG - _bColor1.s.fG) * LSI_G_WEIGHT + 01001 (_bColor0.s.fB - _bColor1.s.fB) * (_bColor0.s.fB - _bColor1.s.fB) * LSI_B_WEIGHT; 01002 } 01003 01014 LSE_INLINE LSFLOAT LSE_CALL CImage::GetError( LSUINT32 _ui32Channel, 01015 const LSI_BLOCK _bBlocks[4], const LSI_BLOCK &_bSrc, LSUINT32 &_ui32Index, LSBOOL _bOmitLast ) { 01016 return GetError( _ui32Channel, 01017 _bBlocks, _bSrc.fValues[_ui32Channel], _ui32Index, _bOmitLast ); 01018 } 01019 01030 LSE_INLINE LSFLOAT LSE_CALL CImage::GetError( LSUINT32 _ui32Channel, 01031 const LSI_BLOCK _bBlocks[4], LSFLOAT _fValue, LSUINT32 &_ui32Index, LSBOOL _bOmitLast ) { 01032 LSFLOAT fMinError = 2.0f; 01033 for ( LSUINT32 I = _bOmitLast ? 3UL : 4UL; I--; ) { 01034 LSFLOAT fError = _bBlocks[I].fValues[_ui32Channel] - _fValue; 01035 if ( CMathLib::Abs( fError ) < CMathLib::Abs( fMinError ) ) { 01036 fMinError = fError; 01037 _ui32Index = I; 01038 if ( fError == 0.0f ) { break; } 01039 } 01040 } 01041 return fMinError; 01042 } 01043 01050 LSE_INLINE LSUINT16 LSE_CALL CImage::ConvertBlockTexelTo16Bit( const LSI_BLOCK &_bColor ) { 01051 LSUINT16 ui16Ret = static_cast<LSUINT16>(static_cast<LSUINT16>(CStd::Clamp( _bColor.s.fR + (1.0f / 31.0f * 0.5f), 0.0f, 1.0f ) * 31.0f) << 11); 01052 ui16Ret |= static_cast<LSUINT16>(CStd::Clamp( _bColor.s.fG + (1.0f / 63.0f * 0.5f), 0.0f, 1.0f ) * 63.0f) << 5; 01053 ui16Ret |= static_cast<LSUINT16>(CStd::Clamp( _bColor.s.fB + (1.0f / 31.0f * 0.5f), 0.0f, 1.0f ) * 31.0f); 01054 return ui16Ret; 01055 } 01056 01063 LSE_INLINE CImage::LSI_BLOCK LSE_CALL CImage::Convert16BitToBlockTexel( LSUINT16 _ui16Color ) { 01064 LSI_BLOCK bColor; 01065 bColor.s.fR = (_ui16Color >> 11) * (1.0f / 31.0f); 01066 bColor.s.fG = ((_ui16Color >> 5) & 0x3F) * (1.0f / 63.0f); 01067 bColor.s.fB = (_ui16Color & 0x1F) * (1.0f / 31.0f); 01068 bColor.s.fA = 1.0f; 01069 return bColor; 01070 } 01071 01081 LSE_INLINE LSBOOL LSE_CALL CImage::Offset16BitColorChannel( LSUINT32 _ui32Channel, LSINT32 _i32Amount, LSUINT16 &_ui16Color ) { 01082 static const LSUINT32 ui32Shifts[4] = { 01083 11, // Red. 01084 5, // Green. 01085 0, // Blue. 01086 0, // Alpha. 01087 }; 01088 static const LSUINT32 ui32Bits[4] = { 01089 5, // Red. 01090 6, // Green. 01091 5, // Blue. 01092 0, // Alpha. 01093 }; 01094 static const LSUINT32 ui32Masks[4] = { 01095 (1UL << ui32Bits[0]) - 1UL, // Red. 01096 (1UL << ui32Bits[1]) - 1UL, // Green. 01097 (1UL << ui32Bits[2]) - 1UL, // Blue. 01098 (1UL << ui32Bits[3]) - 1UL, // Alpha. 01099 }; 01100 // Get the modified min. 01101 LSUINT32 ui32Mask = ui32Masks[_ui32Channel]; 01102 LSUINT32 ui32Min = (_ui16Color >> ui32Shifts[_ui32Channel]) & ui32Mask; 01103 if ( static_cast<LSINT32>(ui32Min) + _i32Amount < 0 || 01104 static_cast<LSINT32>(ui32Min) + _i32Amount > static_cast<LSINT32>(ui32Mask) ) { 01105 // Modifying by this amount would put the min out of its valid range. 01106 return false; 01107 } 01108 ui32Min += static_cast<LSUINT32>(_i32Amount); 01109 _ui16Color = static_cast<LSUINT16>(_ui16Color & ~(ui32Mask << ui32Shifts[_ui32Channel])); 01110 _ui16Color |= ui32Min << ui32Shifts[_ui32Channel]; 01111 return true; 01112 } 01113 01121 LSE_INLINE LSFLOAT LSE_CALL CImage::Round( LSFLOAT _fValue, LSFLOAT _fRes ) { 01122 return ::floorf( _fValue * _fRes + 0.5f ) / _fRes; 01123 } 01124 01125 } // namespace lsi 01126 01127 #endif // __LSI_IMAGE_H__