#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const int nonzero_count[256] = {
0,
1,
2, 2,
3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
typedef unsigned char Buffer_t;
typedef struct
{
int bitbuffer;
int bits_to_go;
Buffer_t *start;
Buffer_t *current;
Buffer_t *end;
} Buffer;
#define putcbuf(c, mf) ((*(mf->current)++ = c), 0)
static void start_outputing_bits(Buffer *buffer);
static int done_outputing_bits(Buffer *buffer);
static int output_nbits(Buffer *buffer, int bits, int n);
void ffpmsg(const char *err_message)
{
printf("ABC");
printf(err_message);
}
int fits_rcomp(int a[],
int nx,
unsigned char *c,
int clen,
int nblock)
{
Buffer bufmem, *buffer = &bufmem;
int i, j, thisblock;
int lastpix, nextpix, pdiff;
int v, fs, fsmask, top, fsmax, fsbits, bbits;
int lbitbuffer, lbits_to_go;
unsigned int psum;
double pixelsum, dpsum;
unsigned int *diff;
fsbits = 5;
fsmax = 25;
bbits = 1 << fsbits;
buffer->start = c;
buffer->current = c;
buffer->end = c + clen;
buffer->bits_to_go = 8;
diff = (unsigned int *)malloc(nblock * sizeof(unsigned int));
if (diff == (unsigned int *)NULL)
{
ffpmsg("fits_rcomp: insufficient memory");
return (-1);
}
start_outputing_bits(buffer);
if (output_nbits(buffer, a[0], 32) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
lastpix = a[0];
thisblock = nblock;
for (i = 0; i < nx; i += nblock)
{
if (nx - i < nblock)
thisblock = nx - i;
pixelsum = 0.0;
for (j = 0; j < thisblock; j++)
{
nextpix = a[i + j];
pdiff = nextpix - lastpix;
diff[j] = (unsigned int)((pdiff < 0) ? ~(pdiff << 1) : (pdiff << 1));
pixelsum += diff[j];
lastpix = nextpix;
}
dpsum = (pixelsum - (thisblock / 2) - 1) / thisblock;
if (dpsum < 0)
dpsum = 0.0;
psum = ((unsigned int)dpsum) >> 1;
for (fs = 0; psum > 0; fs++)
psum >>= 1;
if (fs >= fsmax)
{
if (output_nbits(buffer, fsmax + 1, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
for (j = 0; j < thisblock; j++)
{
if (output_nbits(buffer, diff[j], bbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
}
}
else if (fs == 0 && pixelsum == 0)
{
if (output_nbits(buffer, 0, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
}
else
{
if (output_nbits(buffer, fs + 1, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
fsmask = (1 << fs) - 1;
lbitbuffer = buffer->bitbuffer;
lbits_to_go = buffer->bits_to_go;
for (j = 0; j < thisblock; j++)
{
v = diff[j];
top = v >> fs;
if (lbits_to_go >= top + 1)
{
lbitbuffer <<= top + 1;
lbitbuffer |= 1;
lbits_to_go -= top + 1;
}
else
{
lbitbuffer <<= lbits_to_go;
putcbuf(lbitbuffer & 0xff, buffer);
for (top -= lbits_to_go; top >= 8; top -= 8)
{
putcbuf(0, buffer);
}
lbitbuffer = 1;
lbits_to_go = 7 - top;
}
if (fs > 0)
{
lbitbuffer <<= fs;
lbitbuffer |= v & fsmask;
lbits_to_go -= fs;
while (lbits_to_go <= 0)
{
putcbuf((lbitbuffer >> (-lbits_to_go)) & 0xff, buffer);
lbits_to_go += 8;
}
}
}
if (buffer->current > buffer->end)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
buffer->bitbuffer = lbitbuffer;
buffer->bits_to_go = lbits_to_go;
}
}
done_outputing_bits(buffer);
free(diff);
return (buffer->current - buffer->start);
}
int fits_rcomp_short(
short a[],
int nx,
unsigned char *c,
int clen,
int nblock)
{
Buffer bufmem, *buffer = &bufmem;
int i, j, thisblock;
int lastpix, nextpix;
short pdiff;
int v, fs, fsmask, top, fsmax, fsbits, bbits;
int lbitbuffer, lbits_to_go;
unsigned short psum;
double pixelsum, dpsum;
unsigned int *diff;
fsbits = 4;
fsmax = 14;
bbits = 1 << fsbits;
buffer->start = c;
buffer->current = c;
buffer->end = c + clen;
buffer->bits_to_go = 8;
diff = (unsigned int *)malloc(nblock * sizeof(unsigned int));
if (diff == (unsigned int *)NULL)
{
ffpmsg("fits_rcomp: insufficient memory");
return (-1);
}
start_outputing_bits(buffer);
if (output_nbits(buffer, a[0], 16) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
lastpix = a[0];
thisblock = nblock;
for (i = 0; i < nx; i += nblock)
{
if (nx - i < nblock)
thisblock = nx - i;
pixelsum = 0.0;
for (j = 0; j < thisblock; j++)
{
nextpix = a[i + j];
pdiff = nextpix - lastpix;
diff[j] = (unsigned int)((pdiff < 0) ? ~(pdiff << 1) : (pdiff << 1));
pixelsum += diff[j];
lastpix = nextpix;
}
dpsum = (pixelsum - (thisblock / 2) - 1) / thisblock;
if (dpsum < 0)
dpsum = 0.0;
psum = ((unsigned short)dpsum) >> 1;
for (fs = 0; psum > 0; fs++)
psum >>= 1;
if (fs >= fsmax)
{
if (output_nbits(buffer, fsmax + 1, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
for (j = 0; j < thisblock; j++)
{
if (output_nbits(buffer, diff[j], bbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
}
}
else if (fs == 0 && pixelsum == 0)
{
if (output_nbits(buffer, 0, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
}
else
{
if (output_nbits(buffer, fs + 1, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
fsmask = (1 << fs) - 1;
lbitbuffer = buffer->bitbuffer;
lbits_to_go = buffer->bits_to_go;
for (j = 0; j < thisblock; j++)
{
v = diff[j];
top = v >> fs;
if (lbits_to_go >= top + 1)
{
lbitbuffer <<= top + 1;
lbitbuffer |= 1;
lbits_to_go -= top + 1;
}
else
{
lbitbuffer <<= lbits_to_go;
putcbuf(lbitbuffer & 0xff, buffer);
for (top -= lbits_to_go; top >= 8; top -= 8)
{
putcbuf(0, buffer);
}
lbitbuffer = 1;
lbits_to_go = 7 - top;
}
if (fs > 0)
{
lbitbuffer <<= fs;
lbitbuffer |= v & fsmask;
lbits_to_go -= fs;
while (lbits_to_go <= 0)
{
putcbuf((lbitbuffer >> (-lbits_to_go)) & 0xff, buffer);
lbits_to_go += 8;
}
}
}
if (buffer->current > buffer->end)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
buffer->bitbuffer = lbitbuffer;
buffer->bits_to_go = lbits_to_go;
}
}
done_outputing_bits(buffer);
free(diff);
return (buffer->current - buffer->start);
}
int fits_rcomp_byte(
signed char a[],
int nx,
unsigned char *c,
int clen,
int nblock)
{
Buffer bufmem, *buffer = &bufmem;
int i, j, thisblock;
int lastpix, nextpix;
signed char pdiff;
int v, fs, fsmask, top, fsmax, fsbits, bbits;
int lbitbuffer, lbits_to_go;
unsigned char psum;
double pixelsum, dpsum;
unsigned int *diff;
fsbits = 3;
fsmax = 6;
bbits = 1 << fsbits;
buffer->start = c;
buffer->current = c;
buffer->end = c + clen;
buffer->bits_to_go = 8;
diff = (unsigned int *)malloc(nblock * sizeof(unsigned int));
if (diff == (unsigned int *)NULL)
{
ffpmsg("fits_rcomp: insufficient memory");
return (-1);
}
start_outputing_bits(buffer);
if (output_nbits(buffer, a[0], 8) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
lastpix = a[0];
thisblock = nblock;
for (i = 0; i < nx; i += nblock)
{
if (nx - i < nblock)
thisblock = nx - i;
pixelsum = 0.0;
for (j = 0; j < thisblock; j++)
{
nextpix = a[i + j];
pdiff = nextpix - lastpix;
diff[j] = (unsigned int)((pdiff < 0) ? ~(pdiff << 1) : (pdiff << 1));
pixelsum += diff[j];
lastpix = nextpix;
}
dpsum = (pixelsum - (thisblock / 2) - 1) / thisblock;
if (dpsum < 0)
dpsum = 0.0;
psum = ((unsigned char)dpsum) >> 1;
for (fs = 0; psum > 0; fs++)
psum >>= 1;
if (fs >= fsmax)
{
if (output_nbits(buffer, fsmax + 1, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
for (j = 0; j < thisblock; j++)
{
if (output_nbits(buffer, diff[j], bbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
}
}
else if (fs == 0 && pixelsum == 0)
{
if (output_nbits(buffer, 0, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
}
else
{
if (output_nbits(buffer, fs + 1, fsbits) == EOF)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
fsmask = (1 << fs) - 1;
lbitbuffer = buffer->bitbuffer;
lbits_to_go = buffer->bits_to_go;
for (j = 0; j < thisblock; j++)
{
v = diff[j];
top = v >> fs;
if (lbits_to_go >= top + 1)
{
lbitbuffer <<= top + 1;
lbitbuffer |= 1;
lbits_to_go -= top + 1;
}
else
{
lbitbuffer <<= lbits_to_go;
putcbuf(lbitbuffer & 0xff, buffer);
for (top -= lbits_to_go; top >= 8; top -= 8)
{
putcbuf(0, buffer);
}
lbitbuffer = 1;
lbits_to_go = 7 - top;
}
if (fs > 0)
{
lbitbuffer <<= fs;
lbitbuffer |= v & fsmask;
lbits_to_go -= fs;
while (lbits_to_go <= 0)
{
putcbuf((lbitbuffer >> (-lbits_to_go)) & 0xff, buffer);
lbits_to_go += 8;
}
}
}
if (buffer->current > buffer->end)
{
ffpmsg("rice_encode: end of buffer");
free(diff);
return (-1);
}
buffer->bitbuffer = lbitbuffer;
buffer->bits_to_go = lbits_to_go;
}
}
done_outputing_bits(buffer);
free(diff);
return (buffer->current - buffer->start);
}
static void start_outputing_bits(Buffer *buffer)
{
buffer->bitbuffer = 0;
buffer->bits_to_go = 8;
}
static int output_nbits(Buffer *buffer, int bits, int n)
{
int lbitbuffer;
int lbits_to_go;
static unsigned int mask[33] =
{0,
0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff,
0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff,
0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
lbitbuffer = buffer->bitbuffer;
lbits_to_go = buffer->bits_to_go;
if (lbits_to_go + n > 32)
{
lbitbuffer <<= lbits_to_go;
lbitbuffer |= (bits >> (n - lbits_to_go)) & *(mask + lbits_to_go);
putcbuf(lbitbuffer & 0xff, buffer);
n -= lbits_to_go;
lbits_to_go = 8;
}
lbitbuffer <<= n;
lbitbuffer |= (bits & *(mask + n));
lbits_to_go -= n;
while (lbits_to_go <= 0)
{
putcbuf((lbitbuffer >> (-lbits_to_go)) & 0xff, buffer);
lbits_to_go += 8;
}
buffer->bitbuffer = lbitbuffer;
buffer->bits_to_go = lbits_to_go;
return (0);
}
static int done_outputing_bits(Buffer *buffer)
{
if (buffer->bits_to_go < 8)
{
putcbuf(buffer->bitbuffer << buffer->bits_to_go, buffer);
}
return (0);
}
int fits_rdecomp(unsigned char *c,
int clen,
unsigned int array[],
int nx,
int nblock)
{
int i, k, imax;
int nbits, nzero, fs;
unsigned char *cend, bytevalue;
unsigned int b, diff, lastpix;
int fsmax, fsbits, bbits;
extern const int nonzero_count[];
fsbits = 5;
fsmax = 25;
bbits = 1 << fsbits;
lastpix = 0;
bytevalue = c[0];
lastpix = lastpix | (bytevalue << 24);
bytevalue = c[1];
lastpix = lastpix | (bytevalue << 16);
bytevalue = c[2];
lastpix = lastpix | (bytevalue << 8);
bytevalue = c[3];
lastpix = lastpix | bytevalue;
k = 0;
int c_current = 0;
c += 4;
c_current += 4;
cend = c + clen - 4;
b = *c++;
c_current++;
nbits = 8;
for (i = 0; i < nx;)
{
nbits -= fsbits;
while (nbits < 0)
{
b = (b << 8) | (*c++);
c_current++;
nbits += 8;
}
fs = (b >> nbits) - 1;
b &= (1 << nbits) - 1;
imax = i + nblock;
if (imax > nx)
imax = nx;
if (fs < 0)
{
for (; i < imax; i++)
array[i] = lastpix;
}
else if (fs == fsmax)
{
for (; i < imax; i++)
{
k = bbits - nbits;
diff = b << k;
for (k -= 8; k >= 0; k -= 8)
{
b = *c++;
c_current++;
diff |= b << k;
}
if (nbits > 0)
{
b = *c++;
c_current++;
diff |= b >> (-k);
b &= (1 << nbits) - 1;
}
else
{
b = 0;
}
if ((diff & 1) == 0)
{
diff = diff >> 1;
}
else
{
diff = ~(diff >> 1);
}
array[i] = diff + lastpix;
lastpix = array[i];
}
}
else
{
for (; i < imax; i++)
{
while (b == 0)
{
nbits += 8;
b = *c++;
c_current++;
}
nzero = nbits - nonzero_count[b];
nbits -= nzero + 1;
b ^= 1 << nbits;
nbits -= fs;
while (nbits < 0)
{
b = (b << 8) | (*c++);
c_current++;
nbits += 8;
}
diff = (nzero << fs) | (b >> nbits);
b &= (1 << nbits) - 1;
if ((diff & 1) == 0)
{
diff = diff >> 1;
}
else
{
diff = ~(diff >> 1);
}
array[i] = diff + lastpix;
lastpix = array[i];
}
}
if (c > cend)
{
ffpmsg("decompression error: hit end of compressed byte stream");
return 1;
}
}
if (c < cend)
{
ffpmsg("decompression warning: unused bytes at end of compressed buffer");
}
return 0;
}
int fits_rdecomp_short(unsigned char *c,
int clen,
unsigned short array[],
int nx,
int nblock)
{
int i, imax;
int k;
int nbits, nzero, fs;
unsigned char *cend, bytevalue;
unsigned int b, diff, lastpix;
int fsmax, fsbits, bbits;
extern const int nonzero_count[];
fsbits = 4;
fsmax = 14;
bbits = 1 << fsbits;
lastpix = 0;
bytevalue = c[0];
lastpix = lastpix | (bytevalue << 8);
bytevalue = c[1];
lastpix = lastpix | bytevalue;
c += 2;
cend = c + clen - 2;
b = *c++;
nbits = 8;
for (i = 0; i < nx;)
{
nbits -= fsbits;
while (nbits < 0)
{
b = (b << 8) | (*c++);
nbits += 8;
}
fs = (b >> nbits) - 1;
b &= (1 << nbits) - 1;
imax = i + nblock;
if (imax > nx)
imax = nx;
if (fs < 0)
{
for (; i < imax; i++)
array[i] = lastpix;
}
else if (fs == fsmax)
{
for (; i < imax; i++)
{
k = bbits - nbits;
diff = b << k;
for (k -= 8; k >= 0; k -= 8)
{
b = *c++;
diff |= b << k;
}
if (nbits > 0)
{
b = *c++;
diff |= b >> (-k);
b &= (1 << nbits) - 1;
}
else
{
b = 0;
}
if ((diff & 1) == 0)
{
diff = diff >> 1;
}
else
{
diff = ~(diff >> 1);
}
array[i] = diff + lastpix;
lastpix = array[i];
}
}
else
{
for (; i < imax; i++)
{
while (b == 0)
{
nbits += 8;
b = *c++;
}
nzero = nbits - nonzero_count[b];
nbits -= nzero + 1;
b ^= 1 << nbits;
nbits -= fs;
while (nbits < 0)
{
b = (b << 8) | (*c++);
nbits += 8;
}
diff = (nzero << fs) | (b >> nbits);
b &= (1 << nbits) - 1;
if ((diff & 1) == 0)
{
diff = diff >> 1;
}
else
{
diff = ~(diff >> 1);
}
array[i] = diff + lastpix;
lastpix = array[i];
}
}
if (c > cend)
{
ffpmsg("decompression error: hit end of compressed byte stream");
return 1;
}
}
if (c < cend)
{
ffpmsg("decompression warning: unused bytes at end of compressed buffer");
}
return 0;
}
int fits_rdecomp_byte(unsigned char *c,
int clen,
unsigned char array[],
int nx,
int nblock)
{
int i, imax;
int k;
int nbits, nzero, fs;
unsigned char *cend;
unsigned int b, diff, lastpix;
int fsmax, fsbits, bbits;
extern const int nonzero_count[];
fsbits = 3;
fsmax = 6;
bbits = 1 << fsbits;
lastpix = c[0];
c += 1;
cend = c + clen - 1;
b = *c++;
nbits = 8;
for (i = 0; i < nx;)
{
nbits -= fsbits;
while (nbits < 0)
{
b = (b << 8) | (*c++);
nbits += 8;
}
fs = (b >> nbits) - 1;
b &= (1 << nbits) - 1;
imax = i + nblock;
if (imax > nx)
imax = nx;
if (fs < 0)
{
for (; i < imax; i++)
array[i] = lastpix;
}
else if (fs == fsmax)
{
for (; i < imax; i++)
{
k = bbits - nbits;
diff = b << k;
for (k -= 8; k >= 0; k -= 8)
{
b = *c++;
diff |= b << k;
}
if (nbits > 0)
{
b = *c++;
diff |= b >> (-k);
b &= (1 << nbits) - 1;
}
else
{
b = 0;
}
if ((diff & 1) == 0)
{
diff = diff >> 1;
}
else
{
diff = ~(diff >> 1);
}
array[i] = diff + lastpix;
lastpix = array[i];
}
}
else
{
for (; i < imax; i++)
{
while (b == 0)
{
nbits += 8;
b = *c++;
}
nzero = nbits - nonzero_count[b];
nbits -= nzero + 1;
b ^= 1 << nbits;
nbits -= fs;
while (nbits < 0)
{
b = (b << 8) | (*c++);
nbits += 8;
}
diff = (nzero << fs) | (b >> nbits);
b &= (1 << nbits) - 1;
if ((diff & 1) == 0)
{
diff = diff >> 1;
}
else
{
diff = ~(diff >> 1);
}
array[i] = diff + lastpix;
lastpix = array[i];
}
}
if (c > cend)
{
ffpmsg("decompression error: hit end of compressed byte stream");
return 1;
}
}
if (c < cend)
{
ffpmsg("decompression warning: unused bytes at end of compressed buffer");
}
return 0;
}