static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]) { /* char *outfile; output data stream int a[]; Array of values to encode int nx,ny; Array dimensions [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ int nx2, ny2, stat; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * Initialize bit output */ start_outputing_bits(); /* * write out the bit planes for each quadrant */ stat = qtree_encode(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); if (!stat) stat = qtree_encode(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); if (!stat) stat = qtree_encode(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); if (!stat) stat = qtree_encode(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); /* * Add zero as an EOF symbol */ output_nybble(outfile, 0); done_outputing_bits(outfile); return(stat); }
int fits_rcomp(int a[], /* input array */ int nx, /* number of input pixels */ unsigned char *c, /* output buffer */ int clen, /* max length of output */ int nblock) /* coding block size */ { Buffer bufmem, *buffer = &bufmem; /* int bsize; */ 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; /* * Original size of each pixel (bsize, bytes) and coding block * size (nblock, pixels) * Could make bsize a parameter to allow more efficient * compression of short & byte images. */ /* bsize = 4; */ /* nblock = 32; now an input parameter*/ /* * From bsize derive: * FSBITS = # bits required to store FS * FSMAX = maximum value for FS * BBITS = bits/pixel for direct coding */ /* switch (bsize) { case 1: fsbits = 3; fsmax = 6; break; case 2: fsbits = 4; fsmax = 14; break; case 4: fsbits = 5; fsmax = 25; break; default: ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes"); return(-1); } */ /* move out of switch block, to tweak performance */ fsbits = 5; fsmax = 25; bbits = 1<<fsbits; /* * Set up buffer pointers */ buffer->start = c; buffer->current = c; buffer->end = c+clen; buffer->bits_to_go = 8; /* * array for differences mapped to non-negative values */ diff = (unsigned int *) malloc(nblock*sizeof(unsigned int)); if (diff == (unsigned int *) NULL) { ffpmsg("fits_rcomp: insufficient memory"); return(-1); } /* * Code in blocks of nblock pixels */ start_outputing_bits(buffer); /* write out first int value to the first 4 bytes of the buffer */ if (output_nbits(buffer, a[0], 32) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } lastpix = a[0]; /* the first difference will always be zero */ thisblock = nblock; for (i=0; i<nx; i += nblock) { /* last block may be shorter */ if (nx-i < nblock) thisblock = nx-i; /* * Compute differences of adjacent pixels and map them to unsigned values. * Note that this may overflow the integer variables -- that's * OK, because we can recover when decompressing. If we were * compressing shorts or bytes, would want to do this arithmetic * with short/byte working variables (though diff will still be * passed as an int.) * * compute sum of mapped pixel values at same time * use double precision for sum to allow 32-bit integer inputs */ 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; } /* * compute number of bits to split from sum */ 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; /* * write the codes * fsbits ID bits used to indicate split level */ if (fs >= fsmax) { /* Special high entropy case when FS >= fsmax * Just write pixel difference values directly, no Rice coding at all. */ 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) { /* * special low entropy case when FS = 0 and pixelsum=0 (all * pixels in block are zero.) * Output a 0 and return */ if (output_nbits(buffer, 0, fsbits) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } } else { /* normal case: not either very high or very low entropy */ if (output_nbits(buffer, fs+1, fsbits) == EOF) { ffpmsg("rice_encode: end of buffer"); free(diff); return(-1); } fsmask = (1<<fs) - 1; /* * local copies of bit buffer to improve optimization */ lbitbuffer = buffer->bitbuffer; lbits_to_go = buffer->bits_to_go; for (j=0; j<thisblock; j++) { v = diff[j]; top = v >> fs; /* * top is coded by top zeros + 1 */ 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; } /* * bottom FS bits are written without coding * code is output_nbits, moved into this routine to reduce overheads * This code potentially breaks if FS>24, so I am limiting * FS to 24 by choice of FSMAX above. */ 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; } } } /* check if overflowed output buffer */ 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; } }