private bool LZWEncode(byte[] buffer, int offset, int count, short plane)
{
Debug.Assert(m_enc_hashtab != null);
if (m_enc_oldcode == -1 && count > 0)
{
// NB: This is safe because it can only happen at the start of a strip where we
// know there is space in the data buffer.
PutNextCode(CODE_CLEAR);
m_enc_oldcode = buffer[offset];
offset++;
count--;
m_enc_incount++;
}
while (count > 0)
{
int c = buffer[offset];
offset++;
count--;
m_enc_incount++;
int fcode = (c << BITS_MAX) + m_enc_oldcode;
int h = (c << HSHIFT) ^ m_enc_oldcode; // xor hashing
// Check hash index for an overflow.
if (h >= HSIZE)
h -= HSIZE;
if (m_enc_hashtab[h].hash == fcode)
{
m_enc_oldcode = m_enc_hashtab[h].code;
continue;
}
bool hit = false;
if (m_enc_hashtab[h].hash >= 0)
{
// Primary hash failed, check secondary hash.
int disp = HSIZE - h;
if (h == 0)
disp = 1;
do
{
h -= disp;
if (h < 0)
h += HSIZE;
if (m_enc_hashtab[h].hash == fcode)
{
m_enc_oldcode = m_enc_hashtab[h].code;
hit = true;
break;
}
}
while (m_enc_hashtab[h].hash >= 0);
}
if (!hit)
{
// New entry, emit code and add to table.
// Verify there is space in the buffer for the code and any potential Clear
// code that might be emitted below. The value of limit is setup so that there
// are at least 4 bytes free - room for 2 codes.
if (m_tif.m_rawcp > m_enc_rawlimit)
{
m_tif.m_rawcc = m_tif.m_rawcp;
m_tif.flushData1();
m_tif.m_rawcp = 0;
}
PutNextCode(m_enc_oldcode);
m_enc_oldcode = c;
m_enc_hashtab[h].code = m_free_ent;
m_free_ent++;
m_enc_hashtab[h].hash = fcode;
if (m_free_ent == CODE_MAX - 1)
{
// table is full, emit clear code and reset
cl_hash();
m_enc_ratio = 0;
m_enc_incount = 0;
m_enc_outcount = 0;
m_free_ent = CODE_FIRST;
PutNextCode(CODE_CLEAR);
m_nbits = BITS_MIN;
m_maxcode = CODE_MIN;
}
else
{
// If the next entry is going to be too big for the code size, then
// increase it, if possible.
if (m_free_ent > m_maxcode)
{
m_nbits++;
Debug.Assert(m_nbits <= BITS_MAX);
m_maxcode = (short)MAXCODE(m_nbits);
}
else if (m_enc_incount >= m_enc_checkpoint)
{
// Check compression ratio and, if things seem to be slipping, clear
// the hash table and reset state. The compression ratio is
// a 24 + 8-bit fractional number.
m_enc_checkpoint = m_enc_incount + CHECK_GAP;
int rat;
if (m_enc_incount > 0x007fffff)
{
// NB: shift will overflow
rat = m_enc_outcount >> 8;
rat = (rat == 0 ? 0x7fffffff : m_enc_incount / rat);
}
else
rat = (m_enc_incount << 8) / m_enc_outcount;
if (rat <= m_enc_ratio)
{
cl_hash();
m_enc_ratio = 0;
m_enc_incount = 0;
m_enc_outcount = 0;
m_free_ent = CODE_FIRST;
PutNextCode(CODE_CLEAR);
m_nbits = BITS_MIN;
m_maxcode = CODE_MIN;
}
else
m_enc_ratio = rat;
}
}
}
}
return true;
}