4
/*****************************************************************************/
6
/* This file, fits_hcompress.c, contains the code required to compress */
7
/* data using the HCOMPRESS_1 compression format. */
9
/* Copyright (C) 2004 Association of Universities for Research in Astronomy */
12
/* Redistribution and use in source and binary forms, with or without */
13
/* modification, are permitted provided that the following conditions are */
16
/* 1. Redistributions of source code must retain the above copyright */
17
/* notice, this list of conditions and the following disclaimer. */
19
/* 2. Redistributions in binary form must reproduce the above */
20
/* copyright notice, this list of conditions and the following */
21
/* disclaimer in the documentation and/or other materials provided */
22
/* with the distribution. */
24
/* 3. The name of AURA and its representatives may not be used to */
25
/* endorse or promote products derived from this software without */
26
/* specific prior written permission. */
28
/* THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED */
29
/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
30
/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
31
/* DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, */
32
/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
33
/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS */
34
/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND */
35
/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR */
36
/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE */
37
/* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH */
40
/* This file was copied intact from the FITSIO software that was written by */
41
/* William Pence at the High Energy Astrophysic Science Archive Research */
42
/* Center (HEASARC) at the NASA Goddard Space Flight Center. That software */
43
/* contained the following copyright and warranty notices: */
45
/* Copyright (Unpublished--all rights reserved under the copyright laws of */
46
/* the United States), U.S. Government as represented by the Administrator */
47
/* of the National Aeronautics and Space Administration. No copyright is */
48
/* claimed in the United States under Title 17, U.S. Code. */
50
/* Permission to freely use, copy, modify, and distribute this software */
51
/* and its documentation without fee is hereby granted, provided that this */
52
/* copyright notice and disclaimer of warranty appears in all copies. */
56
/* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, */
57
/* EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, */
58
/* ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY */
59
/* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR */
60
/* PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE */
61
/* DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE */
62
/* SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY */
63
/* DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR */
64
/* CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY */
65
/* CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, */
66
/* CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY */
67
/* PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED */
68
/* FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR */
69
/* SERVICES PROVIDED HEREUNDER." */
71
/*****************************************************************************/
73
/* #########################################################################
74
These routines to apply the H-compress compression algorithm to a 2-D Fits
75
image were written by R. White at the STScI and were obtained from the STScI at
76
http://www.stsci.edu/software/hcompress.html
78
This source file is a concatination of the following sources files in the
88
The following modifications have been made to the original code:
90
- commented out redundant "include" statements
91
- added the noutchar global variable
92
- changed all the 'extern' declarations to 'static', since all the routines are in
94
- changed the first parameter in encode (and in lower level routines from a file stream
96
- modifid the encode routine to return the size of the compressed array of bytes
97
- changed calls to printf and perror to call the CFITSIO ffpmsg routine
98
- modified the mywrite routine, and lower level byte writing routines, to copy
99
the output bytes to a char array, instead of writing them to a file stream
100
- replace "exit" statements with "return" statements
101
- changed the function declarations to the more modern ANSI C style
103
############################################################################ */
111
static long noutchar;
114
static int htrans(int a[],int nx,int ny);
115
static void digitize(int a[], int nx, int ny, int scale);
116
static int encode(char *outfile, long *nlen, int a[], int nx, int ny, int scale);
117
static void shuffle(int a[], int n, int n2, int tmp[]);
119
static int htrans64(LONGLONG a[],int nx,int ny);
120
static void digitize64(LONGLONG a[], int nx, int ny, int scale);
121
static int encode64(char *outfile, long *nlen, LONGLONG a[], int nx, int ny, int scale);
122
static void shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]);
124
static void writeint(char *outfile, int a);
125
static void writelonglong(char *outfile, LONGLONG a);
126
static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]);
127
static int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]);
128
static int qwrite(char *file, char buffer[], int n);
130
static int qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes);
131
static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes);
132
static void start_outputing_bits(void);
133
static void done_outputing_bits(char *outfile);
134
static void output_nbits(char *outfile, int bits, int n);
136
static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit);
137
static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit);
138
static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]);
139
static int bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax);
140
static void write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit);
141
static void write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit);
143
/* #define output_nybble(outfile,c) output_nbits(outfile,c,4) */
144
static void output_nybble(char *outfile, int bits);
145
static void output_nnybble(char *outfile, int n, unsigned char array[]);
147
#define output_huffman(outfile,c) output_nbits(outfile,code[c],ncode[c])
149
/* ---------------------------------------------------------------------- */
150
int _pyfits_fits_hcompress(int *a, int ny, int nx, int scale, char *output,
151
long *nbytes, int *status)
154
compress the input image using the H-compress algorithm
156
a - input image array
157
nx - size of X axis of image
158
ny - size of Y axis of image
159
scale - quantization scale factor. Larger values results in more (lossy) compression
160
scale = 0 does lossless compression
161
output - pre-allocated array to hold the output compressed stream of bytes
162
nbyts - input value = size of the output buffer;
163
returned value = size of the compressed byte stream, in bytes
165
NOTE: the nx and ny dimensions as defined within this code are reversed from
166
the usual FITS notation. ny is the fastest varying dimension, which is
167
usually considered the X axis in the FITS image display
173
if (*status > 0) return(*status);
176
stat = htrans(a, nx, ny);
183
digitize(a, nx, ny, scale);
185
/* encode and write to output array */
187
noutmax = *nbytes; /* input value is the allocated size of the array */
188
*nbytes = 0; /* reset */
190
stat = encode(output, nbytes, a, nx, ny, scale);
195
/* ---------------------------------------------------------------------- */
196
int _pyfits_fits_hcompress64(LONGLONG *a, int ny, int nx, int scale,
197
char *output, long *nbytes, int *status)
200
compress the input image using the H-compress algorithm
202
a - input image array
203
nx - size of X axis of image
204
ny - size of Y axis of image
205
scale - quantization scale factor. Larger values results in more (lossy) compression
206
scale = 0 does lossless compression
207
output - pre-allocated array to hold the output compressed stream of bytes
208
nbyts - size of the compressed byte stream, in bytes
210
NOTE: the nx and ny dimensions as defined within this code are reversed from
211
the usual FITS notation. ny is the fastest varying dimension, which is
212
usually considered the X axis in the FITS image display
218
if (*status > 0) return(*status);
221
stat = htrans64(a, nx, ny);
228
digitize64(a, nx, ny, scale);
230
/* encode and write to output array */
231
noutmax = *nbytes; /* input value is the allocated size of the array */
232
*nbytes = 0; /* reset */
234
stat = encode64(output, nbytes, a, nx, ny, scale);
241
/* Copyright (c) 1993 Association of Universities for Research
242
* in Astronomy. All rights reserved. Produced under National
243
* Aeronautics and Space Administration Contract No. NAS5-26555.
245
/* htrans.c H-transform of NX x NY integer image
247
* Programmer: R. White Date: 11 May 1992
250
/* ######################################################################### */
251
static int htrans(int a[],int nx,int ny)
253
int nmax, log2n, h0, hx, hy, hc, nxtop, nytop, i, j, k;
255
int shift, mask, mask2, prnd, prnd2, nrnd2;
260
* log2n is log2 of max(nx,ny) rounded up to next power of 2
262
nmax = (nx>ny) ? nx : ny;
263
log2n = (int) (log((float) nmax)/log(2.0)+0.5);
264
if ( nmax > (1<<log2n) ) {
268
* get temporary storage for shuffling elements
270
tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
271
if(tmp == (int *) NULL) {
272
_pyfits_ffpmsg("htrans: insufficient memory");
273
return(DATA_COMPRESSION_ERR);
276
* set up rounding and shifting masks
285
* do log2n reductions
287
* We're indexing a as a 2-D array with dimensions (nx,ny).
292
for (k = 0; k<log2n; k++) {
295
for (i = 0; i<nxtop-oddx; i += 2) {
296
s00 = i*ny; /* s00 is index of a[i,j] */
297
s10 = s00+ny; /* s10 is index of a[i+1,j] */
298
for (j = 0; j<nytop-oddy; j += 2) {
300
* Divide h0,hx,hy,hc by 2 (1 the first time through).
302
h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> shift;
303
hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift;
304
hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift;
305
hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift;
308
* Throw away the 2 bottom bits of h0, bottom bit of hx,hy.
309
* To get rounding to be same for positive and negative
310
* numbers, nrnd2 = prnd2 - 1.
313
a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ;
314
a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ;
315
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
321
* do last element in row if row length is odd
322
* s00+1, s10+1 are off edge
324
h0 = (a[s10] + a[s00]) << (1-shift);
325
hx = (a[s10] - a[s00]) << (1-shift);
326
a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ;
327
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
334
* do last row if column length is odd
335
* s10, s10+1 are off edge
338
for (j = 0; j<nytop-oddy; j += 2) {
339
h0 = (a[s00+1] + a[s00]) << (1-shift);
340
hy = (a[s00+1] - a[s00]) << (1-shift);
341
a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ;
342
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
347
* do corner element if both row and column lengths are odd
348
* s00+1, s10, s10+1 are off edge
350
h0 = a[s00] << (2-shift);
351
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
355
* now shuffle in each dimension to group coefficients by order
357
for (i = 0; i<nxtop; i++) {
358
shuffle(&a[ny*i],nytop,1,tmp);
360
for (j = 0; j<nytop; j++) {
361
shuffle(&a[j],nxtop,ny,tmp);
364
* image size reduced by 2 (round up if odd)
366
nxtop = (nxtop+1)>>1;
367
nytop = (nytop+1)>>1;
369
* divisor doubles after first reduction
373
* masks, rounding values double after each iteration
384
/* ######################################################################### */
386
static int htrans64(LONGLONG a[],int nx,int ny)
388
int nmax, log2n, nxtop, nytop, i, j, k;
392
LONGLONG h0, hx, hy, hc, prnd, prnd2, nrnd2, mask, mask2;
396
* log2n is log2 of max(nx,ny) rounded up to next power of 2
398
nmax = (nx>ny) ? nx : ny;
399
log2n = (int) (log((float) nmax)/log(2.0)+0.5);
400
if ( nmax > (1<<log2n) ) {
404
* get temporary storage for shuffling elements
406
tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
407
if(tmp == (LONGLONG *) NULL) {
408
_pyfits_ffpmsg("htrans64: insufficient memory");
409
return(DATA_COMPRESSION_ERR);
412
* set up rounding and shifting masks
415
mask = (LONGLONG) -2;
421
* do log2n reductions
423
* We're indexing a as a 2-D array with dimensions (nx,ny).
428
for (k = 0; k<log2n; k++) {
431
for (i = 0; i<nxtop-oddx; i += 2) {
432
s00 = i*ny; /* s00 is index of a[i,j] */
433
s10 = s00+ny; /* s10 is index of a[i+1,j] */
434
for (j = 0; j<nytop-oddy; j += 2) {
436
* Divide h0,hx,hy,hc by 2 (1 the first time through).
438
h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> shift;
439
hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift;
440
hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift;
441
hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift;
444
* Throw away the 2 bottom bits of h0, bottom bit of hx,hy.
445
* To get rounding to be same for positive and negative
446
* numbers, nrnd2 = prnd2 - 1.
449
a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ;
450
a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ;
451
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
457
* do last element in row if row length is odd
458
* s00+1, s10+1 are off edge
460
h0 = (a[s10] + a[s00]) << (1-shift);
461
hx = (a[s10] - a[s00]) << (1-shift);
462
a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ;
463
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
470
* do last row if column length is odd
471
* s10, s10+1 are off edge
474
for (j = 0; j<nytop-oddy; j += 2) {
475
h0 = (a[s00+1] + a[s00]) << (1-shift);
476
hy = (a[s00+1] - a[s00]) << (1-shift);
477
a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ;
478
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
483
* do corner element if both row and column lengths are odd
484
* s00+1, s10, s10+1 are off edge
486
h0 = a[s00] << (2-shift);
487
a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
491
* now shuffle in each dimension to group coefficients by order
493
for (i = 0; i<nxtop; i++) {
494
shuffle64(&a[ny*i],nytop,1,tmp);
496
for (j = 0; j<nytop; j++) {
497
shuffle64(&a[j],nxtop,ny,tmp);
500
* image size reduced by 2 (round up if odd)
502
nxtop = (nxtop+1)>>1;
503
nytop = (nytop+1)>>1;
505
* divisor doubles after first reduction
509
* masks, rounding values double after each iteration
521
/* ######################################################################### */
523
shuffle(int a[], int n, int n2, int tmp[])
527
int a[]; array to shuffle
528
int n; number of elements to shuffle
529
int n2; second dimension
530
int tmp[]; scratch storage
537
* copy odd elements to tmp
541
for (i=1; i < n; i += 2) {
547
* compress even elements into first half of A
551
for (i=2; i<n; i += 2) {
557
* put odd elements into 2nd half
560
for (i = 1; i<n; i += 2) {
566
/* ######################################################################### */
568
shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
572
LONGLONG a[]; array to shuffle
573
int n; number of elements to shuffle
574
int n2; second dimension
575
LONGLONG tmp[]; scratch storage
579
LONGLONG *p1, *p2, *pt;
582
* copy odd elements to tmp
586
for (i=1; i < n; i += 2) {
592
* compress even elements into first half of A
596
for (i=2; i<n; i += 2) {
602
* put odd elements into 2nd half
605
for (i = 1; i<n; i += 2) {
611
/* ######################################################################### */
612
/* ######################################################################### */
613
/* Copyright (c) 1993 Association of Universities for Research
614
* in Astronomy. All rights reserved. Produced under National
615
* Aeronautics and Space Administration Contract No. NAS5-26555.
617
/* digitize.c digitize H-transform
619
* Programmer: R. White Date: 11 March 1991
622
/* ######################################################################### */
624
digitize(int a[], int nx, int ny, int scale)
629
* round to multiple of scale
631
if (scale <= 1) return;
633
for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale;
636
/* ######################################################################### */
638
digitize64(LONGLONG a[], int nx, int ny, int scale)
640
LONGLONG d, *p, scale64;
643
* round to multiple of scale
645
if (scale <= 1) return;
647
scale64 = scale; /* use a 64-bit int for efficiency in the big loop */
649
for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale64;
651
/* ######################################################################### */
652
/* ######################################################################### */
653
/* Copyright (c) 1993 Association of Universities for Research
654
* in Astronomy. All rights reserved. Produced under National
655
* Aeronautics and Space Administration Contract No. NAS5-26555.
657
/* encode.c encode H-transform and write to outfile
659
* Programmer: R. White Date: 2 February 1994
662
static char code_magic[2] = { (char)0xDD, (char)0x99 };
665
/* ######################################################################### */
666
static int encode(char *outfile, long *nlength, int a[], int nx, int ny, int scale)
669
/* FILE *outfile; - change outfile to a char array */
671
long * nlength returned length (in bytes) of the encoded array)
672
int a[]; input H-transform array (nx,ny)
673
int nx,ny; size of H-transform array
674
int scale; scale factor for digitization
676
int nel, nx2, ny2, i, j, k, q, vmax[3], nsign, bits_to_go;
677
unsigned char nbitplanes[3];
678
unsigned char *signbits;
681
noutchar = 0; /* initialize the number of compressed bytes that have been written */
686
qwrite(outfile, code_magic, sizeof(code_magic));
687
writeint(outfile, nx); /* size of image */
688
writeint(outfile, ny);
689
writeint(outfile, scale); /* scale factor for digitization */
691
* write first value of A (sum of all pixels -- the only value
692
* which does not compress well)
694
writelonglong(outfile, (LONGLONG) a[0]);
698
* allocate array for sign bits and save values, 8 per byte
700
signbits = (unsigned char *) malloc((nel+7)/8);
701
if (signbits == (unsigned char *) NULL) {
702
_pyfits_ffpmsg("encode: insufficient memory");
703
return(DATA_COMPRESSION_ERR);
708
for (i=0; i<nel; i++) {
711
* positive element, put zero at end of buffer
713
signbits[nsign] <<= 1;
715
} else if (a[i] < 0) {
717
* negative element, shift in a one
719
signbits[nsign] <<= 1;
720
signbits[nsign] |= 1;
723
* replace a by absolute value
727
if (bits_to_go == 0) {
729
* filled up this byte, go to the next one
736
if (bits_to_go != 8) {
738
* some bits in last element
739
* move bits in last byte to bottom and increment nsign
741
signbits[nsign] <<= bits_to_go;
745
* calculate number of bit planes for 3 quadrants
747
* quadrant 0=bottom left, 1=bottom right or top left, 2=top right,
749
for (q=0; q<3; q++) {
753
* get maximum absolute value in each quadrant
757
j=0; /* column counter */
758
k=0; /* row counter */
759
for (i=0; i<nel; i++) {
760
q = (j>=ny2) + (k>=nx2);
761
if (vmax[q] < a[i]) vmax[q] = a[i];
768
* now calculate number of bits for each quadrant
771
/* this is a more efficient way to do this, */
774
for (q = 0; q < 3; q++) {
775
for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ;
780
for (q = 0; q < 3; q++) {
781
nbitplanes[q] = (int) (log((float) (vmax[q]+1))/log(2.0)+0.5);
782
if ( (vmax[q]+1) > (1<<nbitplanes[q]) ) {
791
if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
793
_pyfits_ffpmsg("encode: output buffer too small");
794
return(DATA_COMPRESSION_ERR);
800
stat = doencode(outfile, a, nx, ny, nbitplanes);
807
if ( 0 == qwrite(outfile, (char *) signbits, nsign)) {
810
_pyfits_ffpmsg("encode: output buffer too small");
811
return(DATA_COMPRESSION_ERR);
818
if (noutchar >= noutmax) {
819
_pyfits_ffpmsg("encode: output buffer too small");
820
return(DATA_COMPRESSION_ERR);
825
/* ######################################################################### */
826
static int encode64(char *outfile, long *nlength, LONGLONG a[], int nx, int ny, int scale)
829
/* FILE *outfile; - change outfile to a char array */
831
long * nlength returned length (in bytes) of the encoded array)
832
LONGLONG a[]; input H-transform array (nx,ny)
833
int nx,ny; size of H-transform array
834
int scale; scale factor for digitization
836
int nel, nx2, ny2, i, j, k, q, nsign, bits_to_go;
838
unsigned char nbitplanes[3];
839
unsigned char *signbits;
842
noutchar = 0; /* initialize the number of compressed bytes that have been written */
847
qwrite(outfile, code_magic, sizeof(code_magic));
848
writeint(outfile, nx); /* size of image */
849
writeint(outfile, ny);
850
writeint(outfile, scale); /* scale factor for digitization */
852
* write first value of A (sum of all pixels -- the only value
853
* which does not compress well)
855
writelonglong(outfile, a[0]);
859
* allocate array for sign bits and save values, 8 per byte
861
signbits = (unsigned char *) malloc((nel+7)/8);
862
if (signbits == (unsigned char *) NULL) {
863
_pyfits_ffpmsg("encode64: insufficient memory");
864
return(DATA_COMPRESSION_ERR);
869
for (i=0; i<nel; i++) {
872
* positive element, put zero at end of buffer
874
signbits[nsign] <<= 1;
876
} else if (a[i] < 0) {
878
* negative element, shift in a one
880
signbits[nsign] <<= 1;
881
signbits[nsign] |= 1;
884
* replace a by absolute value
888
if (bits_to_go == 0) {
890
* filled up this byte, go to the next one
897
if (bits_to_go != 8) {
899
* some bits in last element
900
* move bits in last byte to bottom and increment nsign
902
signbits[nsign] <<= bits_to_go;
906
* calculate number of bit planes for 3 quadrants
908
* quadrant 0=bottom left, 1=bottom right or top left, 2=top right,
910
for (q=0; q<3; q++) {
914
* get maximum absolute value in each quadrant
918
j=0; /* column counter */
919
k=0; /* row counter */
920
for (i=0; i<nel; i++) {
921
q = (j>=ny2) + (k>=nx2);
922
if (vmax[q] < a[i]) vmax[q] = a[i];
929
* now calculate number of bits for each quadrant
932
/* this is a more efficient way to do this, */
935
for (q = 0; q < 3; q++) {
936
for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ;
941
for (q = 0; q < 3; q++) {
942
nbitplanes[q] = log((float) (vmax[q]+1))/log(2.0)+0.5;
943
if ( (vmax[q]+1) > (((LONGLONG) 1)<<nbitplanes[q]) ) {
953
if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
955
_pyfits_ffpmsg("encode: output buffer too small");
956
return(DATA_COMPRESSION_ERR);
962
stat = doencode64(outfile, a, nx, ny, nbitplanes);
969
if ( 0 == qwrite(outfile, (char *) signbits, nsign)) {
972
_pyfits_ffpmsg("encode: output buffer too small");
973
return(DATA_COMPRESSION_ERR);
980
if (noutchar >= noutmax) {
981
_pyfits_ffpmsg("encode64: output buffer too small");
982
return(DATA_COMPRESSION_ERR);
987
/* ######################################################################### */
988
/* ######################################################################### */
989
/* Copyright (c) 1993 Association of Universities for Research
990
* in Astronomy. All rights reserved. Produced under National
991
* Aeronautics and Space Administration Contract No. NAS5-26555.
993
/* qwrite.c Write binary data
995
* Programmer: R. White Date: 11 March 1991
998
/* ######################################################################### */
1000
writeint(char *outfile, int a)
1005
/* Write integer A one byte at a time to outfile.
1007
* This is portable from Vax to Sun since it eliminates the
1008
* need for byte-swapping.
1010
for (i=3; i>=0; i--) {
1011
b[i] = a & 0x000000ff;
1014
for (i=0; i<4; i++) qwrite(outfile, (char *) &b[i],1);
1017
/* ######################################################################### */
1019
writelonglong(char *outfile, LONGLONG a)
1024
/* Write integer A one byte at a time to outfile.
1026
* This is portable from Vax to Sun since it eliminates the
1027
* need for byte-swapping.
1029
for (i=7; i>=0; i--) {
1030
b[i] = (unsigned char) (a & 0x000000ff);
1033
for (i=0; i<8; i++) qwrite(outfile, (char *) &b[i],1);
1035
/* ######################################################################### */
1037
qwrite(char *file, char buffer[], int n)
1040
* write n bytes from buffer into file
1041
* returns number of bytes read (=n) if successful, <=0 if not
1044
if (noutchar + n > noutmax) return(0); /* buffer overflow */
1046
memcpy(&file[noutchar], buffer, n);
1051
/* ######################################################################### */
1052
/* ######################################################################### */
1053
/* Copyright (c) 1993 Association of Universities for Research
1054
* in Astronomy. All rights reserved. Produced under National
1055
* Aeronautics and Space Administration Contract No. NAS5-26555.
1057
/* doencode.c Encode 2-D array and write stream of characters on outfile
1059
* This version assumes that A is positive.
1061
* Programmer: R. White Date: 7 May 1991
1064
/* ######################################################################### */
1066
doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3])
1068
/* char *outfile; output data stream
1069
int a[]; Array of values to encode
1070
int nx,ny; Array dimensions [nx][ny]
1071
unsigned char nbitplanes[3]; Number of bit planes in quadrants
1079
* Initialize bit output
1081
start_outputing_bits();
1083
* write out the bit planes for each quadrant
1085
stat = qtree_encode(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]);
1088
stat = qtree_encode(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]);
1091
stat = qtree_encode(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]);
1094
stat = qtree_encode(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
1096
* Add zero as an EOF symbol
1098
output_nybble(outfile, 0);
1099
done_outputing_bits(outfile);
1103
/* ######################################################################### */
1105
doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3])
1107
/* char *outfile; output data stream
1108
LONGLONG a[]; Array of values to encode
1109
int nx,ny; Array dimensions [nx][ny]
1110
unsigned char nbitplanes[3]; Number of bit planes in quadrants
1118
* Initialize bit output
1120
start_outputing_bits();
1122
* write out the bit planes for each quadrant
1124
stat = qtree_encode64(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]);
1127
stat = qtree_encode64(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]);
1130
stat = qtree_encode64(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]);
1133
stat = qtree_encode64(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
1135
* Add zero as an EOF symbol
1137
output_nybble(outfile, 0);
1138
done_outputing_bits(outfile);
1142
/* ######################################################################### */
1143
/* ######################################################################### */
1144
/* Copyright (c) 1993 Association of Universities for Research
1145
* in Astronomy. All rights reserved. Produced under National
1146
* Aeronautics and Space Administration Contract No. NAS5-26555.
1148
/* BIT OUTPUT ROUTINES */
1151
static LONGLONG bitcount;
1153
/* THE BIT BUFFER */
1155
static int buffer2; /* Bits buffered for output */
1156
static int bits_to_go2; /* Number of bits free in buffer */
1159
/* ######################################################################### */
1160
/* INITIALIZE FOR BIT OUTPUT */
1163
start_outputing_bits(void)
1165
buffer2 = 0; /* Buffer is empty to start */
1166
bits_to_go2 = 8; /* with */
1170
/* ######################################################################### */
1171
/* OUTPUT N BITS (N must be <= 8) */
1174
output_nbits(char *outfile, int bits, int n)
1176
/* AND mask for the right-most n bits */
1177
static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255};
1179
* insert bits at end of buffer
1182
/* buffer2 |= ( bits & ((1<<n)-1) ); */
1183
buffer2 |= ( bits & (*(mask+n)) );
1185
if (bits_to_go2 <= 0) {
1187
* buffer2 full, put out top 8 bits
1190
outfile[noutchar] = ((buffer2>>(-bits_to_go2)) & 0xff);
1192
if (noutchar < noutmax) noutchar++;
1198
/* ######################################################################### */
1199
/* OUTPUT a 4 bit nybble */
1201
output_nybble(char *outfile, int bits)
1204
* insert 4 bits at end of buffer
1206
buffer2 = (buffer2<<4) | ( bits & 15 );
1208
if (bits_to_go2 <= 0) {
1210
* buffer2 full, put out top 8 bits
1213
outfile[noutchar] = ((buffer2>>(-bits_to_go2)) & 0xff);
1215
if (noutchar < noutmax) noutchar++;
1221
/* ############################################################################ */
1222
/* OUTPUT array of 4 BITS */
1224
static void output_nnybble(char *outfile, int n, unsigned char array[])
1226
/* pack the 4 lower bits in each element of the array into the outfile array */
1228
int ii, jj, kk = 0, shift;
1231
output_nybble(outfile, (int) array[0]);
1234
/* forcing byte alignment doesn;t help, and even makes it go slightly slower
1235
if (bits_to_go2 != 8)
1236
output_nbits(outfile, kk, bits_to_go2);
1238
if (bits_to_go2 <= 4)
1240
/* just room for 1 nybble; write it out separately */
1241
output_nybble(outfile, array[0]);
1242
kk++; /* index to next array element */
1244
if (n == 2) /* only 1 more nybble to write out */
1246
output_nybble(outfile, (int) array[1]);
1252
/* bits_to_go2 is now in the range 5 - 8 */
1253
shift = 8 - bits_to_go2;
1255
/* now write out pairs of nybbles; this does not affect value of bits_to_go2 */
1258
if (bits_to_go2 == 8) {
1259
/* special case if nybbles are aligned on byte boundary */
1260
/* this actually seems to make very little differnece in speed */
1262
for (ii = 0; ii < jj; ii++)
1264
outfile[noutchar] = ((array[kk] & 15)<<4) | (array[kk+1] & 15);
1269
for (ii = 0; ii < jj; ii++)
1271
buffer2 = (buffer2<<8) | ((array[kk] & 15)<<4) | (array[kk+1] & 15);
1275
buffer2 full, put out top 8 bits
1278
outfile[noutchar] = ((buffer2>>shift) & 0xff);
1283
bitcount += (8 * (ii - 1));
1285
/* write out last odd nybble, if present */
1286
if (kk != n) output_nybble(outfile, (int) array[n - 1]);
1292
/* ######################################################################### */
1293
/* FLUSH OUT THE LAST BITS */
1296
done_outputing_bits(char *outfile)
1298
if(bits_to_go2 < 8) {
1299
/* putc(buffer2<<bits_to_go2,outfile); */
1301
outfile[noutchar] = (buffer2<<bits_to_go2);
1302
if (noutchar < noutmax) noutchar++;
1304
/* count the garbage bits too */
1305
bitcount += bits_to_go2;
1308
/* ######################################################################### */
1309
/* ######################################################################### */
1310
/* Copyright (c) 1993 Association of Universities for Research
1311
* in Astronomy. All rights reserved. Produced under National
1312
* Aeronautics and Space Administration Contract No. NAS5-26555.
1314
/* qtree_encode.c Encode values in quadrant of 2-D array using binary
1315
* quadtree coding for each bit plane. Assumes array is
1318
* Programmer: R. White Date: 15 May 1991
1322
* Huffman code values and number of bits in each code
1324
static int code[16] =
1326
0x3e, 0x00, 0x01, 0x08, 0x02, 0x09, 0x1a, 0x1b,
1327
0x03, 0x1c, 0x0a, 0x1d, 0x0b, 0x1e, 0x3f, 0x0c
1329
static int ncode[16] =
1331
6, 3, 3, 4, 3, 4, 5, 5,
1332
3, 5, 4, 5, 4, 5, 6, 4
1336
* variables for bit output to buffer when Huffman coding
1338
static int bitbuffer, bits_to_go3;
1341
* macros to write out 4-bit nybble, Huffman code for this value
1345
/* ######################################################################### */
1347
qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes)
1352
int n; physical dimension of row in a
1353
int nqx; length of row
1354
int nqy; length of column (<=n)
1355
int nbitplanes; number of bit planes to output
1358
int log2n, i, k, bit, b, bmax, nqmax, nqx2, nqy2, nx, ny;
1359
unsigned char *scratch, *buffer;
1362
* log2n is log2 of max(nqx,nqy) rounded up to next power of 2
1364
nqmax = (nqx>nqy) ? nqx : nqy;
1365
log2n = (int) (log((float) nqmax)/log(2.0)+0.5);
1366
if (nqmax > (1<<log2n)) {
1370
* initialize buffer point, max buffer size
1374
bmax = (nqx2*nqy2+1)/2;
1376
* We're indexing A as a 2-D array with dimensions (nqx,nqy).
1377
* Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
1378
* Buffer is used to store string of codes for output.
1380
scratch = (unsigned char *) malloc(2*bmax);
1381
buffer = (unsigned char *) malloc(bmax);
1382
if ((scratch == (unsigned char *) NULL) ||
1383
(buffer == (unsigned char *) NULL)) {
1384
_pyfits_ffpmsg("qtree_encode: insufficient memory");
1385
return(DATA_COMPRESSION_ERR);
1388
* now encode each bit plane, starting with the top
1390
for (bit=nbitplanes-1; bit >= 0; bit--) {
1392
* initial bit buffer
1398
* on first pass copy A to scratch array
1400
qtree_onebit(a,n,nqx,nqy,scratch,bit);
1404
* copy non-zero values to output buffer, which will be written
1407
if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
1409
* quadtree is expanding data,
1410
* change warning code and just fill buffer with bit-map
1412
write_bdirect(outfile,a,n,nqx,nqy,scratch,bit);
1416
* do log2n reductions
1418
for (k = 1; k<log2n; k++) {
1419
qtree_reduce(scratch,ny,nx,ny,scratch);
1422
if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
1423
write_bdirect(outfile,a,n,nqx,nqy,scratch,bit);
1428
* OK, we've got the code in buffer
1429
* Write quadtree warning code, then write buffer in reverse order
1431
output_nybble(outfile,0xF);
1433
if (bits_to_go3>0) {
1435
* put out the last few bits
1437
output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
1441
* have to write a zero nybble if there are no 1's in array
1443
output_huffman(outfile,0);
1446
if (bits_to_go3>0) {
1448
* put out the last few bits
1450
output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
1453
for (i=b-1; i>=0; i--) {
1454
output_nbits(outfile,buffer[i],8);
1463
/* ######################################################################### */
1465
qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes)
1470
int n; physical dimension of row in a
1471
int nqx; length of row
1472
int nqy; length of column (<=n)
1473
int nbitplanes; number of bit planes to output
1476
int log2n, i, k, bit, b, nqmax, nqx2, nqy2, nx, ny;
1477
int bmax; /* this potentially needs to be made a 64-bit int to support large arrays */
1478
unsigned char *scratch, *buffer;
1481
* log2n is log2 of max(nqx,nqy) rounded up to next power of 2
1483
nqmax = (nqx>nqy) ? nqx : nqy;
1484
log2n = (int) (log((float) nqmax)/log(2.0)+0.5);
1485
if (nqmax > (1<<log2n)) {
1489
* initialize buffer point, max buffer size
1493
bmax = (( nqx2)* ( nqy2)+1)/2;
1495
* We're indexing A as a 2-D array with dimensions (nqx,nqy).
1496
* Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
1497
* Buffer is used to store string of codes for output.
1499
scratch = (unsigned char *) malloc(2*bmax);
1500
buffer = (unsigned char *) malloc(bmax);
1501
if ((scratch == (unsigned char *) NULL) ||
1502
(buffer == (unsigned char *) NULL)) {
1503
_pyfits_ffpmsg("qtree_encode64: insufficient memory");
1504
return(DATA_COMPRESSION_ERR);
1507
* now encode each bit plane, starting with the top
1509
for (bit=nbitplanes-1; bit >= 0; bit--) {
1511
* initial bit buffer
1517
* on first pass copy A to scratch array
1519
qtree_onebit64(a,n,nqx,nqy,scratch,bit);
1523
* copy non-zero values to output buffer, which will be written
1526
if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
1528
* quadtree is expanding data,
1529
* change warning code and just fill buffer with bit-map
1531
write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit);
1535
* do log2n reductions
1537
for (k = 1; k<log2n; k++) {
1538
qtree_reduce(scratch,ny,nx,ny,scratch);
1541
if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
1542
write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit);
1547
* OK, we've got the code in buffer
1548
* Write quadtree warning code, then write buffer in reverse order
1550
output_nybble(outfile,0xF);
1552
if (bits_to_go3>0) {
1554
* put out the last few bits
1556
output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
1560
* have to write a zero nybble if there are no 1's in array
1562
output_huffman(outfile,0);
1565
if (bits_to_go3>0) {
1567
* put out the last few bits
1569
output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
1572
for (i=b-1; i>=0; i--) {
1573
output_nbits(outfile,buffer[i],8);
1583
/* ######################################################################### */
1585
* copy non-zero codes from array to buffer
1588
bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax)
1592
for (i = 0; i < n; i++) {
1595
* add Huffman code for a[i] to buffer
1597
bitbuffer |= code[a[i]] << bits_to_go3;
1598
bits_to_go3 += ncode[a[i]];
1599
if (bits_to_go3 >= 8) {
1600
buffer[*b] = bitbuffer & 0xFF;
1603
* return warning code if we fill buffer
1605
if (*b >= bmax) return(1);
1614
/* ######################################################################### */
1616
* Do first quadtree reduction step on bit BIT of array A.
1617
* Results put into B.
1621
qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit)
1628
* use selected bit to get amount to shift
1634
k = 0; /* k is index of b[i/2,j/2] */
1635
for (i = 0; i<nx-1; i += 2) {
1636
s00 = n*i; /* s00 is index of a[i,j] */
1637
s10 = s00+n; /* s10 is index of a[i+1,j] */
1638
for (j = 0; j<ny-1; j += 2) {
1639
b[k] = ( ( a[s10+1] & b0)
1640
| ((a[s10 ]<<1) & b1)
1641
| ((a[s00+1]<<2) & b2)
1642
| ((a[s00 ]<<3) & b3) ) >> bit;
1650
* row size is odd, do last element in row
1651
* s00+1,s10+1 are off edge
1653
b[k] = ( ((a[s10 ]<<1) & b1)
1654
| ((a[s00 ]<<3) & b3) ) >> bit;
1660
* column size is odd, do last row
1661
* s10,s10+1 are off edge
1664
for (j = 0; j<ny-1; j += 2) {
1665
b[k] = ( ((a[s00+1]<<2) & b2)
1666
| ((a[s00 ]<<3) & b3) ) >> bit;
1672
* both row and column size are odd, do corner element
1673
* s00+1, s10, s10+1 are off edge
1675
b[k] = ( ((a[s00 ]<<3) & b3) ) >> bit;
1680
/* ######################################################################### */
1682
* Do first quadtree reduction step on bit BIT of array A.
1683
* Results put into B.
1687
qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit)
1690
LONGLONG b0, b1, b2, b3;
1694
* use selected bit to get amount to shift
1696
b0 = ((LONGLONG) 1)<<bit;
1700
k = 0; /* k is index of b[i/2,j/2] */
1701
for (i = 0; i<nx-1; i += 2) {
1702
s00 = n*i; /* s00 is index of a[i,j] */
1703
s10 = s00+n; /* s10 is index of a[i+1,j] */
1704
for (j = 0; j<ny-1; j += 2) {
1705
b[k] = (unsigned char) (( ( a[s10+1] & b0)
1706
| ((a[s10 ]<<1) & b1)
1707
| ((a[s00+1]<<2) & b2)
1708
| ((a[s00 ]<<3) & b3) ) >> bit);
1715
* row size is odd, do last element in row
1716
* s00+1,s10+1 are off edge
1718
b[k] = (unsigned char) (( ((a[s10 ]<<1) & b1)
1719
| ((a[s00 ]<<3) & b3) ) >> bit);
1725
* column size is odd, do last row
1726
* s10,s10+1 are off edge
1729
for (j = 0; j<ny-1; j += 2) {
1730
b[k] = (unsigned char) (( ((a[s00+1]<<2) & b2)
1731
| ((a[s00 ]<<3) & b3) ) >> bit);
1737
* both row and column size are odd, do corner element
1738
* s00+1, s10, s10+1 are off edge
1740
b[k] = (unsigned char) (( ((a[s00 ]<<3) & b3) ) >> bit);
1746
/* ######################################################################### */
1748
* do one quadtree reduction step on array a
1749
* results put into b (which may be the same as a)
1752
qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[])
1757
k = 0; /* k is index of b[i/2,j/2] */
1758
for (i = 0; i<nx-1; i += 2) {
1759
s00 = n*i; /* s00 is index of a[i,j] */
1760
s10 = s00+n; /* s10 is index of a[i+1,j] */
1761
for (j = 0; j<ny-1; j += 2) {
1762
b[k] = (a[s10+1] != 0)
1763
| ( (a[s10 ] != 0) << 1)
1764
| ( (a[s00+1] != 0) << 2)
1765
| ( (a[s00 ] != 0) << 3);
1772
* row size is odd, do last element in row
1773
* s00+1,s10+1 are off edge
1775
b[k] = ( (a[s10 ] != 0) << 1)
1776
| ( (a[s00 ] != 0) << 3);
1782
* column size is odd, do last row
1783
* s10,s10+1 are off edge
1786
for (j = 0; j<ny-1; j += 2) {
1787
b[k] = ( (a[s00+1] != 0) << 2)
1788
| ( (a[s00 ] != 0) << 3);
1794
* both row and column size are odd, do corner element
1795
* s00+1, s10, s10+1 are off edge
1797
b[k] = ( (a[s00 ] != 0) << 3);
1803
/* ######################################################################### */
1805
write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
1809
* Write the direct bitmap warning code
1811
output_nybble(outfile,0x0);
1813
* Copy A to scratch array (again!), packing 4 bits/nybble
1815
qtree_onebit(a,n,nqx,nqy,scratch,bit);
1821
for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
1822
output_nybble(outfile,scratch[i]);
1825
output_nnybble(outfile, ((nqx+1)/2) * ((nqy+1)/2), scratch);
1828
/* ######################################################################### */
1830
write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
1834
* Write the direct bitmap warning code
1836
output_nybble(outfile,0x0);
1838
* Copy A to scratch array (again!), packing 4 bits/nybble
1840
qtree_onebit64(a,n,nqx,nqy,scratch,bit);
1846
for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
1847
output_nybble(outfile,scratch[i]);
1850
output_nnybble(outfile, ((nqx+1)/2) * ((nqy+1)/2), scratch);