void StringTable::CompressStart(int bpp, int width) { m_bpp = bpp; m_slack = (8 - ((width * bpp) % 8)) % 8; m_partial |= m_clearCode << m_partialSize; m_partialSize += m_codeSize; ClearCompressorTable(); }
void StringTable::Initialize(int minCodeSize) { m_done = false; m_bpp = 8; m_minCodeSize = minCodeSize; m_clearCode = 1 << m_minCodeSize; m_endCode = m_clearCode + 1; m_partial = 0; m_partialSize = 0; m_bufferSize = 0; ClearCompressorTable(); ClearDecompressorTable(); }
bool StringTable::Compress(BYTE *buf, int *len) { if( m_bufferSize == 0 || m_done ) { return false; } int mask = (1 << m_bpp) - 1; BYTE *bufpos = buf; while( m_bufferPos < m_bufferSize ) { //get the current pixel value char ch = (char)((m_buffer[m_bufferPos] >> m_bufferShift) & mask); // The next prefix is : // <the previous LZW code (on 12 bits << 8)> | <the code of the current pixel (on 8 bits)> int nextprefix = (((m_prefix)<<8)&0xFFF00) + (ch & 0x000FF); if(firstPixelPassed) { if( m_strmap[nextprefix] > 0) { m_prefix = m_strmap[nextprefix]; } else { m_partial |= m_prefix << m_partialSize; m_partialSize += m_codeSize; //grab full bytes for the output buffer while( m_partialSize >= 8 && bufpos - buf < *len ) { *bufpos++ = (BYTE)m_partial; m_partial >>= 8; m_partialSize -= 8; } //add the code to the "table map" m_strmap[nextprefix] = m_nextCode; //increment the next highest valid code, increase the code size if( m_nextCode == (1 << m_codeSize) ) { m_codeSize++; } m_nextCode++; //if we're out of codes, restart the string table if( m_nextCode == MAX_LZW_CODE ) { m_partial |= m_clearCode << m_partialSize; m_partialSize += m_codeSize; ClearCompressorTable(); } // Only keep the 8 lowest bits (prevent problems with "negative chars") m_prefix = ch & 0x000FF; } //increment to the next pixel if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) { m_bufferShift -= m_bpp; } else { m_bufferPos++; m_bufferShift = 8 - m_bpp; } //jump out here if the output buffer is full if( bufpos - buf == *len ) { return true; } } else { // Specific behavior for the first pixel of the whole image firstPixelPassed=1; // Only keep the 8 lowest bits (prevent problems with "negative chars") m_prefix = ch & 0x000FF; //increment to the next pixel if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) { m_bufferShift -= m_bpp; } else { m_bufferPos++; m_bufferShift = 8 - m_bpp; } //jump out here if the output buffer is full if( bufpos - buf == *len ) { return true; } } }
bool StringTable::Compress(BYTE *buf, int *len) { if( m_bufferSize == 0 || m_done ) { return false; } int mask = (1 << m_bpp) - 1; BYTE *bufpos = buf; while( m_bufferPos < m_bufferSize ) { //get the current pixel value char ch = (m_buffer[m_bufferPos] >> m_bufferShift) & mask; std::string nextprefix = m_prefix + ch; if( m_strmap.find(nextprefix) != m_strmap.end() ) { m_prefix = nextprefix; } else { m_partial |= m_strmap[m_prefix] << m_partialSize; m_partialSize += m_codeSize; //grab full bytes for the output buffer while( m_partialSize >= 8 && bufpos - buf < *len ) { *bufpos++ = (BYTE)m_partial; m_partial >>= 8; m_partialSize -= 8; } //add the string to the table map m_strmap[nextprefix] = m_nextCode; //increment the next highest valid code, increase the code size if( m_nextCode == (1 << m_codeSize) ) { m_codeSize++; } m_nextCode++; //if we're out of codes, restart the string table if( m_nextCode == MAX_LZW_CODE ) { m_partial |= m_clearCode << m_partialSize; m_partialSize += m_codeSize; ClearCompressorTable(); } m_prefix = ch; } //increment to the next pixel if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) { m_bufferShift -= m_bpp; } else { m_bufferPos++; m_bufferShift = 8 - m_bpp; } //jump out here if the output buffer is full if( bufpos - buf == *len ) { return true; } } m_bufferSize = 0; *len = bufpos - buf; return true; }