00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <stddef.h>
00015 #include <math.h>
00016 #include <ctype.h>
00017 #include <string.h>
00018
00019 #define BYTE char
00020 #define WORD short int
00021 #define LONG int
00022
00023 #define PACKIDENTIFIER "\nCCP4 packed image, X: %04d, Y: %04d\n"
00024 #define PACKBUFSIZ BUFSIZ
00025 #define DIFFBUFSIZ 16384L
00026 #define max(x, y) (((x) > (y)) ? (x) : (y))
00027 #define min(x, y) (((x) < (y)) ? (x) : (y))
00028 #define abs(x) (((x) < 0) ? (-(x)) : (x))
00029 const LONG setbits[33] = {0x00000000L, 0x00000001L, 0x00000003L, 0x00000007L,
00030 0x0000000FL, 0x0000001FL, 0x0000003FL, 0x0000007FL,
00031 0x000000FFL, 0x000001FFL, 0x000003FFL, 0x000007FFL,
00032 0x00000FFFL, 0x00001FFFL, 0x00003FFFL, 0x00007FFFL,
00033 0x0000FFFFL, 0x0001FFFFL, 0x0003FFFFL, 0x0007FFFFL,
00034 0x000FFFFFL, 0x001FFFFFL, 0x003FFFFFL, 0x007FFFFFL,
00035 0x00FFFFFFL, 0x01FFFFFFL, 0x03FFFFFFL, 0x07FFFFFFL,
00036 0x0FFFFFFFL, 0x1FFFFFFFL, 0x3FFFFFFFL, 0x7FFFFFFFL,
00037 0xFFFFFFFFL};
00038 #define shift_left(x, n) (((x) & setbits[32 - (n)]) << (n))
00039 #define shift_right(x, n) (((x) >> (n)) & setbits[32 - (n)])
00040
00041
00042
00043
00044
00045
00046
00047 LONG *diff_words (WORD *, int, int, LONG *, LONG );
00048 void get_pck (FILE *, WORD * );
00049 int put_pck (WORD *, int, int, int );
00050 static int pack_chunk ( );
00051 static void unpack_word (FILE *, int, int, WORD * );
00052 static void pack_longs ( );
00053 static int bits ( );
00054
00055
00056
00057
00058 int
00059 put_pck(WORD *img, int x, int y, int fdesc)
00060 {
00061 int chunksiz, packsiz, nbits, next_nbits, tot_nbits;
00062 LONG buffer[DIFFBUFSIZ];
00063 LONG *diffs = buffer;
00064 LONG *end = diffs - 1;
00065 LONG done = 0;
00066
00067 while(done < (x * y)) {
00068
00069 end = diff_words(img, x, y, buffer, done);
00070 done += (end - buffer) + 1;
00071
00072 diffs = buffer;
00073 while(diffs <= end) {
00074
00075 packsiz = 0;
00076 chunksiz = 1;
00077 nbits = bits(diffs, 1);
00078 while(packsiz == 0) {
00079
00080 if(end <= (diffs + chunksiz * 2))
00081 packsiz = chunksiz;
00082 else {
00083
00084 next_nbits = bits(diffs + chunksiz, chunksiz);
00085 tot_nbits = 2 * max(nbits, next_nbits);
00086
00087 if(tot_nbits >= (nbits + next_nbits + 6))
00088 packsiz = chunksiz;
00089 else {
00090
00091 nbits = tot_nbits;
00092 if(chunksiz == 64)
00093 packsiz = 128;
00094 else
00095 chunksiz *= 2;
00096 }
00097
00098 }
00099 }
00100
00101 if ( pack_chunk(diffs, packsiz, nbits / packsiz, fdesc) == 0)
00102 return( 0 );
00103 diffs += packsiz;
00104 }
00105 }
00106 if ( pack_chunk(NULL, 0, 0, fdesc) == 0 );
00107 return( 1 );
00108
00109 return( 1 );
00110 }
00111
00112
00113
00114
00115 static int
00116 bits(LONG *chunk, int n)
00117 {
00118 int size, maxsize, i;
00119
00120 for (i = 1, maxsize = abs(chunk[0]); i < n; ++i)
00121 maxsize = max(maxsize, abs(chunk[i]));
00122 if (maxsize == 0)
00123 size = 0;
00124 else if (maxsize < 8)
00125 size = 4 * n;
00126 else if (maxsize < 16)
00127 size = 5 * n;
00128 else if (maxsize < 32)
00129 size = 6 * n;
00130 else if (maxsize < 64)
00131 size = 7 * n;
00132 else if (maxsize < 128)
00133 size = 8 * n;
00134 else if (maxsize < 65536)
00135 size = 16 * n;
00136 else
00137 size = 32 * n;
00138 return(size);
00139 }
00140
00141
00142
00143
00144 static int
00145 pack_chunk(LONG *lng, int nmbr, int bitsize, int fdesc)
00146 {
00147 static LONG bitsize_encode[33] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0,
00148 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
00149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7};
00150 LONG descriptor[2], i, j;
00151 static BYTE *buffer = NULL;
00152 static BYTE *buffree = NULL;
00153 static int bitmark;
00154
00155 if(buffer == NULL) {
00156 buffree = buffer = (BYTE *) malloc(PACKBUFSIZ);
00157 bitmark = 0;
00158 }
00159
00160 if(lng != NULL) {
00161 for (i = nmbr, j = 0; i > 1; i /= 2, ++j);
00162 descriptor[0] = j;
00163 descriptor[1] = bitsize_encode[bitsize];
00164 if((buffree - buffer) > (PACKBUFSIZ - (130 * 4))) {
00165 if( write(fdesc, buffer,buffree - buffer) == -1 )
00166 return( 0 );
00167 buffer[0] = buffree[0];
00168 buffree = buffer;
00169 }
00170 pack_longs(descriptor, 2, &buffree, &bitmark, 3);
00171 pack_longs(lng, nmbr, &buffree, &bitmark, bitsize);
00172 }
00173 else {
00174 if( write(fdesc,buffer,(buffree - buffer) + 1) == -1 )
00175 return( 0 );
00176 free((void *) buffer);
00177 buffer = NULL;
00178 }
00179
00180 return( 1 );
00181 }
00182
00183
00184
00185
00186 LONG
00187 *diff_words(WORD *word, int x, int y, LONG *diffs, LONG done)
00188 {
00189 LONG i = 0;
00190 LONG tot = x * y;
00191
00192 if(done == 0)
00193 {
00194 *diffs = word[0];
00195 ++diffs;
00196 ++done;
00197 ++i;
00198 }
00199 while((done <= x) && (i < DIFFBUFSIZ))
00200 {
00201 *diffs = word[done] - word[done - 1];
00202 ++diffs;
00203 ++done;
00204 ++i;
00205 }
00206 while ((done < tot) && (i < DIFFBUFSIZ))
00207 {
00208 *diffs = word[done] - (word[done - 1] + word[done - x + 1] +
00209 word[done - x] + word[done - x - 1] + 2) / 4;
00210 ++diffs;
00211 ++done;
00212 ++i;
00213 }
00214 return(--diffs);
00215 }
00216
00217
00218
00219
00220 static void
00221 pack_longs(LONG *lng, int n, BYTE **target, int *bit, int size)
00222 {
00223 LONG mask, window;
00224 int valids, i, temp;
00225 int temp_bit = *bit;
00226 BYTE *temp_target = *target;
00227
00228 if (size > 0)
00229 {
00230 mask = setbits[size];
00231 for(i = 0; i < n; ++i)
00232 {
00233 window = lng[i] & mask;
00234 valids = size;
00235 if(temp_bit == 0)
00236 *temp_target = (BYTE) window;
00237 else
00238 {
00239 temp = shift_left(window, temp_bit);
00240 *temp_target |= temp;
00241 }
00242 window = shift_right(window, 8 - temp_bit);
00243 valids = valids - (8 - temp_bit);
00244 if(valids < 0)
00245 temp_bit += size;
00246 else
00247 {
00248 while (valids > 0)
00249 {
00250 *++temp_target = (BYTE) window;
00251 window = shift_right(window, 8);
00252 valids -= 8;
00253 }
00254 temp_bit = 8 + valids;
00255 }
00256 if(valids == 0)
00257 {
00258 temp_bit = 0;
00259 ++temp_target;
00260 }
00261 }
00262 *target = temp_target;
00263 *bit = (*bit + (size * n)) % 8;
00264 }
00265 }
00266
00267
00268
00269
00270 void
00271 get_pck(FILE *fp, WORD *img)
00272 {
00273 int x = 0, y = 0, i = 0, c = 0;
00274 char header[BUFSIZ];
00275
00276 if ( fp == NULL ) return;
00277 rewind ( fp );
00278 header[0] = '\n';
00279 header[1] = 0;
00280
00281 while ((c != EOF) && ((x == 0) || (y == 0))) {
00282 c = i = x = y = 0;
00283
00284 while ((++i < BUFSIZ) && (c != EOF) && (c != '\n') && (x==0) && (y==0))
00285 if ((header[i] = c = getc(fp)) == '\n')
00286 sscanf(header, PACKIDENTIFIER, &x, &y);
00287 }
00288
00289 unpack_word(fp, x, y, img);
00290 }
00291
00292
00293
00294
00295 static void
00296 unpack_word(FILE *packfile, int x, int y, WORD *img)
00297 {
00298 int valids = 0, spillbits = 0, usedbits, total = x * y;
00299 LONG window = 0L, spill, pixel = 0, nextint, bitnum, pixnum;
00300 static int bitdecode[8] = {0, 4, 5, 6, 7, 8, 16, 32};
00301
00302 while (pixel < total) {
00303 if (valids < 6) {
00304 if (spillbits > 0) {
00305 window |= shift_left(spill, valids);
00306 valids += spillbits;
00307 spillbits = 0;
00308 }
00309 else {
00310 spill = (LONG) getc(packfile);
00311 spillbits = 8;
00312 }
00313 }
00314 else {
00315 pixnum = 1 << (window & setbits[3]);
00316 window = shift_right(window, 3);
00317 bitnum = bitdecode[window & setbits[3]];
00318 window = shift_right(window, 3);
00319 valids -= 6;
00320 while ((pixnum > 0) && (pixel < total)) {
00321 if (valids < bitnum) {
00322 if (spillbits > 0) {
00323 window |= shift_left(spill, valids);
00324 if ((32 - valids) > spillbits) {
00325 valids += spillbits;
00326 spillbits = 0;
00327 }
00328 else {
00329 usedbits = 32 - valids;
00330 spill = shift_right(spill, usedbits);
00331 spillbits -= usedbits;
00332 valids = 32;
00333 }
00334 }
00335 else {
00336 spill = (LONG) getc(packfile);
00337 spillbits = 8;
00338 }
00339 }
00340 else {
00341 --pixnum;
00342 if (bitnum == 0)
00343 nextint = 0;
00344 else {
00345 nextint = window & setbits[bitnum];
00346 valids -= bitnum;
00347 window = shift_right(window, bitnum);
00348 if ((nextint & (1 << (bitnum - 1))) != 0)
00349 nextint |= ~setbits[bitnum];}
00350 if (pixel > x) {
00351 img[pixel] = (WORD) (nextint +
00352 (img[pixel-1] + img[pixel-x+1] +
00353 img[pixel-x] + img[pixel-x-1] + 2) / 4);
00354 ++pixel;
00355 }
00356 else if (pixel != 0) {
00357 img[pixel] = (WORD) (img[pixel - 1] + nextint);
00358 ++pixel;
00359 }
00360 else
00361 img[pixel++] = (WORD) nextint;
00362 }
00363 }
00364 }
00365 }
00366 }