forked from Starlink/cfitsio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
imcopy.c
233 lines (200 loc) · 9.15 KB
/
imcopy.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "fitsio.h"
int main(int argc, char *argv[])
{
fitsfile *infptr, *outfptr; /* FITS file pointers defined in fitsio.h */
int status = 0, tstatus, ii = 1, iteration = 0, single = 0, hdupos;
int hdutype, bitpix, bytepix, naxis = 0, nkeys, datatype = 0, anynul;
long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
long first, totpix = 0, npix;
double *array, bscale = 1.0, bzero = 0.0, nulval = 0.;
char card[81];
if (argc != 3)
{
printf("\n");
printf("Usage: imcopy inputImage outputImage[compress]\n");
printf("\n");
printf("Copy an input image to an output image, optionally compressing\n");
printf("or uncompressing the image in the process. If the [compress]\n");
printf("qualifier is appended to the output file name then the input image\n");
printf("will be compressed using the tile-compressed format. In this format,\n");
printf("the image is divided into rectangular tiles and each tile of pixels\n");
printf("is compressed and stored in a variable-length row of a binary table.\n");
printf("If the [compress] qualifier is omitted, and the input image is\n");
printf("in tile-compressed format, then the output image will be uncompressed.\n");
printf("\n");
printf("If an extension name or number is appended to the input file name, \n");
printf("enclosed in square brackets, then only that single extension will be\n");
printf("copied to the output file. Otherwise, every extension in the input file\n");
printf("will be processed in turn and copied to the output file.\n");
printf("\n");
printf("Examples:\n");
printf("\n");
printf("1) imcopy image.fit 'cimage.fit[compress]'\n");
printf("\n");
printf(" This compresses the input image using the default parameters, i.e.,\n");
printf(" using the Rice compression algorithm and using row by row tiles.\n");
printf("\n");
printf("2) imcopy cimage.fit image2.fit\n");
printf("\n");
printf(" This uncompresses the image created in the first example.\n");
printf(" image2.fit should be identical to image.fit if the image\n");
printf(" has an integer datatype. There will be small differences\n");
printf(" in the pixel values if it is a floating point image.\n");
printf("\n");
printf("3) imcopy image.fit 'cimage.fit[compress GZIP 100,100;q 16]'\n");
printf("\n");
printf(" This compresses the input image using the following parameters:\n");
printf(" GZIP compression algorithm;\n");
printf(" 100 X 100 pixel compression tiles;\n");
printf(" quantization level = 16 (only used with floating point images)\n");
printf("\n");
printf("The full syntax of the compression qualifier is:\n");
printf(" [compress ALGORITHM TDIM1,TDIM2,...; q QLEVEL s SCALE]\n");
printf("where the allowed ALGORITHM values are:\n");
printf(" Rice, HCOMPRESS, HSCOMPRESS, GZIP, or PLIO. \n");
printf(" (HSCOMPRESS is a variant of HCOMPRESS in which a small\n");
printf(" amount of smoothing is applied to the uncompressed image\n");
printf(" to help suppress blocky compression artifacts in the image\n");
printf(" when using large values for the 'scale' parameter).\n");
printf("TDIMn is the size of the compression tile in each dimension,\n");
printf("\n");
printf("QLEVEL specifies the quantization level when converting a floating\n");
printf("point image into integers, prior to compressing the image. The\n");
printf("default value = 16, which means the image will be quantized into\n");
printf("integer levels that are spaced at intervals of sigma/16., where \n");
printf("sigma is the estimated noise level in background areas of the image.\n");
printf("If QLEVEL is negative, this means use the absolute value for the\n");
printf("quantization spacing (e.g. 'q -0.005' means quantize the floating\n");
printf("point image such that the scaled integers represent steps of 0.005\n");
printf("in the original image).\n");
printf("\n");
printf("SCALE is the integer scale factor that only applies to the HCOMPRESS\n");
printf("algorithm. The default value SCALE = 0 forces the image to be\n");
printf("losslessly compressed; Greater amounts of lossy compression (resulting\n");
printf("in smaller compressed files) can be specified with larger SCALE values.\n");
printf("\n");
printf("\n");
printf("Note that it may be necessary to enclose the file names\n");
printf("in single quote characters on the Unix command line.\n");
return(0);
}
/* Open the input file and create output file */
fits_open_file(&infptr, argv[1], READONLY, &status);
fits_create_file(&outfptr, argv[2], &status);
if (status != 0) {
fits_report_error(stderr, status);
return(status);
}
fits_get_hdu_num(infptr, &hdupos); /* Get the current HDU position */
/* Copy only a single HDU if a specific extension was given */
if (hdupos != 1 || strchr(argv[1], '[')) single = 1;
for (; !status; hdupos++) /* Main loop through each extension */
{
fits_get_hdu_type(infptr, &hdutype, &status);
if (hdutype == IMAGE_HDU) {
/* get image dimensions and total number of pixels in image */
for (ii = 0; ii < 9; ii++)
naxes[ii] = 1;
fits_get_img_param(infptr, 9, &bitpix, &naxis, naxes, &status);
totpix = naxes[0] * naxes[1] * naxes[2] * naxes[3] * naxes[4]
* naxes[5] * naxes[6] * naxes[7] * naxes[8];
}
if (hdutype != IMAGE_HDU || naxis == 0 || totpix == 0) {
/* just copy tables and null images */
fits_copy_hdu(infptr, outfptr, 0, &status);
} else {
/* Explicitly create new image, to support compression */
fits_create_img(outfptr, bitpix, naxis, naxes, &status);
if (status) {
fits_report_error(stderr, status);
return(status);
}
if (fits_is_compressed_image(outfptr, &status)) {
/* write default EXTNAME keyword if it doesn't already exist */
tstatus = 0;
fits_read_card(infptr, "EXTNAME", card, &tstatus);
if (tstatus) {
strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE' / name of this binary table extension");
fits_write_record(outfptr, card, &status);
}
}
/* copy all the user keywords (not the structural keywords) */
fits_get_hdrspace(infptr, &nkeys, NULL, &status);
for (ii = 1; ii <= nkeys; ii++) {
fits_read_record(infptr, ii, card, &status);
if (fits_get_keyclass(card) > TYP_CMPRS_KEY)
fits_write_record(outfptr, card, &status);
}
/* delete default EXTNAME keyword if it exists */
/*
if (!fits_is_compressed_image(outfptr, &status)) {
tstatus = 0;
fits_read_key(outfptr, TSTRING, "EXTNAME", card, NULL, &tstatus);
if (!tstatus) {
if (strcmp(card, "COMPRESSED_IMAGE") == 0)
fits_delete_key(outfptr, "EXTNAME", &status);
}
}
*/
switch(bitpix) {
case BYTE_IMG:
datatype = TBYTE;
break;
case SHORT_IMG:
datatype = TSHORT;
break;
case LONG_IMG:
datatype = TINT;
break;
case FLOAT_IMG:
datatype = TFLOAT;
break;
case DOUBLE_IMG:
datatype = TDOUBLE;
break;
}
bytepix = abs(bitpix) / 8;
npix = totpix;
iteration = 0;
/* try to allocate memory for the entire image */
/* use double type to force memory alignment */
array = (double *) calloc(npix, bytepix);
/* if allocation failed, divide size by 2 and try again */
while (!array && iteration < 10) {
iteration++;
npix = npix / 2;
array = (double *) calloc(npix, bytepix);
}
if (!array) {
printf("Memory allocation error\n");
return(0);
}
/* turn off any scaling so that we copy the raw pixel values */
fits_set_bscale(infptr, bscale, bzero, &status);
fits_set_bscale(outfptr, bscale, bzero, &status);
first = 1;
while (totpix > 0 && !status)
{
/* read all or part of image then write it back to the output file */
fits_read_img(infptr, datatype, first, npix,
&nulval, array, &anynul, &status);
fits_write_img(outfptr, datatype, first, npix, array, &status);
totpix = totpix - npix;
first = first + npix;
}
free(array);
}
if (single) break; /* quit if only copying a single HDU */
fits_movrel_hdu(infptr, 1, NULL, &status); /* try to move to next HDU */
}
if (status == END_OF_FILE) status = 0; /* Reset after normal error */
fits_close_file(outfptr, &status);
fits_close_file(infptr, &status);
/* if error occurred, print out error message */
if (status)
fits_report_error(stderr, status);
return(status);
}