00001
00002
00003
00004
00005
00006
00007
00008
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
00032 m_Bit = 0;
00033 m_nBit = 0;
00034
00035
00036
00037 memset( m_pDictionnary, 0, sizeof( m_pDictionnary ) );
00038
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
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
00095 m_pDictionnary[m_nDictionnary] = (u8)Size;
00096
00097 memcpy( &m_pDictionnary[m_nDictionnary + 1], pBuffer, Size );
00098
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
00110 if( m_pDictionnary[n] == Size )
00111 if( memcmp( &m_pDictionnary[n + 1], pBuffer, Size ) == 0 )
00112 return true;
00113
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
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
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
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
00176 Flush();
00177 MaxSize = *pOutSize;
00178 *pOutSize = 0;
00179
00180
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
00195 if( !IsStringIsInDictionnary( p, s ) )
00196 {
00197
00198 Output( pOutBuffer, *pOutSize, MaxSize, GetCode( p, s - 1 ) );
00199
00200 AddBufferToDictionnary( p, s );
00201 p[0] = p[s-1];
00202 s = 1;
00203 }
00204 }
00205
00206
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
00228 Flush();
00229 MaxSize = *pOutSize;
00230 *pOutSize = 0;
00231
00232
00233
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
00246 cW = Input( pBuffer, Size, Pos );
00247
00248
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
00257 pW = cW;
00258
00259
00260 cW = Input( pBuffer, Size, Pos );
00261
00262
00263 s = GetBuffer( cW, p );
00264 if( IsStringIsInDictionnary( p, s ) )
00265 {
00266
00267 KASSERT( *pOutSize + s < MaxSize );
00268 memcpy( &pOutBuffer[*pOutSize], p, s );
00269 *pOutSize += s;
00270
00271
00272 s = GetBuffer( pW, p );
00273 memcpy( P, p, s );
00274 SP = s;
00275
00276
00277 s = GetBuffer( cW, p );
00278 C = p[0];
00279
00280
00281 P[SP++] = C;
00282 AddBufferToDictionnary( P, SP );
00283 }
00284 else
00285 {
00286
00287 s = GetBuffer( pW, p );
00288 memcpy( P, p, s );
00289 SP = s;
00290
00291
00292 s = GetBuffer( cW, p );
00293 C = p[0];
00294
00295
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 }