00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00032
00033
00034 tlzwstreamcompression :: tlzwstreamcompression ( void )
00035 {
00036 mode = none;
00037 initread = 0;
00038 initwrite = 0;
00039 DecodeBufferSize = 0;
00040 DecodeBuffer = NULL;
00041 rdictionary = NULL;
00042 readcnt = 0;
00043 wdictionary = NULL;
00044 }
00045
00046
00047 void tlzwstreamcompression :: LZWOut ( CodeType code )
00048 {
00049 writelzwdata ( &code, sizeof( CodeType )) ;
00050
00051 LZWTotBytesOut += 2;
00052 LZWCurrBytesOut += 2;
00053 }
00054
00055
00056
00057
00058
00059 IndexType tlzwstreamcompression :: LZWFind ( CodeType currcode, int in )
00060 {
00061 IndexType ndx;
00062 int step = 11, pastzero = 0;
00063
00064 ndx = ( ( IndexType ) currcode << 8 ) | in;
00065 ndx = ndx % DICTIONARY_SIZE;
00066
00067 for ( ;; )
00068 {
00069 if ( wdictionary[ ndx ].code == UNUSED_CODE )
00070 break;
00071 if ( wdictionary[ ndx ].parent == currcode &&
00072 wdictionary[ ndx ].c == in )
00073 break;
00074 ndx += step;
00075 if ( ndx >= DICTIONARY_SIZE)
00076 {
00077 ndx -= DICTIONARY_SIZE;
00078 pastzero += 1;
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 if ( pastzero > 5 )
00089 step = 1;
00090 }
00091
00092 }
00093 return ( ndx );
00094 }
00095
00096
00097 void tlzwstreamcompression :: initreading ( void )
00098 {
00099 if ( mode == none ) {
00100 char tempreadbuf[10];
00101 int tempreadbufsize = 0;
00102
00103 int lzw = 1;
00104 int i;
00105
00106 for (i = 0; i < strlen ( LZ_SIGNATURE ) + 3; i++) {
00107 try {
00108 readlzwdata ( &tempreadbuf[tempreadbufsize], 1 );
00109 tempreadbufsize++;
00110 }
00111
00112 catch ( treadafterend ) {
00113 tempreadbufsize--;
00114 lzw = 0;
00115 }
00116 }
00117
00118 if ( lzw ) {
00119 if ( tempreadbuf[0] )
00120 lzw = 0;
00121 if ( strcmp ( &tempreadbuf[1], LZ_SIGNATURE ) )
00122 lzw = 0;
00123 if ( tempreadbuf[strlen ( LZ_SIGNATURE ) + 2] )
00124 lzw = 0;
00125 }
00126 if ( lzw == 1 ) {
00127 mode = reading;
00128
00129 rdictionary = new Rdictionary [DICTIONARY_SIZE];
00130
00131 if ( rdictionary == NULL )
00132 throw toutofmem ( DICTIONARY_SIZE * sizeof( struct Rdictionary ) );
00133 } else {
00134 lzw = 2;
00135 if ( tempreadbuf[0] )
00136 lzw = 0;
00137 if ( strcmp ( &tempreadbuf[1], RLE_SIGNATURE ) )
00138 lzw = 0;
00139 if ( tempreadbuf[strlen ( RLE_SIGNATURE ) + 2] )
00140 lzw = 0;
00141
00142 if ( lzw == 2 ) {
00143 rlestartbyte = tempreadbuf[strlen ( RLE_SIGNATURE ) + 3];
00144
00145 rlenum = 0;
00146 mode = readingrle;
00147
00148 } else {
00149 for ( i = 0; i < tempreadbufsize; i++ )
00150 tempbuf.push ( tempreadbuf[i] );
00151
00152 mode = readingdirect;
00153 }
00154 }
00155 initread = 1;
00156
00157 } else
00158 if ( initwrite )
00159 throw tinvalidmode ( "tlzwstreamcompression ", tnstream::IOMode ( mode ), tnstream::reading );
00160 }
00161
00162
00163
00164 void tlzwstreamcompression :: initwriting ( void )
00165 {
00166 if ( mode == none ) {
00167
00168 freecode = STARTING_CODE;
00169
00170 LZWTotBytesIn = 0;
00171 LZWTotBytesOut = 0;
00172 LZWCurrBytesIn = 0;
00173 LZWCurrBytesOut = 0;
00174
00175 char c = 0;
00176 writelzwdata ( &c, 1 );
00177 writelzwdata ( LZ_SIGNATURE, strlen ( LZ_SIGNATURE ) + 1 );
00178 writelzwdata ( &c, 1 );
00179
00180
00181 wdictionary = new Wdictionary [ DICTIONARY_SIZE ];
00182
00183 if ( ! wdictionary )
00184 throw toutofmem ( DICTIONARY_SIZE * sizeof( struct Wdictionary ) );
00185
00186 for ( i = 0; i < DICTIONARY_SIZE; i++ )
00187 wdictionary[ i ].code = UNUSED_CODE;
00188
00189 currcodeloaded = 0;
00190
00191 initwrite = 1;
00192 mode = writing;
00193
00194 } else
00195 if ( initread )
00196 throw tinvalidmode ( "tlzwstreamcompression ", tnstream::IOMode ( mode ) , tnstream::writing );
00197 }
00198
00199
00200
00201 void tlzwstreamcompression :: writedata ( const void* buf, int size )
00202 {
00203 if ( !initwrite )
00204 initwriting();
00205
00206 const char* buf2 = (char*) buf;
00207 int pos = 0;
00208
00209 if ( size ) {
00210 if ( !currcodeloaded ) {
00211 currcode = buf2[pos++];
00212
00213 LZWTotBytesIn += 1;
00214 LZWCurrBytesIn += 1;
00215 currcode &= 0xFF;
00216
00217 currcodeloaded = 1;
00218 }
00219
00220 while ( pos < size )
00221 {
00222 in = buf2[pos++];
00223
00224 LZWTotBytesIn += 1;
00225 LZWCurrBytesIn += 1;
00226 idx = LZWFind ( currcode, in );
00227 if ( wdictionary[ idx ].code == UNUSED_CODE )
00228 {
00229
00230 LZWOut ( currcode );
00231
00232
00233 if ( freecode < MAX_CODE )
00234 {
00235 wdictionary[ idx ].c = in;
00236 wdictionary[ idx ].code = freecode++;
00237 wdictionary[ idx ].parent = currcode;
00238 }
00239 currcode = in;
00240
00241
00242 if ( LZWCurrBytesIn >= 10000 )
00243 {
00244 unsigned ratio;
00245 ratio = ( LZWCurrBytesOut * 100 ) /
00246 LZWCurrBytesIn;
00247
00248 LZWCurrBytesIn = 0;
00249 LZWCurrBytesOut = 0;
00250 if ( ratio > LZWBestRatio )
00251 {
00252 if ( ratio > 50 &&
00253 ( ratio > 90 ||
00254 ratio > LZWLastRatio + 10 ))
00255 {
00256 LZWOut ( NEW_DICTIONARY );
00257 for ( i = 0;
00258 i < DICTIONARY_SIZE; i++ )
00259 wdictionary[ i ].code =
00260 UNUSED_CODE;
00261 freecode = STARTING_CODE;
00262 }
00263 }
00264 else
00265 LZWBestRatio = ratio;
00266 LZWLastRatio = ratio;
00267 }
00268 }
00269 else
00270 currcode = wdictionary[ idx ].code;
00271
00272 }
00273 }
00274 }
00275
00276
00277
00278 void tlzwstreamcompression :: LZWIn ( void )
00279 {
00280 readlzwdata ( &incode, sizeof( CodeType ) );
00281 incode = SDL_SwapLE16( incode );
00282 }
00283
00284
00285
00286 unsigned tlzwstreamcompression :: LZWLoadBuffer ( unsigned count, CodeType code )
00287 {
00288 if ( code >= freecode )
00289 throw tbufferoverflow();
00290
00291 while ( code >= PRESET_CODE_MAX )
00292 {
00293 DecodeBuffer[ count++ ] = rdictionary[ code ].c;
00294 if ( count == DecodeBufferSize )
00295 {
00296 DecodeBuffer = (unsigned char *) realloc ( DecodeBuffer, DecodeBufferSize + 1000 );
00297
00298 if ( ! DecodeBuffer )
00299 throw toutofmem ( DecodeBufferSize + 1000 );
00300 else
00301 DecodeBufferSize += 1000;
00302 }
00303 code = rdictionary[ code ].parent;
00304 }
00305 DecodeBuffer[ count++ ] = code;
00306 return ( count );
00307 }
00308
00309
00310
00311 int tlzwstreamcompression :: readdata ( void* buf, int size, bool excpt )
00312 {
00313 if ( !initread )
00314 initreading();
00315
00316 int pos = 0;
00317 char* buf2 = (char*) buf ;
00318
00319
00320 if ( mode == readingdirect ) {
00321 int tp = 0;
00322 while ( pos < size && tempbuf.size() ) {
00323 buf2 [pos++] = tempbuf.front();
00324 tempbuf.pop();
00325 tp++;
00326 }
00327 if ( size-pos > 0 )
00328 tp += readlzwdata ( &buf2[pos], size-pos, excpt );
00329
00330 return tp;
00331
00332 } else
00333
00334
00335
00336 if ( mode == readingrle ) {
00337 while ( pos < size ) {
00338
00339 if ( rlenum ) {
00340 buf2[pos++] = rledata;
00341 rlenum--;
00342 } else {
00343
00344
00345
00346 if ( !readlzwdata ( &rledata, 1, excpt ))
00347 return pos;
00348
00349 if ( rledata == rlestartbyte ) {
00350 readlzwdata ( &rlenum, 1 );
00351 if ( rlenum > 2 )
00352 readlzwdata ( &rledata, 1 );
00353 } else
00354 buf2[pos++] = rledata;
00355 }
00356
00357 }
00358 return pos;
00359
00360 } else {
00361
00362 while ( pos < size && tempbuf.size() ) {
00363 buf2 [pos++] = tempbuf.front();
00364 tempbuf.pop();
00365 }
00366
00367
00368 if ( pos < size ) {
00369
00370
00371
00372 if (!DecodeBufferSize)
00373 {
00374 DecodeBufferSize = 1000;
00375 DecodeBuffer = (unsigned char * ) new char [ DecodeBufferSize ];
00376 if ( DecodeBuffer == NULL )
00377 throw toutofmem ( DecodeBufferSize );
00378 }
00379
00380
00381 if ( !readcnt ) {
00382
00383 priming:
00384 freecode = STARTING_CODE;
00385 LZWIn ( );
00386
00387 if ( incode == END_OF_INPUT )
00388 goto done;
00389
00390
00391
00392 oldcode = incode;
00393 inchar = incode;
00394 buf2[ pos++ ] = incode;
00395
00396 }
00397
00398 while ( pos < size ) {
00399 LZWIn ( );
00400
00401 if ( incode == END_OF_INPUT )
00402 break;
00403
00404 if ( incode == NEW_DICTIONARY )
00405 goto priming;
00406
00407 if ( incode >= freecode )
00408 {
00409
00410
00411
00412 count = LZWLoadBuffer ( 1, oldcode );
00413
00414
00415
00416
00417 DecodeBuffer[ 0 ] = inchar;
00418 }
00419 else
00420 count = LZWLoadBuffer ( 0, incode );
00421
00422 if ( count == 0 )
00423 throw ASCexception();
00424
00425 inchar = DecodeBuffer[ count - 1 ];
00426 while ( count )
00427 {
00428 if ( pos < size )
00429 buf2 [pos++] = DecodeBuffer[--count];
00430 else
00431 tempbuf.push ( DecodeBuffer[--count] );
00432 }
00433
00434
00435 if ( freecode < MAX_CODE )
00436 {
00437 rdictionary[ freecode ].parent = oldcode;
00438 rdictionary[ freecode ].c = inchar;
00439 freecode += 1;
00440
00441 }
00442 oldcode = incode;
00443 }
00444 }
00445 done:
00446 readcnt++;
00447
00448 return pos;
00449 }
00450
00451
00452 }
00453
00454
00455 void tlzwstreamcompression :: close( void )
00456 {
00457 if ( mode == writing ) {
00458 LZWOut ( currcode );
00459 LZWOut ( END_OF_INPUT );
00460 mode = none;
00461 }
00462 }
00463
00464
00465 tlzwstreamcompression :: ~tlzwstreamcompression ( )
00466 {
00467 if ( mode == writing )
00468 close();
00469
00470 if ( rdictionary ) {
00471 delete[] rdictionary;
00472 rdictionary = NULL;
00473 }
00474 if ( wdictionary ) {
00475 delete[] wdictionary;
00476 wdictionary = NULL;
00477 }
00478
00479 if ( DecodeBuffer ) {
00480 delete[] DecodeBuffer;
00481 DecodeBuffer = NULL;
00482 }
00483
00484 }