D:/Zythum/DinoKod/Common/Lzw.cpp

00001 //---------------------------------------------------------------------------------------------
00002 //      This file is a part of "DinoKod".
00003 //      Copyright © 2003 Dino Productions. All Rights Reserved.
00004 //      
00005 //      File                    : Lzw.h
00006 //      Author                  : Sebastien LEIX        sebastien.leix@wanadoo.fr
00007 //      Date                    : 01/01/2003
00008 //      Modification    :
00009 //
00010 //---------------------------------------------------------------------------------------------
00011 #include "Common/Assert.h"
00012 #include "Common/Error.h"
00013 #include "Common/Lzw.h"
00014 
00015 KLZW    g_Lzw;
00016 
00017 //--------------------------------------------------------------------------------------------------------------------------
00018 KLZW::KLZW()
00019 {
00020         Flush();
00021 }
00022 
00023 //--------------------------------------------------------------------------------------------------------------------------
00024 KLZW::~KLZW()
00025 {
00026 }
00027 
00028 //--------------------------------------------------------------------------------------------------------------------------
00029 void KLZW::Flush()
00030 {
00031         // Reset l'IO
00032         m_Bit = 0;
00033         m_nBit = 0;
00034 
00035         // Flush le dictionnaire
00036 //#if _DEBUG
00037         memset( m_pDictionnary, 0, sizeof( m_pDictionnary ) );
00038 //#endif _DEBUG
00039         m_nDictionnary = 0;
00040 }
00041 
00042 //--------------------------------------------------------------------------------------------------------------------------
00043 void KLZW::Output( u8* pBufferOut, s32& OutSize, s32 MaxSize, s32 Code )
00044 {
00045         KASSERT( Code <= ( pow( 2, LZW_NBITS ) - 1 ) );
00046 
00047         if( Code == LZW_MAX_VALUE )
00048         {
00049                 if( m_nBit )
00050                 {
00051                         // Flush
00052                         m_Bit |= 0 << ( (sizeof( m_Bit ) * 8) - (8 - m_nBit) );
00053                         m_nBit = 8;
00054                 }
00055         }
00056         else
00057         {
00058                 m_Bit |= Code << ( (sizeof( m_Bit ) * 8) - m_nBit - LZW_NBITS );
00059                 m_nBit += LZW_NBITS;
00060         }
00061 
00062         while( m_nBit >= 8 )
00063         {
00064                 KASSERT( OutSize < MaxSize );
00065                 pBufferOut[OutSize++] = (u8)(( m_Bit >> ( sizeof( m_Bit ) * 8 - 8 ) ) & 0xFF);
00066                 m_Bit <<= 8;
00067                 m_nBit -= 8;
00068         }
00069 }
00070 
00071 //--------------------------------------------------------------------------------------------------------------------------
00072 s32 KLZW::Input( u8* pBufferIn, s32 Size, s32 &Pos )
00073 {
00074         while( m_nBit < LZW_NBITS )
00075         {
00076                 m_Bit |= ( (s32)pBufferIn[Pos++] & 0xFF ) << ( ( sizeof( m_Bit ) * 8) - m_nBit - 8 );
00077                 m_nBit += 8;
00078         }
00079         
00080         s32 Code = ( m_Bit >> (sizeof( m_Bit ) * 8 - LZW_NBITS ) );
00081         m_Bit <<= LZW_NBITS;
00082         m_nBit -= LZW_NBITS;
00083 
00084         return Code;
00085 }
00086 
00087 //--------------------------------------------------------------------------------------------------------------------------
00088 void KLZW::AddBufferToDictionnary( u8* pBuffer, s32 Size )
00089 {
00090         KASSERT( Size > 0 );
00091         KASSERT( Size < 256 );
00092         KASSERT( sizeof( m_pDictionnary ) > ( m_nDictionnary + Size + 1 ) );
00093 
00094         // Ecrit la taille
00095         m_pDictionnary[m_nDictionnary] = (u8)Size;
00096         // Puis le buffer
00097         memcpy( &m_pDictionnary[m_nDictionnary + 1], pBuffer, Size );
00098         // Incremente le pointeur de dico
00099         m_nDictionnary += Size + 1;
00100 }
00101 
00102 //--------------------------------------------------------------------------------------------------------------------------
00103 bool KLZW::IsStringIsInDictionnary( u8* pBuffer, s32 Size )
00104 {
00105         s32     n = 0;
00106 
00107         while( n < m_nDictionnary )
00108         {
00109                 // Recherche dans le dico un buffer de meme taille
00110                 if( m_pDictionnary[n] ==  Size )
00111                         if( memcmp( &m_pDictionnary[n + 1], pBuffer, Size ) == 0 )
00112                                 return true;
00113                 // Va au buffer suivant
00114                 n += m_pDictionnary[n] + 1;
00115         }
00116 
00117         return false;
00118 }
00119 
00120 //--------------------------------------------------------------------------------------------------------------------------
00121 s32 KLZW::GetCode( u8* pBuffer, s32 Size )
00122 {
00123         s32     n = 0;
00124         s32     c = 0;
00125         
00126         while( n < m_nDictionnary )
00127         {
00128                 // Recherche dans le dico un buffer de meme taille
00129                 if( m_pDictionnary[n] == Size )
00130                         if( memcmp( &m_pDictionnary[n + 1], pBuffer, Size ) == 0 )
00131                                 if( c < LZW_MAX_CODE )
00132                                         return c;
00133                                 else
00134                                         KError::FatalError( NULL, "KLZW::GetCode(...) : Dictionnary full, LZW_MAX_CODE reached!" );
00135 
00136                 // Va au buffer suivant
00137                 n += m_pDictionnary[n] + 1;
00138                 c ++;
00139         }
00140 
00141         return -1;
00142 }
00143 
00144 //--------------------------------------------------------------------------------------------------------------------------
00145 s32 KLZW::GetBuffer( s32 Code, u8* pBuffer )
00146 {
00147         s32     n = 0;
00148         s32     c = 0;
00149         while( c < Code )
00150         {
00151                 if( n >= m_nDictionnary )
00152                 {
00153                         pBuffer = NULL;
00154                         return 0;
00155                 }
00156 
00157                 KASSERT( n < m_nDictionnary );
00158                 // Va au buffer suivant
00159                 n += m_pDictionnary[n] + 1;
00160                 c++;
00161         }
00162 
00163         memcpy( pBuffer, &m_pDictionnary[n + 1], m_pDictionnary[n] );
00164         return m_pDictionnary[n];
00165 }
00166 
00167 //--------------------------------------------------------------------------------------------------------------------------
00168 void KLZW::Compress( u8* pBuffer, s32 Size, u8* pOutBuffer, s32* pOutSize )
00169 {
00170         u8              p[1024];
00171         s32             s;
00172         s32             n;
00173         s32             MaxSize;
00174 
00175         // Init
00176         Flush();
00177         MaxSize = *pOutSize;
00178         *pOutSize = 0;
00179 
00180         // Initialise le dico
00181         n = 0;
00182         while( n < 256 )
00183         {
00184                 AddBufferToDictionnary( (u8*)&n, 1 );
00185                 n++;
00186         }
00187 
00188         n = 0;
00189         s = 0;
00190         while( n < Size )
00191         {
00192                 KASSERT( sizeof( p ) > s );
00193                 p[s++] = pBuffer[n++];
00194                 // Est ce que la chaine est dans le dico ?
00195                 if( !IsStringIsInDictionnary( p, s ) )
00196                 {
00197                         // Sort le buffer
00198                         Output( pOutBuffer, *pOutSize, MaxSize, GetCode( p, s - 1 ) );
00199                         // Ajoute dans le dico
00200                         AddBufferToDictionnary( p, s );
00201                         p[0] = p[s-1];
00202                         s = 1;
00203                 }
00204         }
00205 
00206         // Flush
00207         Output( pOutBuffer, *pOutSize, MaxSize, GetCode( p, s ) );
00208         Output( pOutBuffer, *pOutSize, MaxSize, LZW_MAX_VALUE );
00209         Flush();
00210 }
00211 
00212 //--------------------------------------------------------------------------------------------------------------------------
00213 void KLZW::Expand( u8* pBuffer, s32 Size, u8* pOutBuffer, s32* pOutSize )
00214 {
00215         u8              p[1024];
00216         s32             s;
00217         u8              P[1024];
00218         s32             SP;
00219         u8              C;
00220         s32             cW;
00221         s32             pW;
00222 
00223         s32             n;
00224         s32             Pos;
00225         s32             MaxSize;
00226 
00227         // Init
00228         Flush();
00229         MaxSize = *pOutSize;
00230         *pOutSize = 0;
00231 
00232         // Initialise le dico
00233         // 1
00234         n = 0;
00235         while( n < 256 )
00236         {
00237                 AddBufferToDictionnary( (u8*)&n, 1 );
00238                 n++;
00239         }
00240 
00241         n = 0;
00242         SP = 0;
00243         Pos = 0;
00244 
00245         // 2
00246         cW = Input( pBuffer, Size, Pos );
00247 
00248         // 3
00249         s = GetBuffer( cW, p );
00250         KASSERT( *pOutSize + s < MaxSize );
00251         memcpy( &pOutBuffer[*pOutSize], p, s );
00252         *pOutSize += s;
00253 
00254         while( Pos < Size )
00255         {
00256                 // 4
00257                 pW = cW;
00258 
00259                 // 5
00260                 cW = Input( pBuffer, Size, Pos );
00261 
00262                 // 6
00263                 s = GetBuffer( cW, p );
00264                 if( IsStringIsInDictionnary( p, s ) )
00265                 {
00266                         // i. Output
00267                         KASSERT( *pOutSize + s < MaxSize );
00268                         memcpy( &pOutBuffer[*pOutSize], p, s );
00269                         *pOutSize += s;
00270                         
00271                         // ii.
00272                         s = GetBuffer( pW, p );
00273                         memcpy( P, p, s );
00274                         SP = s;
00275 
00276                         // iii.
00277                         s = GetBuffer( cW, p );
00278                         C = p[0];
00279                         
00280                         // iv.
00281                         P[SP++] = C;
00282                         AddBufferToDictionnary( P, SP );
00283                 }
00284                 else
00285                 {
00286                         // i.
00287                         s = GetBuffer( pW, p );
00288                         memcpy( P, p, s );
00289                         SP = s;
00290 
00291                         // ii. 
00292                         s = GetBuffer( cW, p );
00293                         C = p[0];
00294 
00295                         // iii.
00296                         P[SP++] = C;
00297                         AddBufferToDictionnary( P, SP );
00298                         KASSERT( *pOutSize + s < MaxSize );
00299                         memcpy( &pOutBuffer[*pOutSize], P, SP );
00300                         *pOutSize += SP;
00301                 }
00302         }
00303         Flush();
00304 }

Generated on Sun Mar 25 20:02:10 2007 for Zythum Project by  doxygen 1.5.1-p1