Instrument Neutral Distributed Interface INDI  2.0.2
fpack.c
Go to the documentation of this file.
1 /* FPACK
2  * R. Seaman, NOAO, with a few enhancements by W. Pence, HEASARC
3  *
4  * Calls fits_img_compress in the CFITSIO library by W. Pence, HEASARC
5  */
6 
7 #include <ctype.h>
8 /* #include <signal.h> */
9 #include "fitsio.h"
10 #include "fpack.h"
11 
12 /* ==================================================================
13 int main(int argc, char *argv[])
14 {
15  fpstate fpvar;
16 
17  if (argc <= 1) { fp_usage (); fp_hint (); exit (-1); }
18 
19  fp_init (&fpvar);
20  fp_get_param (argc, argv, &fpvar);
21 
22  if (fpvar.listonly) {
23  fp_list (argc, argv, fpvar);
24 
25  } else {
26  fp_preflight (argc, argv, FPACK, &fpvar);
27  fp_loop (argc, argv, FPACK, fpvar);
28  }
29 
30  exit (0);
31 }
32 ================================================================== */
33 int _fp_msg (const char *msg)
34 {
35  printf ("%s", msg);
36  return(0);
37 }
38 
39 int fp_get_param (int argc, char *argv[], fpstate *fpptr)
40 {
41  int gottype=0, gottile=0, wholetile=0, iarg, len, ndim, ii, doffset;
42  char tmp[SZ_STR], tile[SZ_STR];
43 
44  if (fpptr->initialized != FP_INIT_MAGIC) {
45  fp_msg ("Error: internal initialization error\n"); exit (-1);
46  }
47 
48  tile[0] = 0;
49 
50  /* flags must come first and be separately specified
51  */
52  for (iarg = 1; iarg < argc; iarg++) {
53  if ((argv[iarg][0] == '-' && strlen (argv[iarg]) == 2) ||
54  !strncmp(argv[iarg], "-q", 2) || !strncmp(argv[iarg], "-qz", 3) ||
55  !strncmp(argv[iarg], "-g1", 3) || !strncmp(argv[iarg], "-g2", 3) ||
56  !strncmp(argv[iarg], "-i2f", 4) ||
57  !strncmp(argv[iarg], "-n3ratio", 8) || !strncmp(argv[iarg], "-n3min", 6) ||
58  !strncmp(argv[iarg], "-tableonly", 10) || !strncmp(argv[iarg], "-table", 6) )
59  {
60 
61  /* Rice is the default, so -r is superfluous */
62  if ( argv[iarg][1] == 'r') {
63  fpptr->comptype = RICE_1;
64  if (gottype) {
65  fp_msg ("Error: multiple compression flags\n");
66  fp_usage (); exit (-1);
67  } else
68  gottype++;
69 
70  } else if (argv[iarg][1] == 'p') {
71  fpptr->comptype = PLIO_1;
72  if (gottype) {
73  fp_msg ("Error: multiple compression flags\n");
74  fp_usage (); exit (-1);
75  } else
76  gottype++;
77 
78  } else if (argv[iarg][1] == 'g') {
79  /* test for modifiers following the 'g' */
80  if (argv[iarg][2] == '2')
81  fpptr->comptype = GZIP_2;
82  else
83  fpptr->comptype = GZIP_1;
84 
85  if (gottype) {
86  fp_msg ("Error: multiple compression flags\n");
87  fp_usage (); exit (-1);
88  } else
89  gottype++;
90 /*
91  } else if (argv[iarg][1] == 'b') {
92  fpptr->comptype = BZIP2_1;
93  if (gottype) {
94  fp_msg ("Error: multiple compression flags\n");
95  fp_usage (); exit (-1);
96  } else
97  gottype++;
98 */
99  } else if (argv[iarg][1] == 'h') {
100  fpptr->comptype = HCOMPRESS_1;
101  if (gottype) {
102  fp_msg ("Error: multiple compression flags\n");
103  fp_usage (); exit (-1);
104  } else
105  gottype++;
106 
107  } else if (argv[iarg][1] == 'd') {
108  fpptr->comptype = NOCOMPRESS;
109  if (gottype) {
110  fp_msg ("Error: multiple compression flags\n");
111  fp_usage (); exit (-1);
112  } else
113  gottype++;
114 
115  } else if (!strcmp(argv[iarg], "-i2f")) {
116  /* this means convert integer images to float, and then */
117  /* quantize and compress the float image. This lossy */
118  /* compression method may give higher compression than the */
119  /* lossless compression method that is usually applied to */
120  /* integer images. */
121 
122  fpptr->int_to_float = 1;
123 
124  } else if (!strcmp(argv[iarg], "-n3ratio")) {
125  /* this is the minimum ratio between the MAD noise sigma */
126  /* and the q parameter value in the case where the integer */
127  /* image is quantized and compressed like a float image. */
128  if (++iarg >= argc) {
129  fp_usage (); exit (-1);
130  } else {
131  fpptr->n3ratio = (float) atof (argv[iarg]);
132  }
133  } else if (!strcmp(argv[iarg], "-n3min")) {
134  /* this is the minimum MAD noise sigma in the case where the */
135  /* integer image is quantized and compressed like a float image. */
136  if (++iarg >= argc) {
137  fp_usage (); exit (-1);
138  } else {
139  fpptr->n3min = (float) atof (argv[iarg]);
140  }
141  } else if (argv[iarg][1] == 'q') {
142  /* test for modifiers following the 'q' */
143 
144  if (argv[iarg][2] == 'z') {
145  fpptr->dither_method = 2; /* preserve zero pixels */
146 
147  if (argv[iarg][3] == 't') {
148  fpptr->dither_offset = -1; /* dither based on tile checksum */
149 
150  } else if (isdigit(argv[iarg][3])) { /* is a number appended to q? */
151  doffset = atoi(argv[iarg]+3);
152 
153  if (doffset == 0) {
154  fpptr->no_dither = 1; /* don't dither the quantized values */
155  } else if (doffset > 0 && doffset <= 10000) {
156  fpptr->dither_offset = doffset;
157  } else {
158  fp_msg ("Error: invalid q suffix\n");
159  fp_usage (); exit (-1);
160  }
161  }
162  } else {
163  if (argv[iarg][2] == 't') {
164  fpptr->dither_offset = -1; /* dither based on tile checksum */
165 
166  } else if (isdigit(argv[iarg][2])) { /* is a number appended to q? */
167  doffset = atoi(argv[iarg]+2);
168 
169  if (doffset == 0) {
170  fpptr->no_dither = 1; /* don't dither the quantized values */
171  } else if (doffset > 0 && doffset <= 10000) {
172  fpptr->dither_offset = doffset;
173  } else {
174  fp_msg ("Error: invalid q suffix\n");
175  fp_usage (); exit (-1);
176  }
177  }
178  }
179 
180  if (++iarg >= argc) {
181  fp_usage (); exit (-1);
182  } else {
183  fpptr->quantize_level = (float) atof (argv[iarg]);
184  }
185  } else if (argv[iarg][1] == 'n') {
186  if (++iarg >= argc) {
187  fp_usage (); exit (-1);
188  } else {
189  fpptr->rescale_noise = (float) atof (argv[iarg]);
190  }
191  } else if (argv[iarg][1] == 's') {
192  if (++iarg >= argc) {
193  fp_usage (); exit (-1);
194  } else {
195  fpptr->scale = (float) atof (argv[iarg]);
196  }
197  } else if (!strcmp(argv[iarg], "-tableonly")) {
198  fpptr->do_tables = 1;
199  fpptr->do_images = 0;
200  fp_msg ("Note: -tableonly is intended for feasibility studies, not general use.\n");
201 
202  } else if (!strcmp(argv[iarg], "-table")) {
203  fpptr->do_tables = 1;
204  fp_msg ("Note: -table is intended for feasibility studies, not general use.\n");
205 
206  } else if (argv[iarg][1] == 't') {
207  if (gottile) {
208  fp_msg ("Error: multiple tile specifications\n");
209  fp_usage (); exit (-1);
210  } else
211  gottile++;
212 
213  if (++iarg >= argc) {
214  fp_usage (); exit (-1);
215  } else
216  strncpy (tile, argv[iarg], SZ_STR); /* checked below */
217 
218  } else if (argv[iarg][1] == 'v') {
219  fpptr->verbose = 1;
220 
221  } else if (argv[iarg][1] == 'w') {
222  wholetile++;
223  if (gottile) {
224  fp_msg ("Error: multiple tile specifications\n");
225  fp_usage (); exit (-1);
226  } else
227  gottile++;
228 
229  } else if (argv[iarg][1] == 'F') {
230  fpptr->clobber++; /* overwrite existing file */
231 
232  } else if (argv[iarg][1] == 'D') {
233  fpptr->delete_input++;
234 
235  } else if (argv[iarg][1] == 'Y') {
236  fpptr->do_not_prompt++;
237 
238  } else if (argv[iarg][1] == 'S') {
239  fpptr->to_stdout++;
240 
241  } else if (argv[iarg][1] == 'L') {
242  fpptr->listonly++;
243 
244  } else if (argv[iarg][1] == 'C') {
245  fpptr->do_checksums = 0;
246 
247  } else if (argv[iarg][1] == 'T') {
248  fpptr->test_all = 1;
249 
250  } else if (argv[iarg][1] == 'R') {
251  if (++iarg >= argc) {
252  fp_usage (); fp_hint (); exit (-1);
253  } else
254  strncpy (fpptr->outfile, argv[iarg], SZ_STR);
255 
256  } else if (argv[iarg][1] == 'H') {
257  fp_help (); exit (0);
258 
259  } else if (argv[iarg][1] == 'V') {
260  fp_version (); exit (0);
261 
262  } else {
263  fp_msg ("Error: unknown command line flag `");
264  fp_msg (argv[iarg]); fp_msg ("'\n");
265  fp_usage (); fp_hint (); exit (-1);
266  }
267 
268  } else
269  break;
270  }
271 
272  if (fpptr->scale != 0. &&
273  fpptr->comptype != HCOMPRESS_1 && fpptr->test_all != 1) {
274 
275  fp_msg ("Error: `-s' requires `-h or -T'\n"); exit (-1);
276  }
277 
278  if (fpptr->quantize_level == 0) {
279 
280  if ((fpptr->comptype != GZIP_1) && (fpptr->comptype != GZIP_2)) {
281  fp_msg ("Error: `-q 0' only allowed with GZIP\n"); exit (-1);
282  }
283 
284  if (fpptr->int_to_float == 1) {
285  fp_msg ("Error: `-q 0' not allowed with -i2f\n"); exit (-1);
286  }
287  }
288 
289  if (wholetile) {
290  for (ndim=0; ndim < MAX_COMPRESS_DIM; ndim++)
291  fpptr->ntile[ndim] = (long) -1;
292 
293  } else if (gottile) {
294  len = strlen (tile);
295  for (ii=0, ndim=0; ii < len; ) {
296  if (! (isdigit (tile[ii]) || tile[ii] == ',')) {
297  fp_msg ("Error: `-t' requires comma separated tile dims, ");
298  fp_msg ("e.g., `-t 100,100'\n"); exit (-1);
299  }
300 
301  if (tile[ii] == ',') { ii++; continue; }
302 
303  fpptr->ntile[ndim] = atol (&tile[ii]);
304  for ( ; isdigit(tile[ii]); ii++);
305 
306  if (++ndim > MAX_COMPRESS_DIM) {
307  fp_msg ("Error: too many dimensions for `-t', max=");
308  snprintf (tmp, SZ_STR,"%d\n", MAX_COMPRESS_DIM); fp_msg (tmp);
309  exit (-1);
310  }
311  }
312  }
313 
314  if (iarg >= argc) {
315  fp_msg ("Error: no FITS files to compress\n");
316  fp_usage (); exit (-1);
317  } else
318  fpptr->firstfile = iarg;
319 
320  return(0);
321 }
322 
323 /* ================================================================== */
324 int fp_usage (void)
325 {
326 fp_msg ("usage: fpack ");
327 fp_msg (
328 "[-r|-h|-g|-p] [-w|-t <axes>] [-q <level>] [-s <scale>] [-n <noise>] -v <FITS>\n");
329 fp_msg ("more: [-T] [-R] [-F] [-D] [-Y] [-S] [-L] [-C] [-H] [-V] [-i2f]\n");
330 return(0);
331 }
332 
333 /* ================================================================== */
334 int fp_hint (void)
335 { fp_msg (" `fpack -H' for help\n");
336 return(0);
337 }
338 
339 /* ================================================================== */
340 int fp_help (void)
341 {
342 fp_msg ("fpack, a FITS image compression program. Version ");
343 fp_version ();
344 fp_usage ();
345 fp_msg ("\n");
346 fp_msg ("NOTE: the compression parameters specified on the fpack command line may\n");
347 fp_msg ("be over-ridden by compression directive keywords in the header of each HDU\n");
348 fp_msg ("of the input file(s). See the fpack User's Guide for more details\n");
349 fp_msg ("\n");
350 
351 fp_msg ("Flags must be separate and appear before filenames:\n");
352 fp_msg (" -r Rice compression [default], or\n");
353 fp_msg (" -h Hcompress compression, or\n");
354 fp_msg (" -g or -g1 GZIP_1 (per-tile) compression, or\n");
355 fp_msg (" -g2 GZIP_2 (per-tile) compression (with byte shuffling), or\n");
356 /*
357 fp_msg (" -b BZIP2 (per-tile) compression, or\n");
358 */
359 fp_msg (" -p PLIO compression (only for positive 8 or 16-bit integer images).\n");
360 fp_msg (" -d Tile the image without compression (debugging mode).\n");
361 
362 fp_msg (" -w Compress the whole image as a single large tile.\n");
363 fp_msg (" -t <axes> Comma separated list of tile dimensions [default is row by row].\n");
364 
365 fp_msg (" -q <level> Quantized level spacing when converting floating point images to\n");
366 fp_msg (" scaled integers. (+value relative to sigma of background noise;\n");
367 fp_msg (" -value is absolute). Default q value of 4 gives a compression ratio\n");
368 fp_msg (" of about 6 with very high fidelity (only 0.26% increase in noise).\n");
369 fp_msg (" Using q values of 2, or 1 will give compression ratios of\n");
370 fp_msg (" about 8, or 10, respectively (with 1.0% or 4.1% noise increase).\n");
371 fp_msg (" The scaled quantized values are randomly dithered using a seed \n");
372 fp_msg (" value determined from the system clock at run time.\n");
373 fp_msg (" Use -q0 instead of -q to suppress random dithering.\n");
374 fp_msg (" Use -qz instead of -q to not dither zero-valued pixels.\n");
375 fp_msg (" Use -qt or -qzt to compute random dithering seed from first tile checksum.\n");
376 fp_msg (" Use -qN or -qzN, (N in range 1 to 10000) to use a specific dithering seed.\n");
377 fp_msg (" Floating-point images can be losslessly compressed by selecting\n");
378 fp_msg (" the GZIP algorithm and specifying -q 0, but this is slower and often\n");
379 fp_msg (" produces much less compression than the default quantization method.\n");
380 fp_msg (" -i2f Convert integer images to floating point, then quantize and compress\n");
381 fp_msg (" using the specified q level. When used appropriately, this lossy\n");
382 fp_msg (" compression method can give much better compression than the normal\n");
383 fp_msg (" lossless compression methods without significant loss of information.\n");
384 fp_msg (" The -n3ratio and -n3min flags control the minimum noise thresholds;\n");
385 fp_msg (" Images below these thresholds will be losslessly compressed.\n");
386 fp_msg (" -n3ratio Minimum ratio of background noise sigma divided by q. Default = 2.0.\n");
387 fp_msg (" -n3min Minimum background noise sigma. Default = 6. The -i2f flag will be ignored\n");
388 fp_msg (" if the noise level in the image does not exceed both thresholds.\n");
389 fp_msg (" -s <scale> Scale factor for lossy Hcompress [default = 0 = lossless]\n");
390 fp_msg (" (+values relative to RMS noise; -value is absolute)\n");
391 fp_msg (" -n <noise> Rescale scaled-integer images to reduce noise and improve compression.\n");
392 fp_msg (" -v Verbose mode; list each file as it is processed.\n");
393 fp_msg (" -T Show compression algorithm comparison test statistics; files unchanged.\n");
394 fp_msg (" -R <file> Write the comparison test report (above) to a text file.\n");
395 fp_msg (" -table Compress FITS binary tables as well as compress any image HDUs.\n");
396 fp_msg (" -tableonly Compress only FITS binary tables; do not compress any image HDUs.\n");
397 fp_msg (" \n");
398 
399 fp_msg ("\nkeywords shared with funpack:\n");
400 
401 fp_msg (" -F Overwrite input file by output file with same name.\n");
402 fp_msg (" -D Delete input file after writing output.\n");
403 fp_msg (" -Y Suppress prompts to confirm -F or -D options.\n");
404 
405 fp_msg (" -S Output compressed FITS files to STDOUT.\n");
406 fp_msg (" -L List contents; files unchanged.\n");
407 
408 fp_msg (" -C Don't update FITS checksum keywords.\n");
409 
410 fp_msg (" -H Show this message.\n");
411 fp_msg (" -V Show version number.\n");
412 
413 fp_msg ("\n <FITS> FITS files to pack; enter '-' (a hyphen) to read input from stdin stream.\n");
414 fp_msg (" Refer to the fpack User's Guide for more extensive help.\n");
415 return(0);
416 }
int fp_usage(void)
Definition: fpack.c:324
int fp_get_param(int argc, char *argv[], fpstate *fpptr)
Definition: fpack.c:39
int _fp_msg(const char *msg)
Definition: fpack.c:33
int fp_hint(void)
Definition: fpack.c:334
int fp_help(void)
Definition: fpack.c:340
#define SZ_STR
Definition: fpack.h:95
#define FP_INIT_MAGIC
Definition: fpack.h:84
int fp_version(void)
Definition: fpackutil.c:93
#define fp_msg(msg)
Definition: fpack.h:212
Definition: fpack.h:100
long ntile[MAX_COMPRESS_DIM]
Definition: fpack.h:112
int comptype
Definition: fpack.h:101
int no_dither
Definition: fpack.h:103
int listonly
Definition: fpack.h:115
int do_images
Definition: fpack.h:121
int test_all
Definition: fpack.h:123
int to_stdout
Definition: fpack.h:114
int do_tables
Definition: fpack.h:122
int initialized
Definition: fpack.h:132
int clobber
Definition: fpack.h:116
int dither_offset
Definition: fpack.h:104
float rescale_noise
Definition: fpack.h:107
int do_checksums
Definition: fpack.h:119
int dither_method
Definition: fpack.h:105
int delete_input
Definition: fpack.h:117
float quantize_level
Definition: fpack.h:102
int int_to_float
Definition: fpack.h:109
char outfile[SZ_STR]
Definition: fpack.h:129
int firstfile
Definition: fpack.h:130
float scale
Definition: fpack.h:106
int verbose
Definition: fpack.h:124
int do_not_prompt
Definition: fpack.h:118
float n3ratio
Definition: fpack.h:110
float n3min
Definition: fpack.h:111