/* read_fis.c */ /* Copyright (C) 2006 Icare - http://www.icare.univ-lille1.fr Fabrice Ducos, fabrice.ducos@icare.univ-lille1.fr This program is a free software; you can redistribute it and/or modify it under the terms of the CeCILL Public License as published by www.cecill.info (License version 2 or later). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL Public License for more details. You should have received a copy of the CeCILL Public License along with this program; if not, please contact www.cecill.info If you have any questions or concerns regarding this program, please email to problem@icare.univ-lille1.fr For general information about the ICARE Project, please email to icare-contact@univ-lille.fr */ #include #include #include #include #include #include #include #ifndef FILENAME_MAX /* is normally defined in stdio.h */ #define FILENAME_MAX 255 #endif /* add a NUL char at the end of string (string must be an array of chars, not a char *) */ #define C_STRINGIFY(string) ( string[sizeof(string) - 1] = '\0' ) static void swap_array_8(void *buffer, size_t nelements) { /* no swap */ return; } static void swap_array_16(void *buffer, size_t nelements) { register int i; uint16_t *buffer_16 = (uint16_t *) buffer; assert(nelements > 0); for (i = 0 ; i < nelements ; i++) { buffer_16[i] = ntohs(buffer_16[i]); } } static void swap_array_32(void *buffer, size_t nelements) { register int i; uint32_t *buffer_32 = (uint32_t *) buffer; assert(nelements > 0); for (i = 0 ; i < nelements ; i++) { buffer_32[i] = ntohl(buffer_32[i]); } } static const char fis_carac_format[] = "%40c%4c%4c%5c%5c%5c"; /* file characteristics */ static const char fis_creat_format[] = "%20c%5c%20c%80c"; /* creation identification */ static const char fis_updat_format[] = "%20c%5c"; /* update identification */ static const char fis_missi_format[] = "%2c%2c%2c%5c%14c%7c%4c"; /* mission and instrument parameters */ static const char fis_spatial_pos_format[] = "%7c%7c%7c%7c%7c%7c%7c%7c"; /* spatial positions of image data (in degrees) */ static const char fis_mission_pos_format[] = "%5c%5c%5c%5c"; /* positions of image data relative to the mission */ static const char fis_time_pos_format[] = "%14c%14c"; /* time positions of image data */ static const char fis_missing_format[] = "%5c"; /* missing rows in image data */ static const char fis_other_format[] = "%5c%6c%12c%6c%6c"; /* other parameters */ static const long fis_padding_size = 119; static char cstr_fil[40 + 1]; static char cstr_org[4 + 1]; static char cstr_typ[4 + 1]; static char cstr_mxp[5 + 1]; static char cstr_mxl[5 + 1]; static char cstr_mxc[5 + 1]; static char cstr_auc[20 + 1]; static char cstr_djc[5 + 1]; static char cstr_ser[20 + 1]; static char cstr_tit[80 + 1]; static char cstr_aum[20 + 1]; static char cstr_djm[5 + 1]; static char cstr_mis[2 + 1]; static char cstr_nim[2 + 1]; static char cstr_ins[2 + 1]; static char cstr_oss[5 + 1]; static char cstr_ijr[14 + 1]; static char cstr_llp[7 + 1]; static char cstr_csc[4 + 1]; static char cstr_anw[7 + 1]; static char cstr_onw[7 + 1]; static char cstr_ane[7 + 1]; static char cstr_one[7 + 1]; static char cstr_ase[7 + 1]; static char cstr_ose[7 + 1]; static char cstr_asw[7 + 1]; static char cstr_osw[7 + 1]; static char cstr_npp[5 + 1]; static char cstr_npl[5 + 1]; static char cstr_ndp[5 + 1]; static char cstr_ndl[5 + 1]; static char cstr_ijd[14 + 1]; static char cstr_ijf[14 + 1]; static char cstr_nlm[5 + 1]; static char cstr_nor[5 + 1]; static char cstr_nri[6 + 1]; static char cstr_nve[12 + 1]; static char cstr_nmi[6 + 1]; static char cstr_nbr[6 + 1]; static char *fis_fil; static char *fis_org; static char *fis_typ; static int fis_mxp; static int fis_mxl; static int fis_mxc; static char *fis_auc; static int fis_djc; static char *fis_ser; static char *fis_tit; static char *fis_aum; static int fis_djm; static int fis_mis; static int fis_nim; static int fis_ins; static int fis_oss; static double fis_ijr; static double fis_llp; static char *fis_csc; static double fis_anw; static double fis_onw; static double fis_ane; static double fis_one; static double fis_ase; static double fis_ose; static double fis_asw; static double fis_osw; static int fis_npp; static int fis_npl; static int fis_ndp; static int fis_ndl; static double fis_ijd; static double fis_ijf; static int fis_nlm; static int fis_nor; static int fis_nri; static char *fis_nve; static int fis_nmi; static int fis_nbr; /* read a FIS file (Format Image Standard from Lannion), given its filename * returns data into buffer, npix and pix_size when called like this: * ret = read_fis(filename, &buffer, &npix, &pix_size, log) * ret will contain 0 if no error occured, -1 otherwise * * buffer is a pointer to a grid of pixels allocated by read_fis (should be freed by the caller) * npix is the number of pixels in the grid * pix_size is the pixel size (1, 2 or 4 bytes only) * log is an input, to control error message printing on stderr (0: no error message on stderr, 1: error messages enabled) */ int read_fis(const char *filename, void **ptr_buffer, size_t *ptr_npix, size_t *ptr_pix_size, const unsigned char log) { FILE *stream; int nscanf; int retval; size_t pix_size; size_t phys_rec_size; int n_header_rec; void *buffer; size_t nread; size_t npix; char *ptr_dot_fis; void (*swap_array)(void *, size_t); #ifndef APPNAME # define APPNAME #endif ptr_dot_fis = strstr(filename, ".fis"); if (ptr_dot_fis == NULL) { if (log) fprintf(stderr, APPNAME ": read_fis: %s: expects a file with extension .fis\n", filename); return -1; } assert(ptr_dot_fis[4] == '\0'); /* will fail if .fis is not the last extension */ stream = fopen(filename, "r"); if (! stream) { if (log) fprintf(stderr, APPNAME ": read_fis: open(%s): %s\n", filename, strerror(errno)); return -1; } nscanf = fscanf(stream, fis_carac_format, cstr_fil, cstr_org, cstr_typ, cstr_mxp, cstr_mxl, cstr_mxc); assert(nscanf == 6); C_STRINGIFY(cstr_fil); C_STRINGIFY(cstr_org); C_STRINGIFY(cstr_typ); C_STRINGIFY(cstr_mxp); C_STRINGIFY(cstr_mxl); C_STRINGIFY(cstr_mxc); fis_fil = cstr_fil; fis_org = cstr_org; fis_typ = cstr_typ; fis_mxp = atoi(cstr_mxp); fis_mxl = atoi(cstr_mxl); fis_mxc = atoi(cstr_mxc); #ifdef DEBUG_READ_FIS printf("fis_fil %s\n" "fis_org %s\n" "fis_typ %s\n" "fis_mxp %i\n" "fis_mxl %i\n" "fis_mxc %i\n", fis_fil, fis_org, fis_typ, fis_mxp, fis_mxl, fis_mxc); #endif nscanf = fscanf(stream, fis_creat_format, cstr_auc, cstr_djc, cstr_ser, cstr_tit); assert(nscanf == 4); C_STRINGIFY(cstr_auc); C_STRINGIFY(cstr_djc); C_STRINGIFY(cstr_ser); C_STRINGIFY(cstr_tit); fis_auc = cstr_auc; fis_djc = atoi(cstr_djc); fis_ser = cstr_ser; fis_tit = cstr_tit; #ifdef DEBUG_READ_FIS printf("fis_auc %s\n" "fis_djc %i\n" "fis_ser %s\n" "fis_tit %s\n", fis_auc, fis_djc, fis_ser, fis_tit); #endif nscanf = fscanf(stream, fis_updat_format, cstr_aum, cstr_djm); assert(nscanf == 2); C_STRINGIFY(cstr_aum); C_STRINGIFY(cstr_djm); fis_aum = cstr_aum; fis_djm = atoi(cstr_djm); #ifdef DEBUG_READ_FIS printf("fis_aum %s\n" "fis_djm %i\n", fis_aum, fis_djm); #endif nscanf = fscanf(stream, fis_missi_format, cstr_mis, cstr_nim, cstr_ins, cstr_oss, cstr_ijr, cstr_llp, cstr_csc); assert(nscanf == 7); C_STRINGIFY(cstr_mis); C_STRINGIFY(cstr_nim); C_STRINGIFY(cstr_ins); C_STRINGIFY(cstr_oss); C_STRINGIFY(cstr_ijr); C_STRINGIFY(cstr_llp); C_STRINGIFY(cstr_csc); fis_mis = atoi(cstr_mis); fis_nim = atoi(cstr_nim); fis_ins = atoi(cstr_ins); fis_oss = atoi(cstr_oss); fis_ijr = atof(cstr_ijr); fis_llp = atof(cstr_llp); fis_csc = cstr_csc; #ifdef DEBUG_READ_FIS printf("cstr_ins %s\ncstr_oss %s\ncstr_ijr %s\n", cstr_ins, cstr_oss, cstr_ijr); printf("fis_mis %i\n" "fis_nim %i\n" "fis_ins %i\n" "fis_oss %i\n" "fis_ijr %f\n" "fis_llp %f\n" "fis_csc %s\n", fis_mis, fis_nim, fis_ins, fis_oss, fis_ijr, fis_llp, fis_csc); #endif nscanf = fscanf(stream, fis_spatial_pos_format, cstr_anw, cstr_onw, cstr_ane, cstr_one, cstr_ase, cstr_ose, cstr_asw, cstr_osw); assert(nscanf == 8); C_STRINGIFY(cstr_anw); C_STRINGIFY(cstr_onw); C_STRINGIFY(cstr_ane); C_STRINGIFY(cstr_one); C_STRINGIFY(cstr_ase); C_STRINGIFY(cstr_ose); C_STRINGIFY(cstr_asw); C_STRINGIFY(cstr_osw); fis_anw = atof(cstr_anw); fis_onw = atof(cstr_onw); fis_ane = atof(cstr_ane); fis_one = atof(cstr_one); fis_ase = atof(cstr_ase); fis_ose = atof(cstr_ose); fis_asw = atof(cstr_asw); fis_osw = atof(cstr_osw); #ifdef DEBUG_READ_FIS printf("fis_anw %f\n" "fis_onw %f\n" "fis_ane %f\n" "fis_one %f\n" "fis_ase %f\n" "fis_ose %f\n" "fis_asw %f\n" "fis_osw %f\n", fis_anw, fis_onw, fis_ane, fis_one, fis_ase, fis_ose, fis_asw, fis_osw); #endif nscanf = fscanf(stream, fis_mission_pos_format, cstr_npp, cstr_npl, cstr_ndp, cstr_ndl); assert(nscanf == 4); C_STRINGIFY(cstr_npp); C_STRINGIFY(cstr_npl); C_STRINGIFY(cstr_ndp); C_STRINGIFY(cstr_ndl); fis_npp = atoi(cstr_npp); fis_npl = atol(cstr_npl); fis_ndp = atol(cstr_ndp); fis_ndl = atol(cstr_ndl); #ifdef DEBUG_READ_FIS printf("fis_npp %i\n" "fis_npl %i\n" "fis_ndp %i\n" "fis_ndl %i\n", fis_npp, fis_npl, fis_ndp, fis_ndl); #endif nscanf = fscanf(stream, fis_time_pos_format, cstr_ijd, cstr_ijf); assert(nscanf == 2); C_STRINGIFY(cstr_ijd); C_STRINGIFY(cstr_ijf); fis_ijd = atoi(cstr_ijd); fis_ijf = atoi(cstr_ijf); #ifdef DEBUG_READ_FIS printf("fis_ijd %f\n" "fis_ijf %f\n", fis_ijd, fis_ijf); #endif nscanf = fscanf(stream, fis_missing_format, cstr_nlm); assert(nscanf == 1); C_STRINGIFY(cstr_nlm); fis_nlm = atoi(cstr_nlm); #ifdef DEBUG_READ_FIS printf("fis_nlm %i\n", fis_nlm); #endif nscanf = fscanf(stream, fis_other_format, cstr_nor, cstr_nri, cstr_nve, cstr_nmi, cstr_nbr); assert(nscanf == 5); C_STRINGIFY(cstr_nor); C_STRINGIFY(cstr_nri); C_STRINGIFY(cstr_nve); C_STRINGIFY(cstr_nmi); C_STRINGIFY(cstr_nbr); fis_nor = atoi(cstr_nor); fis_nri = atoi(cstr_nri); fis_nve = cstr_nve; fis_nmi = atoi(cstr_nmi); fis_nbr = atoi(cstr_nbr); #ifdef DEBUG_READ_FIS printf("fis_nor %i\n" "fis_nri %i\n" "fis_nve %s\n" "fis_nmi %i\n" "fis_nbr %i\n", fis_nor, fis_nri, fis_nve, fis_nmi, fis_nbr); #endif retval = fseek(stream, fis_padding_size, SEEK_CUR); /* jumps overs padding bytes in the header */ assert(retval == 0); /* WARNING: strncasecmp: BSD only (case insensitive string comparison) */ if (strncasecmp(fis_typ, "I1", 2) == 0) { pix_size = 1; swap_array = swap_array_8; } else if (strncasecmp(fis_typ, "I2", 2) == 0) { pix_size = 2; swap_array = swap_array_16; } else if (strncasecmp(fis_typ, "I4", 2) == 0) { pix_size = 4; swap_array = swap_array_32; } else { if (log) fprintf(stderr, APPNAME ": read_fis: invalid or not supported value for 'type': %s: expects only I1, I2 or I4\n", fis_typ); return -1; } #ifdef DEBUG_READ_FIS printf("pix_size %d\n", pix_size); #endif if (strncasecmp(fis_org, "PLC", 3) == 0) { phys_rec_size = fis_mxp*pix_size; } else if (strncasecmp(fis_org, "CPL", 3) == 0 || strncasecmp(fis_org, "PCL", 3) == 0) { phys_rec_size = fis_mxc*fis_mxp*pix_size; } else { fprintf(stderr, APPNAME ": read_fis: invalid or not supported value for 'organization': %s: expects only PLC, CPL and PCL\n", fis_org); return -1; } #ifdef DEBUG_READ_FIS printf("phys_rec_size = %d\n", phys_rec_size); #endif if (phys_rec_size < 512) { n_header_rec = 512/phys_rec_size; if ((512 % phys_rec_size) != 0) { n_header_rec++; } } else { n_header_rec = 2; } #ifdef DEBUG_READ_FIS printf("n_header_rec %d\n", n_header_rec); #endif retval = fseek(stream, n_header_rec * phys_rec_size, SEEK_SET); /* jumps over header data */ npix = fis_mxc*fis_mxl*fis_mxp; if (ptr_buffer) { buffer = calloc(npix, pix_size); nread = fread(buffer, pix_size, npix, stream); assert(nread == npix); swap_array(buffer, npix); switch (pix_size) { case 1 : { *((uint8_t **) ptr_buffer) = buffer; break; } case 2 : { *((uint16_t **) ptr_buffer) = buffer; break; } case 4 : { *((uint32_t **) ptr_buffer) = buffer; break; } default : { /* this should never happen */ fprintf(stderr, APPNAME ": read_fis: internal error: unexpected value for pix_size: %d\n", pix_size); abort(); break; } } /* switch */ } /* if (ptr_buffer) */ retval = fclose(stream); if (retval) { if (log) fprintf(stderr, APPNAME ": read_fis: close(%s): %s\n", filename, strerror(errno)); return -1; } if (ptr_npix) { *ptr_npix = npix; } if (ptr_pix_size) { *ptr_pix_size = pix_size; } return 0; }