/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "LZWDecode.h" #include "FilterPredictor.h" #include "core/memcheck.h" // method performs decoding using namespace merge_lib; LZWDecode::LZWDecode(): _predict(NULL), _dummy(""), _encoded(_dummy), _curSymbolIndex(0), _earlyChange(1), _readBuf(0), _readBits(0), _nextCode(0), _bitsToRead(0), _curSequenceLength(0), _first(true) { clearTable(); } LZWDecode::~LZWDecode() { if( _predict ) { delete _predict; } } bool LZWDecode::encode(std::string & decoded) { return true; } void LZWDecode::initialize(Object * objectWithStream) { if( objectWithStream ) { std::string head; objectWithStream->getHeader(head); if( head.find(FilterPredictor::DECODE_PARAM_TOKEN) != -1 ) { _predict = new FilterPredictor(); _predict->initialize(objectWithStream); _earlyChange = _predict->getEarlyChange(); } _readBits = 0; _readBuf = 0; clearTable(); } } void LZWDecode::clearTable() { _nextCode = 258; _bitsToRead = 9; _curSequenceLength = 0; _first = true; } int LZWDecode::getCode() { int c = 0; int code = 0; while (_readBits < _bitsToRead) { if( _curSymbolIndex < _encoded.size() ) { c = _encoded[_curSymbolIndex++]; } else { return EOF; } _readBuf = (_readBuf << 8) | (c & 0xff); _readBits += 8; } code = (_readBuf >> (_readBits - _bitsToRead)) & ((1 << _bitsToRead) - 1); _readBits -= _bitsToRead; return code; } // Method performs LZW decoding bool LZWDecode::decode(std::string & encoded) { _curSymbolIndex = 0; _encoded = encoded; // LZW decoding std::string decoded; struct DecodingTable { int length; int head; unsigned tail; } decTable[4097]; int prevCode = 0; int newChar = 0; unsigned curSequence[4097]; int nextLength = 0; clearTable(); while(1) { int code = getCode(); if( code == EOF || code == 257 ) { // finish break; } if( code == 256 ) { clearTable(); continue; } if( _nextCode >= 4997 ) { std::cout<<"Bad LZW stream - unexpected clearTable\n"; clearTable(); continue; } nextLength = _curSequenceLength + 1; if( code < 256 ) { curSequence[ 0 ] = code; _curSequenceLength = 1; } else if( code < _nextCode ) { //lets take sequence from table _curSequenceLength = decTable[code].length; int j = code; for( int i = _curSequenceLength - 1; i > 0; i--) { curSequence[ i ] = decTable[j].tail; j = decTable[ j ].head; } curSequence[0] = j; } else if( code == _nextCode ) { curSequence[ _curSequenceLength ] = newChar; ++_curSequenceLength; } else { std::cout<<"Bad LZW stream - unexpected code "<decode(encoded); } return true; }