File indexing completed on 2024-04-21 03:43:56
0001 /* 0002 SPDX-FileCopyrightText: William D. Pence <https://heasarc.gsfc.nasa.gov/fitsio/> 0003 SPDX-FileCopyrightText: R. Seaman 0004 0005 SPDX-License-Identifier: LicenseRef-NASA-FV-License-Agreement 0006 0007 Calls fits_img_compress in the CFITSIO library by W. Pence, HEASARC 0008 */ 0009 0010 #include <ctype.h> 0011 /* #include <signal.h> */ 0012 #include "fitsio.h" 0013 #include "fpack.h" 0014 0015 /* ================================================================== 0016 int main(int argc, char *argv[]) 0017 { 0018 fpstate fpvar; 0019 0020 if (argc <= 1) { fp_usage (); fp_hint (); exit (-1); } 0021 0022 fp_init (&fpvar); 0023 fp_get_param (argc, argv, &fpvar); 0024 0025 if (fpvar.listonly) { 0026 fp_list (argc, argv, fpvar); 0027 0028 } else { 0029 fp_preflight (argc, argv, FPACK, &fpvar); 0030 fp_loop (argc, argv, FPACK, fpvar); 0031 } 0032 0033 exit (0); 0034 } 0035 ================================================================== */ 0036 int _fp_msg (const char *msg) 0037 { 0038 printf ("%s", msg); 0039 return(0); 0040 } 0041 0042 int fp_get_param (int argc, char *argv[], fpstate *fpptr) 0043 { 0044 int gottype=0, gottile=0, wholetile=0, iarg, len, ndim, ii, doffset; 0045 char tmp[SZ_STR], tile[SZ_STR]; 0046 0047 if (fpptr->initialized != FP_INIT_MAGIC) { 0048 fp_msg ("Error: internal initialization error\n"); exit (-1); 0049 } 0050 0051 tile[0] = 0; 0052 0053 /* flags must come first and be separately specified 0054 */ 0055 for (iarg = 1; iarg < argc; iarg++) { 0056 if ((argv[iarg][0] == '-' && strlen (argv[iarg]) == 2) || 0057 !strncmp(argv[iarg], "-q", 2) || !strncmp(argv[iarg], "-qz", 3) || 0058 !strncmp(argv[iarg], "-g1", 3) || !strncmp(argv[iarg], "-g2", 3) || 0059 !strncmp(argv[iarg], "-i2f", 4) || 0060 !strncmp(argv[iarg], "-n3ratio", 8) || !strncmp(argv[iarg], "-n3min", 6) || 0061 !strncmp(argv[iarg], "-tableonly", 10) || !strncmp(argv[iarg], "-table", 6) ) 0062 { 0063 0064 /* Rice is the default, so -r is superfluous */ 0065 if ( argv[iarg][1] == 'r') { 0066 fpptr->comptype = RICE_1; 0067 if (gottype) { 0068 fp_msg ("Error: multiple compression flags\n"); 0069 fp_usage (); exit (-1); 0070 } else 0071 gottype++; 0072 0073 } else if (argv[iarg][1] == 'p') { 0074 fpptr->comptype = PLIO_1; 0075 if (gottype) { 0076 fp_msg ("Error: multiple compression flags\n"); 0077 fp_usage (); exit (-1); 0078 } else 0079 gottype++; 0080 0081 } else if (argv[iarg][1] == 'g') { 0082 /* test for modifiers following the 'g' */ 0083 if (argv[iarg][2] == '2') 0084 fpptr->comptype = GZIP_2; 0085 else 0086 fpptr->comptype = GZIP_1; 0087 0088 if (gottype) { 0089 fp_msg ("Error: multiple compression flags\n"); 0090 fp_usage (); exit (-1); 0091 } else 0092 gottype++; 0093 /* 0094 } else if (argv[iarg][1] == 'b') { 0095 fpptr->comptype = BZIP2_1; 0096 if (gottype) { 0097 fp_msg ("Error: multiple compression flags\n"); 0098 fp_usage (); exit (-1); 0099 } else 0100 gottype++; 0101 */ 0102 } else if (argv[iarg][1] == 'h') { 0103 fpptr->comptype = HCOMPRESS_1; 0104 if (gottype) { 0105 fp_msg ("Error: multiple compression flags\n"); 0106 fp_usage (); exit (-1); 0107 } else 0108 gottype++; 0109 0110 } else if (argv[iarg][1] == 'd') { 0111 fpptr->comptype = NOCOMPRESS; 0112 if (gottype) { 0113 fp_msg ("Error: multiple compression flags\n"); 0114 fp_usage (); exit (-1); 0115 } else 0116 gottype++; 0117 0118 } else if (!strcmp(argv[iarg], "-i2f")) { 0119 /* this means convert integer images to float, and then */ 0120 /* quantize and compress the float image. This lossy */ 0121 /* compression method may give higher compression than the */ 0122 /* lossless compression method that is usually applied to */ 0123 /* integer images. */ 0124 0125 fpptr->int_to_float = 1; 0126 0127 } else if (!strcmp(argv[iarg], "-n3ratio")) { 0128 /* this is the minimum ratio between the MAD noise sigma */ 0129 /* and the q parameter value in the case where the integer */ 0130 /* image is quantized and compressed like a float image. */ 0131 if (++iarg >= argc) { 0132 fp_usage (); exit (-1); 0133 } else { 0134 fpptr->n3ratio = (float) atof (argv[iarg]); 0135 } 0136 } else if (!strcmp(argv[iarg], "-n3min")) { 0137 /* this is the minimum MAD noise sigma in the case where the */ 0138 /* integer image is quantized and compressed like a float image. */ 0139 if (++iarg >= argc) { 0140 fp_usage (); exit (-1); 0141 } else { 0142 fpptr->n3min = (float) atof (argv[iarg]); 0143 } 0144 } else if (argv[iarg][1] == 'q') { 0145 /* test for modifiers following the 'q' */ 0146 0147 if (argv[iarg][2] == 'z') { 0148 fpptr->dither_method = 2; /* preserve zero pixels */ 0149 0150 if (argv[iarg][3] == 't') { 0151 fpptr->dither_offset = -1; /* dither based on tile checksum */ 0152 0153 } else if (isdigit(argv[iarg][3])) { /* is a number appended to q? */ 0154 doffset = atoi(argv[iarg]+3); 0155 0156 if (doffset == 0) { 0157 fpptr->no_dither = 1; /* don't dither the quantized values */ 0158 } else if (doffset > 0 && doffset <= 10000) { 0159 fpptr->dither_offset = doffset; 0160 } else { 0161 fp_msg ("Error: invalid q suffix\n"); 0162 fp_usage (); exit (-1); 0163 } 0164 } 0165 } else { 0166 if (argv[iarg][2] == 't') { 0167 fpptr->dither_offset = -1; /* dither based on tile checksum */ 0168 0169 } else if (isdigit(argv[iarg][2])) { /* is a number appended to q? */ 0170 doffset = atoi(argv[iarg]+2); 0171 0172 if (doffset == 0) { 0173 fpptr->no_dither = 1; /* don't dither the quantized values */ 0174 } else if (doffset > 0 && doffset <= 10000) { 0175 fpptr->dither_offset = doffset; 0176 } else { 0177 fp_msg ("Error: invalid q suffix\n"); 0178 fp_usage (); exit (-1); 0179 } 0180 } 0181 } 0182 0183 if (++iarg >= argc) { 0184 fp_usage (); exit (-1); 0185 } else { 0186 fpptr->quantize_level = (float) atof (argv[iarg]); 0187 } 0188 } else if (argv[iarg][1] == 'n') { 0189 if (++iarg >= argc) { 0190 fp_usage (); exit (-1); 0191 } else { 0192 fpptr->rescale_noise = (float) atof (argv[iarg]); 0193 } 0194 } else if (argv[iarg][1] == 's') { 0195 if (++iarg >= argc) { 0196 fp_usage (); exit (-1); 0197 } else { 0198 fpptr->scale = (float) atof (argv[iarg]); 0199 } 0200 } else if (!strcmp(argv[iarg], "-tableonly")) { 0201 fpptr->do_tables = 1; 0202 fpptr->do_images = 0; 0203 fp_msg ("Note: -tableonly is intended for feasibility studies, not general use.\n"); 0204 0205 } else if (!strcmp(argv[iarg], "-table")) { 0206 fpptr->do_tables = 1; 0207 fp_msg ("Note: -table is intended for feasibility studies, not general use.\n"); 0208 0209 } else if (argv[iarg][1] == 't') { 0210 if (gottile) { 0211 fp_msg ("Error: multiple tile specifications\n"); 0212 fp_usage (); exit (-1); 0213 } else 0214 gottile++; 0215 0216 if (++iarg >= argc) { 0217 fp_usage (); exit (-1); 0218 } else 0219 strncpy (tile, argv[iarg], SZ_STR-1); /* checked below */ 0220 0221 } else if (argv[iarg][1] == 'v') { 0222 fpptr->verbose = 1; 0223 0224 } else if (argv[iarg][1] == 'w') { 0225 wholetile++; 0226 if (gottile) { 0227 fp_msg ("Error: multiple tile specifications\n"); 0228 fp_usage (); exit (-1); 0229 } else 0230 gottile++; 0231 0232 } else if (argv[iarg][1] == 'F') { 0233 fpptr->clobber++; /* overwrite existing file */ 0234 0235 } else if (argv[iarg][1] == 'D') { 0236 fpptr->delete_input++; 0237 0238 } else if (argv[iarg][1] == 'Y') { 0239 fpptr->do_not_prompt++; 0240 0241 } else if (argv[iarg][1] == 'S') { 0242 fpptr->to_stdout++; 0243 0244 } else if (argv[iarg][1] == 'L') { 0245 fpptr->listonly++; 0246 0247 } else if (argv[iarg][1] == 'C') { 0248 fpptr->do_checksums = 0; 0249 0250 } else if (argv[iarg][1] == 'T') { 0251 fpptr->test_all = 1; 0252 0253 } else if (argv[iarg][1] == 'R') { 0254 if (++iarg >= argc) { 0255 fp_usage (); fp_hint (); exit (-1); 0256 } else 0257 strncpy (fpptr->outfile, argv[iarg], SZ_STR); 0258 0259 } else if (argv[iarg][1] == 'H') { 0260 fp_help (); exit (0); 0261 0262 } else if (argv[iarg][1] == 'V') { 0263 fp_version (); exit (0); 0264 0265 } else { 0266 fp_msg ("Error: unknown command line flag `"); 0267 fp_msg (argv[iarg]); fp_msg ("'\n"); 0268 fp_usage (); fp_hint (); exit (-1); 0269 } 0270 0271 } else 0272 break; 0273 } 0274 0275 if (fpptr->scale != 0. && 0276 fpptr->comptype != HCOMPRESS_1 && fpptr->test_all != 1) { 0277 0278 fp_msg ("Error: `-s' requires `-h or -T'\n"); exit (-1); 0279 } 0280 0281 if (fpptr->quantize_level == 0) { 0282 0283 if ((fpptr->comptype != GZIP_1) && (fpptr->comptype != GZIP_2)) { 0284 fp_msg ("Error: `-q 0' only allowed with GZIP\n"); exit (-1); 0285 } 0286 0287 if (fpptr->int_to_float == 1) { 0288 fp_msg ("Error: `-q 0' not allowed with -i2f\n"); exit (-1); 0289 } 0290 } 0291 0292 if (wholetile) { 0293 for (ndim=0; ndim < MAX_COMPRESS_DIM; ndim++) 0294 fpptr->ntile[ndim] = (long) -1; 0295 0296 } else if (gottile) { 0297 len = strlen (tile); 0298 for (ii=0, ndim=0; ii < len; ) { 0299 if (! (isdigit (tile[ii]) || tile[ii] == ',')) { 0300 fp_msg ("Error: `-t' requires comma separated tile dims, "); 0301 fp_msg ("e.g., `-t 100,100'\n"); exit (-1); 0302 } 0303 0304 if (tile[ii] == ',') { ii++; continue; } 0305 0306 fpptr->ntile[ndim] = atol (&tile[ii]); 0307 for ( ; isdigit(tile[ii]); ii++); 0308 0309 if (++ndim > MAX_COMPRESS_DIM) { 0310 fp_msg ("Error: too many dimensions for `-t', max="); 0311 snprintf (tmp, SZ_STR,"%d\n", MAX_COMPRESS_DIM); fp_msg (tmp); 0312 exit (-1); 0313 } 0314 } 0315 } 0316 0317 if (iarg >= argc) { 0318 fp_msg ("Error: no FITS files to compress\n"); 0319 fp_usage (); exit (-1); 0320 } else 0321 fpptr->firstfile = iarg; 0322 0323 return(0); 0324 } 0325 0326 /* ================================================================== */ 0327 int fp_usage (void) 0328 { 0329 fp_msg ("usage: fpack "); 0330 fp_msg ( 0331 "[-r|-h|-g|-p] [-w|-t <axes>] [-q <level>] [-s <scale>] [-n <noise>] -v <FITS>\n"); 0332 fp_msg ("more: [-T] [-R] [-F] [-D] [-Y] [-S] [-L] [-C] [-H] [-V] [-i2f]\n"); 0333 return(0); 0334 } 0335 0336 /* ================================================================== */ 0337 int fp_hint (void) 0338 { fp_msg (" `fpack -H' for help\n"); 0339 return(0); 0340 } 0341 0342 /* ================================================================== */ 0343 int fp_help (void) 0344 { 0345 fp_msg ("fpack, a FITS image compression program. Version "); 0346 fp_version (); 0347 fp_usage (); 0348 fp_msg ("\n"); 0349 fp_msg ("NOTE: the compression parameters specified on the fpack command line may\n"); 0350 fp_msg ("be over-ridden by compression directive keywords in the header of each HDU\n"); 0351 fp_msg ("of the input file(s). See the fpack User's Guide for more details\n"); 0352 fp_msg ("\n"); 0353 0354 fp_msg ("Flags must be separate and appear before filenames:\n"); 0355 fp_msg (" -r Rice compression [default], or\n"); 0356 fp_msg (" -h Hcompress compression, or\n"); 0357 fp_msg (" -g or -g1 GZIP_1 (per-tile) compression, or\n"); 0358 fp_msg (" -g2 GZIP_2 (per-tile) compression (with byte shuffling), or\n"); 0359 /* 0360 fp_msg (" -b BZIP2 (per-tile) compression, or\n"); 0361 */ 0362 fp_msg (" -p PLIO compression (only for positive 8 or 16-bit integer images).\n"); 0363 fp_msg (" -d Tile the image without compression (debugging mode).\n"); 0364 0365 fp_msg (" -w Compress the whole image as a single large tile.\n"); 0366 fp_msg (" -t <axes> Comma separated list of tile dimensions [default is row by row].\n"); 0367 0368 fp_msg (" -q <level> Quantized level spacing when converting floating point images to\n"); 0369 fp_msg (" scaled integers. (+value relative to sigma of background noise;\n"); 0370 fp_msg (" -value is absolute). Default q value of 4 gives a compression ratio\n"); 0371 fp_msg (" of about 6 with very high fidelity (only 0.26% increase in noise).\n"); 0372 fp_msg (" Using q values of 2, or 1 will give compression ratios of\n"); 0373 fp_msg (" about 8, or 10, respectively (with 1.0% or 4.1% noise increase).\n"); 0374 fp_msg (" The scaled quantized values are randomly dithered using a seed \n"); 0375 fp_msg (" value determined from the system clock at run time.\n"); 0376 fp_msg (" Use -q0 instead of -q to suppress random dithering.\n"); 0377 fp_msg (" Use -qz instead of -q to not dither zero-valued pixels.\n"); 0378 fp_msg (" Use -qt or -qzt to compute random dithering seed from first tile checksum.\n"); 0379 fp_msg (" Use -qN or -qzN, (N in range 1 to 10000) to use a specific dithering seed.\n"); 0380 fp_msg (" Floating-point images can be losslessly compressed by selecting\n"); 0381 fp_msg (" the GZIP algorithm and specifying -q 0, but this is slower and often\n"); 0382 fp_msg (" produces much less compression than the default quantization method.\n"); 0383 fp_msg (" -i2f Convert integer images to floating point, then quantize and compress\n"); 0384 fp_msg (" using the specified q level. When used appropriately, this lossy\n"); 0385 fp_msg (" compression method can give much better compression than the normal\n"); 0386 fp_msg (" lossless compression methods without significant loss of information.\n"); 0387 fp_msg (" The -n3ratio and -n3min flags control the minimum noise thresholds;\n"); 0388 fp_msg (" Images below these thresholds will be losslessly compressed.\n"); 0389 fp_msg (" -n3ratio Minimum ratio of background noise sigma divided by q. Default = 2.0.\n"); 0390 fp_msg (" -n3min Minimum background noise sigma. Default = 6. The -i2f flag will be ignored\n"); 0391 fp_msg (" if the noise level in the image does not exceed both thresholds.\n"); 0392 fp_msg (" -s <scale> Scale factor for lossy Hcompress [default = 0 = lossless]\n"); 0393 fp_msg (" (+values relative to RMS noise; -value is absolute)\n"); 0394 fp_msg (" -n <noise> Rescale scaled-integer images to reduce noise and improve compression.\n"); 0395 fp_msg (" -v Verbose mode; list each file as it is processed.\n"); 0396 fp_msg (" -T Show compression algorithm comparison test statistics; files unchanged.\n"); 0397 fp_msg (" -R <file> Write the comparison test report (above) to a text file.\n"); 0398 fp_msg (" -table Compress FITS binary tables as well as compress any image HDUs.\n"); 0399 fp_msg (" -tableonly Compress only FITS binary tables; do not compress any image HDUs.\n"); 0400 fp_msg (" \n"); 0401 0402 fp_msg ("\nkeywords shared with funpack:\n"); 0403 0404 fp_msg (" -F Overwrite input file by output file with same name.\n"); 0405 fp_msg (" -D Delete input file after writing output.\n"); 0406 fp_msg (" -Y Suppress prompts to confirm -F or -D options.\n"); 0407 0408 fp_msg (" -S Output compressed FITS files to STDOUT.\n"); 0409 fp_msg (" -L List contents; files unchanged.\n"); 0410 0411 fp_msg (" -C Don't update FITS checksum keywords.\n"); 0412 0413 fp_msg (" -H Show this message.\n"); 0414 fp_msg (" -V Show version number.\n"); 0415 0416 fp_msg ("\n <FITS> FITS files to pack; enter '-' (a hyphen) to read input from stdin stream.\n"); 0417 fp_msg (" Refer to the fpack User's Guide for more extensive help.\n"); 0418 return(0); 0419 }