int get_header_int(PyObject* header, const char* keyword, int* val, int def, HeaderGetFlags flags) { long tmp; int ret = get_header_long(header, keyword, &tmp, def, flags); if (ret == GET_HEADER_SUCCESS) { if (tmp >= INT_MIN && tmp <= INT_MAX) { *val = (int) tmp; } else { PyErr_Format(PyExc_OverflowError, "Cannot convert %ld to C 'int'", tmp); ret = GET_HEADER_FAILED; } } return ret; }
void configure_compression(fitsfile* fileptr, PyObject* header) { /* Configure the compression-related elements in the fitsfile struct using values in the FITS header. */ FITSfile* Fptr; int tfields; tcolumn* columns; char keyword[9]; char* zname; int znaxis; char* tmp; float version; unsigned int idx; Fptr = fileptr->Fptr; tfields = Fptr->tfield; columns = Fptr->tableptr; // Get the ZBITPIX header value; if this is missing we're in trouble if (0 != get_header_int(header, "ZBITPIX", &(Fptr->zbitpix), 0)) { return; } // By default assume there is no ZBLANK column and check for ZBLANK or // BLANK in the header Fptr->cn_zblank = Fptr->cn_zzero = Fptr->cn_zscale = -1; Fptr->cn_uncompressed = 0; #ifdef CFITSIO_SUPPORTS_GZIPDATA Fptr->cn_gzip_data = 0; #endif // Check for a ZBLANK, ZZERO, ZSCALE, and // UNCOMPRESSED_DATA/GZIP_COMPRESSED_DATA columns in the compressed data // table for (idx = 0; idx < tfields; idx++) { if (0 == strncmp(columns[idx].ttype, "UNCOMPRESSED_DATA", 18)) { Fptr->cn_uncompressed = idx + 1; #ifdef CFITSIO_SUPPORTS_GZIPDATA } else if (0 == strncmp(columns[idx].ttype, "GZIP_COMPRESSED_DATA", 21)) { Fptr->cn_gzip_data = idx + 1; #endif } else if (0 == strncmp(columns[idx].ttype, "ZSCALE", 7)) { Fptr->cn_zscale = idx + 1; } else if (0 == strncmp(columns[idx].ttype, "ZZERO", 6)) { Fptr->cn_zzero = idx + 1; } else if (0 == strncmp(columns[idx].ttype, "ZBLANK", 7)) { Fptr->cn_zblank = idx + 1; } } Fptr->zblank = 0; if (Fptr->cn_zblank < 1) { // No ZBLANK column--check the ZBLANK and BLANK heard keywords if(0 != get_header_int(header, "ZBLANK", &(Fptr->zblank), 0)) { // ZBLANK keyword not found get_header_int(header, "BLANK", &(Fptr->zblank), 0); } } Fptr->zscale = 1.0; if (Fptr->cn_zscale < 1) { if (0 != get_header_double(header, "ZSCALE", &(Fptr->zscale), 1.0)) { Fptr->cn_zscale = 0; } } Fptr->cn_bscale = Fptr->zscale; Fptr->zzero = 0.0; if (Fptr->cn_zzero < 1) { if (0 != get_header_double(header, "ZZERO", &(Fptr->zzero), 0.0)) { Fptr->cn_zzero = 0; } } Fptr->cn_bzero = Fptr->zzero; get_header_string(header, "ZCMPTYPE", &tmp, DEFAULT_COMPRESSION_TYPE); strncpy(Fptr->zcmptype, tmp, 11); Fptr->zcmptype[strlen(tmp)] = '\0'; Fptr->compress_type = compress_type_from_string(Fptr->zcmptype); if (PyErr_Occurred()) { return; } get_header_int(header, "ZNAXIS", &znaxis, 0); Fptr->zndim = znaxis; if (znaxis > MAX_COMPRESS_DIM) { // The CFITSIO compression code currently only supports up to 6 // dimensions by default. znaxis = MAX_COMPRESS_DIM; } Fptr->maxtilelen = 1; for (idx = 1; idx <= znaxis; idx++) { snprintf(keyword, 9, "ZNAXIS%u", idx); get_header_long(header, keyword, Fptr->znaxis + idx - 1, 0); snprintf(keyword, 9, "ZTILE%u", idx); get_header_long(header, keyword, Fptr->tilesize + idx - 1, 0); Fptr->maxtilelen *= Fptr->tilesize[idx - 1]; } // Set some more default compression options Fptr->rice_blocksize = DEFAULT_BLOCK_SIZE; Fptr->rice_bytepix = DEFAULT_BYTE_PIX; Fptr->quantize_level = DEFAULT_QUANTIZE_LEVEL; Fptr->hcomp_smooth = DEFAULT_HCOMP_SMOOTH; Fptr->hcomp_scale = DEFAULT_HCOMP_SCALE; // Now process the ZVALn keywords idx = 1; while (1) { snprintf(keyword, 9, "ZNAME%u", idx); // Assumes there are no gaps in the ZNAMEn keywords; this same // assumption was made in the Python code. This could be done slightly // more flexibly by using a wildcard slice of the header if (0 != get_header_string(header, keyword, &zname, "")) { break; } snprintf(keyword, 9, "ZVAL%u", idx); if (Fptr->compress_type == RICE_1) { if (0 == strcmp(zname, "BLOCKSIZE")) { get_header_int(header, keyword, &(Fptr->rice_blocksize), DEFAULT_BLOCK_SIZE); } else if (0 == strcmp(zname, "BYTEPIX")) { get_header_int(header, keyword, &(Fptr->rice_bytepix), DEFAULT_BYTE_PIX); } } else if (Fptr->compress_type == HCOMPRESS_1) { if (0 == strcmp(zname, "SMOOTH")) { get_header_int(header, keyword, &(Fptr->hcomp_smooth), DEFAULT_HCOMP_SMOOTH); } else if (0 == strcmp(zname, "SCALE")) { get_header_float(header, keyword, &(Fptr->hcomp_scale), DEFAULT_HCOMP_SCALE); } } else if (Fptr->zbitpix < 0 && 0 == strcmp(zname, "NOISEBIT")) { get_header_float(header, keyword, &(Fptr->quantize_level), DEFAULT_QUANTIZE_LEVEL); if (Fptr->quantize_level == 0.0) { /* NOISEBIT == 0 is equivalent to no quantize */ Fptr->quantize_level = NO_QUANTIZE; } } idx++; } /* The ZQUANTIZ keyword determines the quantization algorithm; NO_QUANTIZE implies lossless compression */ if (0 == get_header_string(header, "ZQUANTIZ", &tmp, "")) { /* Ugh; the fact that cfitsio defines its version as a float makes preprocessor comparison impossible */ fits_get_version(&version); if ((version >= CFITSIO_LOSSLESS_COMP_SUPPORTED_VERS) && (0 == strcmp(tmp, "NONE"))) { Fptr->quantize_level = NO_QUANTIZE; } else if (0 == strcmp(tmp, "SUBTRACTIVE_DITHER_1")) { #ifdef CFITSIO_SUPPORTS_SUBTRACTIVE_DITHER_2 // Added in CFITSIO 3.35, this also changed the name of the // quantize_dither struct member to quantize_method Fptr->quantize_method = SUBTRACTIVE_DITHER_1; } else if (0 == strcmp(tmp, "SUBTRACTIVE_DITHER_2")) { Fptr->quantize_method = SUBTRACTIVE_DITHER_2; } else { Fptr->quantize_method = NO_DITHER; } } else { Fptr->quantize_method = NO_DITHER; } if (Fptr->quantize_method != NO_DITHER) { if (0 != get_header_int(header, "ZDITHER0", &(Fptr->dither_seed), 0)) { // ZDITHER0 keyword not found Fptr->dither_seed = 0; Fptr->request_dither_seed = 0; } } #else Fptr->quantize_dither = SUBTRACTIVE_DITHER_1; } else {