/* ======================== idLZWCompressor::Start ======================== */ void idLZWCompressor::Start( uint8 * data_, int maxSize_, bool append ) { // Clear hash ClearHash(); if ( append ) { assert( lzwData->nextCode > LZW_FIRST_CODE ); int originalNextCode = lzwData->nextCode; lzwData->nextCode = LZW_FIRST_CODE; // If we are appending, then fill up the hash for ( int i = LZW_FIRST_CODE; i < originalNextCode; i++ ) { AddToDict( lzwData->dictionaryW[i], lzwData->dictionaryK[i] ); } assert( originalNextCode == lzwData->nextCode ); } else { for ( int i = 0; i < LZW_FIRST_CODE; i++ ) { lzwData->dictionaryK[i] = (uint8)i; lzwData->dictionaryW[i] = 0xFFFF; } lzwData->nextCode = LZW_FIRST_CODE; lzwData->codeBits = LZW_START_BITS; lzwData->codeWord = -1; lzwData->tempValue = 0; lzwData->tempBits = 0; lzwData->bytesWritten = 0; } oldCode = -1; // Used by DecompressBlock data = data_; blockSize = 0; blockIndex = 0; bytesRead = 0; maxSize = maxSize_; overflowed = false; savedBytesWritten = 0; savedCodeWord = 0; saveCodeBits = 0; savedTempValue = 0; savedTempBits = 0; }
/* ======================== idLZWCompressor::DecompressBlock ======================== */ void idLZWCompressor::DecompressBlock() { assert( blockIndex == blockSize ); // Make sure we've read all we can blockIndex = 0; blockSize = 0; int firstChar = -1; while( blockSize < LZW_BLOCK_SIZE - lzwCompressionData_t::LZW_DICT_SIZE ) { assert( lzwData->codeBits <= lzwCompressionData_t::LZW_DICT_BITS ); int code = ReadBits( lzwData->codeBits ); if( code == -1 ) { break; } if( oldCode == -1 ) { assert( code < 256 ); block[blockSize++] = ( uint8 )code; oldCode = code; firstChar = code; continue; } if( code >= lzwData->nextCode ) { assert( code == lzwData->nextCode ); firstChar = WriteChain( oldCode ); block[blockSize++] = ( uint8 )firstChar; } else { firstChar = WriteChain( code ); } AddToDict( oldCode, firstChar ); if( BumpBits() ) { oldCode = -1; } else { oldCode = code; } } }
/* ======================== idLZWCompressor::WriteByte ======================== */ void idLZWCompressor::WriteByte( uint8 value ) { int code = Lookup( lzwData->codeWord, value ); if ( code >= 0 ) { lzwData->codeWord = code; } else { WriteBits( lzwData->codeWord, lzwData->codeBits ); if ( !BumpBits() ) { AddToDict( lzwData->codeWord, value ); } lzwData->codeWord = value; } if ( lzwData->bytesWritten >= maxSize - ( lzwData->codeBits + lzwData->tempBits + 7 ) / 8 ) { overflowed = true; // At any point, if we can't perform an End call, then trigger an overflow return; } }