#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)
#include "fitsio2.h"
static void start_outputing_bits(Buffer *buffer);
static int done_outputing_bits(Buffer *buffer);
static int output_nbits(Buffer *buffer, int bits, int n);
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;
c += 4;
cend = c + clen - 4;
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_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;
}