/* LIBPOL_VERSION ="@(#)polder.c 1.3 98/01/16" */ /******************************************************************************/ /* */ /* NAME OF PROJECT: POLDER Library */ /* */ /* NAME OF OBJECT: polder.c */ /* DATE OF CREATION: July 3rd, 1997 */ /* */ /* AUTHORS: CESBIO / CISI / CNES */ /* */ /* ROLE: */ /* */ /* MODIFICATIONS : */ /* DATE : REF CF : */ /******************************************************************************/ /*----------------------------------------------------------------------------*/ /* Inclusion of STANDARD files (.h) */ /*----------------------------------------------------------------------------*/ #include #include #include #include #include #include #include /*----------------------------------------------------------------------------*/ /* Inclusion of SPECIFIC files (.h) */ /*----------------------------------------------------------------------------*/ #include "config.h" #include "polder.h" #include "EndianSwap/EndianSwap.h" /*----------------------------------------------------------------------------*/ /* Macros definition */ /*----------------------------------------------------------------------------*/ #define FREE(A) { if ((A)!=NULL) { free(A); (A)=NULL; } } #ifndef max #define max(a,b) (a>b) ? a : b #endif #ifndef min #define min(a,b) (a>= 8; n = nb-1; for (nb=2;n>0;n--) nb*=2; nb--; dqx_size = product[id]->par[0].lgt * 8; if (pos >= dqx_size) return UNDEF; n = max(13, (13+(dqx_size/32-1-pos/32)*4)); m = min(4, (dqx_size/8)); memcpy(&dqx_par,buf+n,m); if(product[id]->is_big_endian != ARCH_BIG_ENDIAN) dqx_par = ES_swap_int(&dqx_par); dqx_par >>= (4-m)*8; pos %= 32; dqx_par >>= pos; dqx_par &= nb; return (unsigned short int)dqx_par; } /* End of internal operation get_bits */ /******************************************************************************/ /* */ /* OPERATION : get_float */ /* */ /* ROLE : This function decode data and give the float value */ /* */ /* CALLING CONTEXT : float get_float( par, buf, sign, type) */ /* */ /* par PARAMETER (E) : parameters to compute float value */ /* buf u.char (E) : data to decode */ /* sign int (E) : determine sign of the float value (0 or 1) */ /* type int (E) : type of Polder product */ /* is_big_endian (E) : byte ordering */ /* */ /* RETURN VALUE : on success, return the float value */ /* on error, return an undefined value NaN */ /* */ /* TYPE : float */ /* */ /******************************************************************************/ float get_float(PARAMETER par, unsigned char* buf,int sign, int type,unsigned int is_big_endian) { float f; unsigned char tmp_uchar; signed short tmp_short; unsigned short tmp_ushort; unsigned long tmp_ulong; switch(par.lgt) { case 1: memcpy(&tmp_uchar,buf+par.pos,1); if ( (tmp_uchar == 0xFF) || (tmp_uchar == 0xFE) || (!sign && tmp_uchar == 0x00 && type == B11) || (sign && tmp_uchar == 0x81 && type == B11) ) f = NaN; else f = (float)tmp_uchar*par.a + par.b; break; case 2: if (sign) { if(is_big_endian == ARCH_BIG_ENDIAN) memcpy(&tmp_short,buf+par.pos,2); else ES_memcpy_swap(&tmp_short,buf+par.pos,1,2); switch(tmp_short) { case -32767: /* 0x8001 = missing data (lev 1)for signed short int */ case 32767: /* 0x7FFF = dense data (lev 1) for unsigned short int */ f = NaN; break; default: f = (float)tmp_short*par.a + par.b; } } else { if(is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&tmp_ushort,buf+par.pos,2); } else { ES_memcpy_swap(&tmp_ushort,buf+par.pos,1,2); } if ( (tmp_ushort == 65535) || /* 0xFFFF = missing data (level 2-3) for short int */ (tmp_ushort == 65534) || /* 0xFFFE = invalid data */ (tmp_ushort == 0 && type == B11) ) /* 0x7FFF = missing data (level 1) for short int */ f = NaN; else f = (float)tmp_ushort*par.a + par.b; } break; case 4: if(is_big_endian == ARCH_BIG_ENDIAN) memcpy(&tmp_ulong,buf+par.pos,4); else ES_memcpy_swap(&tmp_ulong,buf+par.pos,1,4); f = (float)tmp_ulong*par.a + par.b; break; } return f; } /* End of internal operation get_float */ /******************************************************************************/ /* */ /* OPERATION : IsNAN */ /* */ /* ROLE : This function return True = 1 if X is an undefined value (=-999) */ /* return False = 0 if X is an defined value */ /* */ /* CALLING CONTEXT : int IsNAN(X) */ /* */ /* X float (E) : value to be tested */ /* */ /* RETURN VALUE : if X is undefined, return 0 else return 1 */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int IsNAN(float X) { if (X==-999) return 1; else return 0; } /* End of internal operation IsNAN */ /******************************************************************************/ /* */ /* OPERATION : polder_error */ /* */ /* ROLE : This function give the message corresponding to the number error*/ /* */ /* */ /* CALLING CONTEXT : void polder_error(err,...) */ /* */ /* err int (E) : number error */ /* ... (E) : value to include in the error message */ /* */ /* RETURN VALUE : no return value */ /* */ /* TYPE : void */ /* */ /******************************************************************************/ void polder_error(int err,...) { va_list argument; char* filename; int id,line,column; /* Message depends of error value : err */ switch(err) { case PLD_UNDEF_PID: fprintf(stderr,"Invalid product identifiant\n"); break; case PLD_MAX_OPENED: fprintf(stderr, "Too many products opened\n\tRetry with another value in InitPolder\n"); break; case PLD_FILE_ACCESS: va_start(argument,err); filename = va_arg(argument,char*); va_end(argument); fprintf(stderr, "Error on opening \"%s\"\n\tVerify exact filename and pathname\n", filename); break; case PLD_ALT_FILENAME: va_start(argument,err); filename = va_arg(argument,char*); va_end(argument); fprintf(stderr, "The product filename \"%s\" is not a generic filename\n", filename); break; case PLD_PRODUCT_EMPTY: fprintf(stderr,"Product seems empty\n"); break; case PLD_FILESIZE: fprintf(stderr, "Error on accessing data\n\tProduct seems alterated\n"); break; case PLD_PIXEL_UNDEFINED: va_start(argument,err); id = va_arg(argument,int); line = va_arg(argument,int); column = va_arg(argument,int); va_end(argument); fprintf(stderr, "Pixel (%4d,%4d) is not observed in current product\n",line, column); break; case PLD_NOMEM: fprintf(stderr,"Memory allocation error\n"); break; case PLD_INVAL: fprintf(stderr,"Invalid argument\n"); break; case PLD_OUTSIDE: va_start(argument,err); id = va_arg(argument,int); line = va_arg(argument,int); va_end(argument); fprintf(stderr,"Line %4d outside the product\n",line); break; case PLD_PRODUCT_UNAVAILABLE: fprintf(stderr, "This file appears to be valid Polder product, but it is not recognized by libpolder.\n"); fprintf(stderr, "Most probably, the versions of the product and libpolder are not compatible.\n"); break; default: fprintf(stderr,"undefined error in the product\n"); break; } } /* End of internal operation polder_error */ /******************************************************************************/ /* */ /* OPERATION : ExtractVariable_Var */ /* */ /* ROLE : extract all parameters of one variable */ /* */ /* CALLING CONTEXT : int ExtractVariable_Var(id, val, type) */ /* */ /* id (int) (E) : product identifiant */ /* val (short **) (S) : pointer on values array */ /* type (int) (E) : parameter type */ /* */ /* Note : The caller must free memory for values array */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_NOMEM memory allocation error */ /* PLD_INVAL invalid parameter */ /* PLD_LIG_INVAL invalid lines ( 1st line > Last line) */ /* PLD_OUTSIDE line outside the product */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* */ /******************************************************************************/ int get_Date(int id, char **begin, char **end) { int err; int status; PRODUCT *prod; unsigned char *buffer; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* read the number of pixels */ buffer = (unsigned char *)malloc(17); status = fseek(prod->lfid,640,SEEK_SET); status = fread(buffer,16,1,prod->lfid); if (status!=1) { err = PLD_FILESIZE; goto error; } buffer[16]='\0'; *begin = buffer; buffer = (unsigned char *)malloc(17); status = fseek(prod->lfid,656,SEEK_SET); status = fread(buffer,16,1,prod->lfid); if (status!=1) { err = PLD_FILESIZE; goto error; } buffer[16]='\0'; *end = buffer; return PLD_OK; error: if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,index); } return err; } /* End of internal operation ExtractVariable_Var */ /******************************************************************************/ /* */ /* OPERATION : ExtractVariable_Var */ /* */ /* ROLE : extract all parameters of one variable */ /* */ /* CALLING CONTEXT : int ExtractVariable_Var(id, val, type) */ /* */ /* id (int) (E) : product identifiant */ /* val (short **) (S) : pointer on values array */ /* type (int) (E) : parameter type */ /* */ /* Note : The caller must free memory for values array */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_NOMEM memory allocation error */ /* PLD_INVAL invalid parameter */ /* PLD_LIG_INVAL invalid lines ( 1st line > Last line) */ /* PLD_OUTSIDE line outside the product */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* */ /******************************************************************************/ int ExtractVariable_Var(int id, float **val, int type) { int err; int status; PRODUCT *prod; unsigned char *buffer; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* read the number of pixels */ buffer = (unsigned char *)malloc(sizeof(int)); status = fseek(prod->dfid,52,SEEK_SET); status = fread(buffer,4,1,prod->dfid); if (status!=1) { FREE(buffer); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&prod->records_number,buffer,4); } else { ES_memcpy_int(&prod->records_number,(void*)buffer,1); } FREE(buffer); /* initialisation of the result pointer */ (*val) = (float *)malloc(prod->records_number*sizeof(float)); /* reading and memorisation of all pixels */ float var_float; unsigned char *buf = (unsigned char *)malloc(prod->pixlgt); long index; for(index=0; index < prod->records_number; index++) { /* read one pixel */ status = fseek(prod->dfid, DESCRIPTOR + index*prod->pixlgt, SEEK_SET); if (status) { FREE(buf); err = PLD_FILESIZE; goto error; } if (fread(buf,prod->pixlgt,1,prod->dfid) != 1) { FREE(buf); err = PLD_FILESIZE; goto error; } /* extract the good value in var */ ExtractParameter(id,buf,&var_float,type); /* save the value */ (*val)[index] = var_float; } FREE(buf); return PLD_OK; error: if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,index); } return err; } /******************************************************************************/ /* */ /* OPERATION : ExtractVariable_Var */ /* */ /* ROLE : extract all parameters of one variable */ /* */ /* CALLING CONTEXT : int ExtractVariable_Var(id, val, type) */ /* */ /* id (int) (E) : product identifiant */ /* val (short **) (S) : pointer on values array */ /* type (int) (E) : parameter type */ /* */ /* Note : The caller must free memory for values array */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_NOMEM memory allocation error */ /* PLD_INVAL invalid parameter */ /* PLD_LIG_INVAL invalid lines ( 1st line > Last line) */ /* PLD_OUTSIDE line outside the product */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* */ /******************************************************************************/ int ExtractVariable_Var_Byte(int id, unsigned char **val, int type) { int err; int status; PRODUCT *prod; unsigned char *buffer; int size; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* read the number of pixels */ buffer = (unsigned char *)malloc(sizeof(int)); status = fseek(prod->dfid,52,SEEK_SET); status = fread(buffer,4,1,prod->dfid); if (status!=1) { FREE(buffer); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&prod->records_number,buffer,4); } else { ES_memcpy_int(&prod->records_number,(void*)buffer,1); } FREE(buffer); size = prod->records_number; /* initialisation of the result pointer */ (*val) = (unsigned char *)malloc(prod->records_number*sizeof(unsigned char)); /* reading and memorisation of all pixels */ unsigned char var_short; unsigned char *ptr=(*val); int i; PARAMETER par = prod->par[type & TYPE]; //printf("type = %d - pos = %d\n",type,par.pos); unsigned char *buf=(unsigned char*)malloc(prod->pixlgt*sizeof(unsigned char)); for(i=0; irecords_number; i++) { /*if type to read is Lines*/ status = fseek(prod->dfid, DESCRIPTOR + i*(prod->pixlgt)+par.pos, SEEK_SET); if(status) { FREE(buf); err = PLD_FILESIZE; goto error; } if(!fread(buf,prod->pixlgt,1,prod->dfid)) { FREE(buf); err = PLD_FILESIZE; goto error; } memcpy(&var_short,(void*)buf,1); /* save the value */ // (*ptr) = var_short; ptr++; } FREE(buf); return PLD_OK; error: if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,i); } return err; } int ExtractVariable_Var_Short(int id, unsigned short **val, int type) { int err; int status; PRODUCT *prod; unsigned char *buffer; int size; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* read the number of pixels */ buffer = (unsigned char *)malloc(sizeof(int)); status = fseek(prod->dfid,52,SEEK_SET); status = fread(buffer,4,1,prod->dfid); if (status!=1) { FREE(buffer); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&prod->records_number,buffer,4); } else { ES_memcpy_int(&prod->records_number,(void*)buffer,1); } FREE(buffer); size = prod->records_number; /* initialisation of the result pointer */ (*val) = (unsigned short *)malloc(prod->records_number*sizeof(unsigned short)); /* reading and memorisation of all pixels */ unsigned short var_short; unsigned short *ptr=(*val); int i; PARAMETER par = prod->par[type & TYPE]; //printf("type = %d - pos = %d\n",type,par.pos); unsigned char *buf=(unsigned char*)malloc(prod->pixlgt*sizeof(unsigned char)); for(i=0; irecords_number; i++) { /*if type to read is Lines*/ status = fseek(prod->dfid, DESCRIPTOR + i*(prod->pixlgt)+par.pos, SEEK_SET); if(status) { FREE(buf); err = PLD_FILESIZE; goto error; } if(!fread(buf,prod->pixlgt,1,prod->dfid)) { FREE(buf); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&var_short,(void*)buf,2); } else { ES_memcpy_swap(&var_short,(void*)buf,1,2); } /* save the value */ // (*ptr) = var_short; ptr++; } FREE(buf); return PLD_OK; error: if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,i); } return err; } /* End of internal operation ExtractVariable_Var */ /* End of internal operation ExtractVariable_Var */ /******************************************************************************/ /* */ /* OPERATION : ExtractVariable_Var */ /* */ /* ROLE : extract all parameters of one variable */ /* */ /* CALLING CONTEXT : int ExtractVariable_Var(id, val, type) */ /* */ /* id (int) (E) : product identifiant */ /* val (short **) (S) : pointer on values array */ /* type (int) (E) : parameter type */ /* */ /* Note : The caller must free memory for values array */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_NOMEM memory allocation error */ /* PLD_INVAL invalid parameter */ /* PLD_LIG_INVAL invalid lines ( 1st line > Last line) */ /* PLD_OUTSIDE line outside the product */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* */ /******************************************************************************/ int ExtractVariable_Var_Int(int id, unsigned int **val, int type) { int err; int status; PRODUCT *prod; unsigned char *buffer; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* read the number of pixels */ buffer = (unsigned char *)malloc(sizeof(int)); status = fseek(prod->dfid,52,SEEK_SET); status = fread(buffer,4,1,prod->dfid); if (status!=1) { FREE(buffer); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&prod->records_number,buffer,4); } else { ES_memcpy_int(&prod->records_number,(void*)buffer,1); } FREE(buffer); /* initialisation of the result pointer */ (*val) = (unsigned int *)malloc(prod->records_number*sizeof(unsigned int)); /* reading and memorisation of all pixels */ unsigned int var_int; unsigned int var_short; unsigned char *buf = (unsigned char *)malloc(prod->pixlgt*sizeof(unsigned char)); //unsigned char *buf = (unsigned char *)malloc(prod->pixlgt); *buf = (unsigned char) 0; long index; PARAMETER par = prod->par[type & TYPE]; for(index=0; index < prod->records_number; index++) { /* read one pixel */ status = fseek(prod->dfid, DESCRIPTOR + index*(prod->pixlgt)+par.pos, SEEK_SET); if (status) { FREE(buf); err = PLD_FILESIZE; goto error; } if(!fread(buf,2,1,prod->dfid)) { FREE(buf); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&var_short,buf,2); } else { ES_memcpy_int(&var_short,(void*)buf,1); } /* save the value */ (*val)[index] = (unsigned int)var_short; } FREE(buf); return PLD_OK; error: if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,index); } return err; } /* End of internal operation ExtractVariable_Var */ /******************************************************************************/ /* */ /* OPERATION : ExtractVariable_Grid */ /* */ /* ROLE : extract all line or column values (the same index value of arrays*/ /* read by ExtractVariable_Grid and ExtractVariable_Var represent */ /* the same pixel) */ /* */ /* CALLING CONTEXT : int ExtractVariable_Grid(id, val, size, grid) */ /* */ /* id (int) (E) : product identifiant */ /* val (short **) (S) : pointer on values array */ /* size (int*) (S) : size of the array */ /* grid (int) (E) : type of request (LINE/COLUMN) */ /* */ /* Note : The caller must free memory for values array */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_NOMEM memory allocation error */ /* PLD_INVAL invalid parameter */ /* PLD_LIG_INVAL invalid lines ( 1st line > Last line) */ /* PLD_OUTSIDE line outside the product */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* */ /******************************************************************************/ int ExtractVariable_Grid(int id, short **val, int *size, int grid) { int err; int status; PRODUCT *prod; unsigned char *buffer; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* read the number of pixels */ buffer = (unsigned char *)malloc(sizeof(int)); status = fseek(prod->dfid,52,SEEK_SET); status = fread(buffer,4,1,prod->dfid); if (status!=1) { FREE(buffer); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&prod->records_number,buffer,4); } else { ES_memcpy_int(&prod->records_number,(void*)buffer,1); } FREE(buffer); (*size) = prod->records_number; /* initialisation of the result pointer */ (*val) = (short *)malloc(prod->records_number*sizeof(short)); /* reading and memorisation of all pixels */ short var_short; short *ptr=(*val); int i; unsigned char *buf=(unsigned char*)malloc(sizeof(short)); for(i=0; irecords_number; i++) { /*if type to read is Lines*/ if( grid == LINE ) { status = fseek(prod->dfid, DESCRIPTOR + i*(prod->pixlgt)+6, SEEK_SET); if(status) { FREE(buf); err = PLD_FILESIZE; goto error; } if(!fread(buf,2,1,prod->dfid)) { FREE(buf); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&var_short,buf,2); } else { ES_memcpy_short(&var_short,(void*)buf,1); } } else { status = fseek(prod->dfid, DESCRIPTOR + i*(prod->pixlgt)+8, SEEK_SET); if(status) { FREE(buf); err = PLD_FILESIZE; goto error; } if(!fread(buf,2,1,prod->dfid)) { FREE(buf); err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) { memcpy(&var_short,buf,2); } else { ES_memcpy_short(&var_short,(void*)buf,1); } } /* save the value */ (*ptr) = var_short; ptr++; } FREE(buf); return PLD_OK; error: fprintf(stderr,"ERROR: "); if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,i); } return err; } /* End of internal operation ExtractVariable_Grid */ /******************************************************************************/ /* */ /* OPERATION : get_type_product */ /* */ /* ROLE : This function give type of Polder Product */ /* */ /* */ /* CALLING CONTEXT : int get_type_product(level,nbpar,pixsize,maxpix,maxlig) */ /* */ /* level (int) (E) : level of Polder product (1,2 or 3) */ /* nbpar (int) (E) : number of parameters per pixel in Polder Product*/ /* pixsize (int) (E) : size of pixel record (byte) */ /* maxpix (int *) (S) : maximum number of pixels in line */ /* maxlig (int *) (S) : maxximum number of lines in Polder Product */ /* */ /* RETURN VALUE : type of product : */ /* */ /* L2C : Land Surfaces & Atmosphere: aerosols and water vapor */ /* L3B : Land Surfaces & Atmosphere: albedo and NDVI */ /* O2C : Ocean color & marine aerosols: marine aerosol parameters */ /* O2B : Ocean color & marine aerosols: non directional parameters */ /* L3C : Land Surfaces & Atmosphere: atmospheric parameters */ /* L3A : Land Surfaces & Atmosphere: surface directional signatures */ /* O3C : Ocean color & marine aerosols: marine aerosol parameters */ /* O3B : Ocean color & marine aerosols: marine parameters synthesis */ /* O2A : Ocean color & marine aerosols: directional parameters */ /* L2A : Land Surfaces & Atmosphere: surface parameters */ /* B11 : Level 1 */ /* R3B : Earth radiation and clouds Level 3 */ /* R2B : Earth radiation and clouds Level 2 */ /* UNDEF : Type undefined */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int get_type_product(int level, int nbpar, int pixsize,int * maxpix, int * maxlig) { int type; type = UNDEF; switch(nbpar) { case 8: type = L2C; *maxpix = 2160; *maxlig = 1080; break; case 18: type = L3B; *maxpix = 6480; *maxlig = 3240; break; case 22: type = O2C; *maxpix = 2160; *maxlig = 1080; break; case 21: type = O2B; *maxpix = 6480 ; *maxlig = 3240; break; case 32: type = L3A; *maxpix = 6480; *maxlig = 3240; break; case 43: type = L3C; *maxpix = 2160; *maxlig = 1080; break; case 51: type = R3B; *maxpix = 2160 ; *maxlig = 1080; break; case 63: type = O3C; *maxpix = 2160 ; *maxlig = 1080; break; case 84: type = O3B; *maxpix = 6480 ; *maxlig = 3240; break; case 126: type = O2A; *maxpix = 6480 ; *maxlig = 3240; break; case 130: type = L2A; *maxpix = 6480 ; *maxlig = 3240; break; case 148: type = L2C; *maxpix = 6480 ; *maxlig = 3240; break; case 196: type = R2B; *maxpix = 2160 ; *maxlig = 1080; break; case 216: type = R2B; *maxpix = 2160 ; *maxlig = 1080; break; case 327: type = B11; *maxpix = 6480 ; *maxlig = 3240; break; case 373: type = B11; *maxpix = 6480 ; *maxlig = 3240; break; default: type = UNDEF; *maxpix = 0 ; *maxlig = 0; break; } return type; } /* End of internal operation get_type_product */ /******************************************************************************/ /* */ /* OPERATION : get_nb_par_dir */ /* */ /* ROLE : This function give the number of directional parameters */ /* */ /* */ /* CALLING CONTEXT : int get_nb_par_dir(type) */ /* */ /* type (int) (E) type of Polder product as the following values : */ /* O2A : Ocean color & marine aerosols: directional parameters */ /* L2A : Land Surfaces & Atmosphere: surface parameters */ /* B11 : Level 1 */ /* R2B : Earth radiation and clouds Level 2 */ /* */ /* RETURN VALUE : number of directional parameters */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int get_nb_par_dir(int type) { int nb_par_dir; switch(type) { case B11: nb_par_dir = B11_NB_PAR_DIR; break; case L2A: nb_par_dir = L2A_NB_PAR_DIR; break; case O2A: nb_par_dir = O2A_NB_PAR_DIR; break; case R2B: nb_par_dir = R2B_NB_PAR_DIR; break; default: nb_par_dir = 0; break; } return nb_par_dir; } /* End of internal operation get_nb_par_dir */ /******************************************************************************/ /* */ /* OPERATION : get_colnumber */ /* */ /* ROLE : This function give the pixel number in the line */ /* */ /* */ /* CALLING CONTEXT : short get_colnumber(buffer) */ /* */ /* buffer (u.char *) (E) buffer into pixel number is read */ /* is_big_endian unsigned int (E) byte ordering */ /* RETURN VALUE : pixel number in the line */ /* */ /* TYPE :short */ /* */ /******************************************************************************/ short get_colnumber(unsigned char* buffer, unsigned int is_big_endian) { short tmp; if(is_big_endian == ARCH_BIG_ENDIAN) memcpy(&tmp,buffer+8,2); else ES_memcpy_short(&tmp,(void*)buffer+8,1); return tmp; } /* End of internal operation get_colnumber */ /******************************************************************************/ /* */ /* OPERATION : get_linenumber */ /* */ /* ROLE : This function give the pixel line */ /* */ /* */ /* CALLING CONTEXT : short get_linenumber(buffer) */ /* */ /* buffer (u.char *) (E) buffer into pixel number is read */ /* is_big_endian unsigned int (E) byte ordering */ /* RETURN VALUE : pixel line */ /* */ /* TYPE :short */ /* */ /******************************************************************************/ short get_linenumber(unsigned char* buffer, unsigned int is_big_endian) { short tmp; if(is_big_endian == ARCH_BIG_ENDIAN) memcpy(&tmp,buffer+6,2); else ES_memcpy_short(&tmp,(void*)buffer+6,1); return tmp; } /* End of internal operation get_linenumber */ /******************************************************************************/ /* */ /* OPERATION : ExtractParameter */ /* */ /* ROLE : This function extract a pixel parameter */ /* */ /* CALLING CONTEXT : int ExtractParameter(id, buffer,val,type) */ /* */ /* id (int) (E) : product identifiant */ /* buffer (u.char *) (E/S) : pointer on data records */ /* val (float *) (E/S) : pointer on values parameter array */ /* type (int) (E) : type of Polder Product */ /* */ /* parameter is identified by its reel sequence, added to the extract mode, */ /* if it is a directional parameter. */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_NOMEM memory allocation error */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int ExtractParameter(int id, unsigned char* buffer, float* val, int type) { int mode; /* extraction mode for directionnels parametres */ int refl; int sign; int cas_br_i, cas_br_j, option_br; float tmp; float zs,zv; float zv_min; int i_min; int i,j,n; float sum_li[10]; float sum_col, sum_glob; int num_elem, num_tab; int num; /* number record of the pixel */ /* internal purpose function : no parameter error controle */ /* refl: brightness -> reflectance exchange flag (only level 1) */ if (product[id]->type == B11) refl = (type & RAD2REF); else refl = 0; mode = type & MODE; sign = type & SB; cas_br_i = (type & CAS_BR_I) >> 13; cas_br_j = (type & CAS_BR_J) >> 9; option_br = type & OPT_BR; type = type & TYPE; if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) memcpy(&num,buffer,4); else ES_memcpy_swap(&num,buffer,1,4); /* if record number is null, pixel is empty */ if (!num) { switch(mode) { case ALL: for (i=0;i<14;i++) val[i] = NaN; break; default: *val = NaN; break; } } /* in general case... */ else { switch(mode) { case ALL: /* the 14 directions */ for (i=0;i<14;i++) { if (refl) zs = get_float( product[id]->par[B1_THS+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); val[i] = get_float( product[id]->par[type+(product[id]->nb_par_dir)*i], buffer,sign,product[id]->type,product[id]->is_big_endian); if ((!IsNAN(val[i])) && (refl)) val[i] /= cos(zs*PI/180.); } break; case FIRST: /* first valid direction */ i = 0; do { if (refl) zs = get_float( product[id]->par[B1_THS+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); *val = get_float( product[id]->par[type+(product[id]->nb_par_dir)*i], buffer,sign,product[id]->type,product[id]->is_big_endian); i++; } while ((IsNAN(*val)) && (i<14)); if ((!IsNAN(*val)) && (refl)) *val /= cos(zs*PI/180.); break; case LAST: /* last valid direction */ i = 13; do { if (refl) zs = get_float( product[id]->par[B1_THS+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); *val = get_float( product[id]->par[type+(product[id]->nb_par_dir)*i], buffer,sign,product[id]->type,product[id]->is_big_endian); i--; } while ((IsNAN(*val)) && (i>=0)); if ((!IsNAN(*val)) && (refl)) *val /= cos(zs*PI/180.); break; case MEAN: /* valid directions mean */ *val = 0.; n = 0; for (i=0;i<14;i++) { if (refl) zs = get_float( product[id]->par[B1_THS+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); tmp = get_float( product[id]->par[type+(product[id]->nb_par_dir)*i], buffer,sign,product[id]->type,product[id]->is_big_endian); if (!IsNAN(tmp)) { if (refl) tmp /= cos(zs*PI/180.); *val += tmp; n++; } } if (!IsNAN(*val)) *val /= n; break; case NADIR: /* value for nearest nadir direction */ i_min = -1; zv_min = 999.; for (i=0;i<14;i++) { switch(product[id]->type) { /* Level 1 */ case B11: zv = get_float( product[id]->par[B1_THV+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); break; /* Land Surfaces & Atmosphere: surface parameters */ case L2A: zv = get_float( product[id]->par[L2_THV+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); break; /* Ocean color & marine aerosols: directional parameters */ case O2A: zv = get_float( product[id]->par[L2_THV+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); break; } if ((!IsNAN(zv))&&(zvpar[B1_THS+(product[id]->nb_par_dir)*i_min], buffer,0,product[id]->type,product[id]->is_big_endian); *val = get_float( product[id]->par[type+(product[id]->nb_par_dir)*i_min], buffer,sign,product[id]->type,product[id]->is_big_endian); if ((!IsNAN(*val)) && (refl)) *val /= cos(zs*PI/180.); break; case MEDIAN: /* mean of valid values ) */ *val = NaN; break; case LIST_02: case LIST_03: case LIST_04: case LIST_05: n = mode >> 24; for (i=0;ipar[type+(product[id]->nb_par_dir)*i], buffer,sign,product[id]->type,product[id]->is_big_endian); break; case VIEW_01: case VIEW_02: case VIEW_03: case VIEW_04: case VIEW_05: case VIEW_06: case VIEW_07: case VIEW_08: case VIEW_09: case VIEW_10: case VIEW_11: case VIEW_12: case VIEW_13: case VIEW_14: i = (mode >> 16) - 1; if (refl) zs = get_float( product[id]->par[B1_THS+(product[id]->nb_par_dir)*i], buffer,0,product[id]->type,product[id]->is_big_endian); *val = get_float( product[id]->par[type+(product[id]->nb_par_dir)*i], buffer,sign,product[id]->type,product[id]->is_big_endian); if ((!IsNAN(*val)) && (refl)) *val /= cos(zs*PI/180.); break; default: /* case of undirectional parameters */ if (cas_br_i == 0 && cas_br_j == 0) { *val = get_float(product[id]->par[type],buffer,sign,0,product[id]->is_big_endian); } else { for (i=0;i<10;i++) sum_li[i]=0; sum_glob = 0; num_elem = 0; num_tab = 0; for (j=0;jpar[type+num_elem], buffer,sign,0,product[id]->is_big_endian); sum_col += val[num_tab]; sum_glob += val[num_tab]; sum_li[i] += val[num_tab]; num_tab++; num_elem++; } if (option_br) { val[num_tab] = sum_col; num_tab++; } } if (option_br) { for (i=0;i=NBproduct)) { err = PLD_UNDEF_PID; goto error; } if (product[id]==NULL) { err = PLD_UNDEF_PID; goto error; } if ((line < product[id]->north) || (line > product[id]->south)) { /* line outside the product */ err = PLD_OUTSIDE; goto error; } nb_pixels = product[id]->pos[line+1-product[id]->north] - product[id]->pos[line-product[id]->north]; if (nb_pixels == 0) { /* line not observed */ err = PLD_OUTSIDE; goto error; } status = fseek(product[id]->dfid,DESCRIPTOR+ product[id]->pos[line-product[id]->north]*product[id]->pixlgt, SEEK_SET); if (status) { err = PLD_FILESIZE; goto error; } if (fread(buffer,product[id]->pixlgt,nb_pixels, product[id]->dfid)!=nb_pixels) { err = PLD_FILESIZE; goto error; } return nb_pixels; error: if (verbose>1) { fprintf(stderr,"[ReadLine]: "); polder_error(err,id,line); } return err; } /* End of external operation ReadLine */ /******************************************************************************/ /* */ /* OPERATION : ReadPixel */ /* */ /* ROLE : This function read a pixel in Polder product */ /* */ /* CALLING CONTEXT : int ReadPixel(id, line ,col ,buffer) */ /* */ /* id (int) (E) : product identifiant */ /* line (int) (E) : line number (in the Polder grid) */ /* col (int) (E) : column number (in the Polder grid) */ /* buffer (void *) (E/S) : pointer on data records */ /* Note : The caller must allocate and free memory for buffer to read */ /* data records */ /* there is no control of buffer size. Mostly for internal use */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_NOMEM memory allocation error */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int ReadPixel(int id,int line, int column, void *buffer) { int pixels; int i,j; unsigned char* buf; short col; int err; /* Initialisations */ buf=NULL; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } if (product[id]==NULL) { err = PLD_UNDEF_PID; goto error; } /* Memory allocation*/ buf = (unsigned char*)malloc(product[id]->pixlgt*product[id]->pixline); if (buf == NULL) { err = PLD_NOMEM; goto error; /* Read the line */ } pixels = ReadLine(id,line,buf); if (pixels < 0) { err = pixels; goto error; } /* extract the first pixel in the line */ col = get_colnumber(buf, product[id]->is_big_endian); if (column < col) { err = PLD_PIXEL_UNDEFINED; goto error; } /* extract the last pixel in the line */ col = get_colnumber(buf+(pixels-1)*product[id]->pixlgt, product[id]->is_big_endian); if (column > col) { err = PLD_PIXEL_UNDEFINED; goto error; } /* extract data for requested pixel */ for (i=0; ipixlgt, product[id]->is_big_endian); if (col == column) break; if (col > column) { err = PLD_PIXEL_UNDEFINED; goto error; } } /* write the record, free allocated memory and quit */ memcpy(buffer,buf+i*product[id]->pixlgt,product[id]->pixlgt); FREE(buf); return PLD_OK; error: FREE(buf); if (verbose) { fprintf(stderr,"[ReadPixel]: "); polder_error(err,id,line,column); } return err; } /* End of external operation ReadPixel */ /******************************************************************************/ /* */ /* OPERATION : ReadNextPixel */ /* */ /* ROLE : This function read next record number in Polder product */ /* */ /* CALLING CONTEXT : int ReadNextPixel(id, line, column,no_rec, buffer) */ /* */ /* id (int) (E) : product identifiant */ /* line (int) (E) : line number (in the Polder grid) */ /* col (int) (E) : column number (in the Polder grid) */ /* no_rec (int) (E) : record number (1 up to records_number) */ /* 0 to go to next pixel */ /* buffer (void *) (E/S) : pointer on data records */ /* Note : The caller must allocate and free memory for buffer to read */ /* data records */ /* there is no control of buffer size. Mostly for internal use */ /* */ /* RETURN VALUE : on success, return next record number */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int ReadNextPixel(int id,int line, int column, int no_rec, void* buffer) { int err; int status; PRODUCT *prod; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod = product[id]; if (prod == NULL) { err = PLD_UNDEF_PID; goto error; } /* compute the record number */ status = SetLineCol(id,line,column); if (status != PLD_OK) { err = status; goto error; } /* read the number of pixels */ status = fseek(prod->dfid,52,SEEK_SET); status = fread(buffer,4,1,prod->dfid); if (status!=1) { err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) memcpy(&prod->records_number,buffer,4); else ES_memcpy_int(&prod->records_number,buffer,1); if ((no_rec > prod->records_number) || (prod->current > prod->records_number - 1)) { /* line not observed */ err = PLD_PIXEL_UNDEFINED; goto error; } if (no_rec > 0) prod->current = no_rec; else prod->current++; status = fseek(prod->dfid, DESCRIPTOR + (prod->current)*prod->pixlgt, SEEK_SET); if (status) { err = PLD_FILESIZE; goto error; } if (fread(buffer,prod->pixlgt,1,prod->dfid) != 1) { err = PLD_FILESIZE; goto error; } return prod->current; error: if (verbose) { fprintf(stderr,"[ReadNextPixel]: "); polder_error(err,id,no_rec); } return err; } /* End of internal operation ReadNextPixel */ /******************************************************************************/ /* */ /* OPERATION : SetLineCol */ /* */ /* ROLE : Compute the pixel record number that correspond to */ /* pixel line column number */ /* */ /* CALLING CONTEXT : int SetLineCol(id, line, col) */ /* */ /* id (int) (E) : product identifiant */ /* line (int) (E) : line number (in the Polder grid) */ /* col (int) (E) : line number (in the Polder grid) */ /* */ /* RETURN VALUE : on success, return the record that correspond to line col*/ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_OUTSIDE line outside the product */ /* PLD_FILESIZE error on accessing data */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int SetLineCol(int id, int line, int col) { int nb_pixels; int err; int status; PRODUCT *prod; int current; short column; unsigned char *buf; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } prod=product[id]; if (prod==NULL) { err = PLD_UNDEF_PID; goto error; } if ((line < prod->north) || (line > prod->south)) { /* line outside the product */ err = PLD_OUTSIDE; goto error; } buf=(unsigned char*)malloc(sizeof(short)); nb_pixels= prod->pos[line+1-prod->north] - prod->pos[line-prod->north]; if (nb_pixels == 0) { /* line not observed */ err = PLD_OUTSIDE; goto error; } current=prod->pos[line-prod->north]+1; while(nb_pixels--) { status = fseek(prod->dfid, DESCRIPTOR + (current-1)*prod->pixlgt+8, SEEK_SET); if(status) { err = PLD_FILESIZE; goto error; } if(!fread(buf,2,1,prod->dfid)) { err = PLD_FILESIZE; goto error; } if(product[id]->is_big_endian == ARCH_BIG_ENDIAN) memcpy(&column,buf,2); else ES_memcpy_short(&column,(void*)buf,1); if(column == col) break; current++; } if(nb_pixels + 1 == 0) { /* col is not observed */ err = PLD_OUTSIDE; goto error; } /* ok we found the record at (line,col) pos */ /* we go back of one record (compatibility with ReaDNextPixel ) */ if(current) current--; prod->current = current; return PLD_OK; error: return err; /* End of internal operation SetLineCol*/ } /******************************************************************************/ /******************************************************************************/ /* */ /* definition of EXTERNAL OPERATIONS */ /* */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* */ /* OPERATION : InitPolder */ /* ROLE : Display Polder Library information message and set the number */ /* of products opened simultaneously and the verbose or quiet mode.*/ /* */ /* CALLING CONTEXT : int InitPolder(NBproduct,VerboseMode) */ /* */ /* RETURN VALUE : on success ,PLD_OK */ /* if failed, return a error code : */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int InitPolder(int nbproduct, int VerboseMode) { int err; /* initialization is done just one time */ if (!initialization_done) { fprintf(stderr,"\nPolder2 Library (version: 1.1)\n\n"); fprintf(stderr,"Authors: CNES / CISI / CESBIO\n"); fprintf(stderr,"-----------------------------\n\n"); verbose = VerboseMode; NBproduct = nbproduct; product = (PRODUCT **)calloc(NBproduct,sizeof(PRODUCT *)); if (product == NULL) { err = PLD_NOMEM; goto error; } initialization_done = 1; } return PLD_OK; error: if (verbose) { fprintf(stderr,"[InitPolder]: "); polder_error(err); } return err; } /* End of external operation InitPolder */ /******************************************************************************/ /* */ /* OPERATION : OpenProduct */ /* ROLE : This function open Polder leader and data files,read parameters */ /* for internal use. */ /* */ /* CALLING CONTEXT : int OpenProduct(filename) */ /* */ /* filename (char*) (E) : Polder product filename */ /* You can use either the Polder leader file name or the Polder data file */ /* name, but the two files must be present in the same directory and the */ /* filename must be given with its whole pathname. */ /* */ /* RETURN VALUE : on success ,product identifiant which should be used as */ /* product reference in other functions */ /* if failed, return a error code : */ /* PLD_MAX_OPENED too many products open */ /* PLD_NOMEM memory allocation error */ /* PLD_FILE_ACCESS error on opening leader file */ /* PLD_ALT_FILENAME not generic filename */ /* PLD_FILESIZE error on accessing data */ /* PLD_PRODUCT_EMPTY product empty */ /* PLD_PRODUCT_UNAVAILABLE product and libpolder are not compatible */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int OpenProduct(char* filename) { FILE *fid; PRODUCT *prod; int pixels_line[3240], i,j; int north,south; char file[500], *c; char level; int pos; int id; int err; int status; char endianess[BYTE_ORDERING+1]; /* if the initialization has been forgotten, we do it */ if (!initialization_done) { InitPolder(50,1); } /* search a free identifiant */ for (id=0;idlfid = NULL; prod->dfid = NULL; prod->par = NULL; prod->pos = NULL; /* access to leader file of the Product */ strcpy(file,filename); c = strrchr(file,'/'); if (c == NULL) c = file; else c++; *(c+15) = 'L'; prod->lfid = fopen(file,"r"); if (prod->lfid == NULL) { err = PLD_FILE_ACCESS; goto error; } /* access to the Polder data file */ *(c+15) = 'D'; prod->dfid = fopen(file,"r"); if (prod->dfid == NULL) { err = PLD_FILE_ACCESS; prod->dfid = NULL; goto error; } /* initialize the current position into the data file */ prod->current = 0; level = *(c+3) - '0'; status = 0; switch (level) { case 1: status += fseek(prod->lfid,TECHNOLOGICAL,SEEK_CUR); case 2: status += fseek(prod->lfid,SPATIOTEMPO+INSTRUMENT,SEEK_CUR); case 3: status += fseek(prod->lfid,DESCRIPTOR+HEADER+PREPROCESSING, SEEK_CUR); break; default: err = PLD_ALT_FILENAME; goto error; } /* reading the byte ordering */ status += fseek(prod->lfid,16,SEEK_CUR); if (status) { err = PLD_FILESIZE; goto error; } status = fscanf(prod->lfid,"%16c",endianess); if (status!=1) { err = PLD_FILESIZE; goto error; } endianess[BYTE_ORDERING] = '\0'; prod->is_big_endian = (strcmp(endianess, "BIG ENDIAN ") == 0); status=0; /* reading the "scaling" record" ** -> number of parameters per pixel ** -> size of pixel record ** -> (size,a and b) for every parameter */ status = fscanf(prod->lfid,"%4d%8d",&prod->nbpar,&prod->pixlgt); if (status!=2) { err = PLD_FILESIZE; goto error; } /* Searching the type of product */ prod->type = get_type_product(level,prod->nbpar,prod->pixlgt, &(prod->maxpix), &(prod->maxlig)); if (prod->type==UNDEF) { err = PLD_PRODUCT_UNAVAILABLE; goto error; } /* Searching the number of directional parameters */ prod->nb_par_dir = get_nb_par_dir (prod->type); prod->par = (PARAMETER*) malloc(prod->nbpar*sizeof(PARAMETER)); if (prod->par==NULL) { err = PLD_NOMEM; goto error; } for (i=0,pos=13;inbpar;i++) { fscanf(prod->lfid,"%02d%12f%12f",&prod->par[i].lgt, &prod->par[i].a,&prod->par[i].b); prod->par[i].pos = pos; pos += prod->par[i].lgt; } status = fseek(prod->lfid,SCALING-44-prod->nbpar*26,SEEK_CUR); /* reading the "annotation" record" ** -> number of lines in the product ** -> number of pixels per line ** -> the first North line ** -> the last South line ** ** Note : The lower and upper limits of the product are present at the ** "spatioindicral" record which is not at level 3. So, they ** are computed again here. */ status += fseek(prod->lfid,200,SEEK_CUR); if (status) { err = PLD_FILESIZE; goto error; } fscanf(prod->lfid,"%4d",&prod->lines_number); /* if product is empty, line number equal 0 */ if (prod->lines_number == 0) { err = PLD_PRODUCT_EMPTY; goto error; } prod->pixline = 0; for (i=0;imaxlig;i++) { fscanf(prod->lfid,"%4d",&pixels_line[i]); if (pixels_line[i] > prod->pixline) prod->pixline = pixels_line[i]; } for (i=0;!pixels_line[i];i++) ; prod->north = i+1; for (i=prod->maxlig-1;!pixels_line[i];i--) ; prod->south = i+1; prod->pos = (int*) malloc((prod->south - prod->north + 2)*sizeof(int)); if (prod->pos==NULL) { err = PLD_NOMEM; goto error; } prod->pos[0] = 0; for (i=prod->north,j=0;i<=prod->south;i++,j++) prod->pos[j+1] = prod->pos[j] + pixels_line[i-1]; status = fseek(prod->lfid,ANNOTATION-204-prod->maxlig*4,SEEK_CUR); return id; error: if (verbose) { fprintf(stderr,"[OpenProduct]: "); polder_error(err,file); } if(id > 0) CloseProduct(id); return err; } /* End of external operation OpenProduct*/ /******************************************************************************/ /* */ /* OPERATION : CloseProduct */ /* */ /* ROLE : This function close Polder leader and data files */ /* */ /* CALLING CONTEXT : int CloseProduct(id) */ /* */ /* id (int) (E) : product identifiant */ /* */ /* RETURN VALUE : no return value */ /* */ /* TYPE : void */ /* */ /******************************************************************************/ void CloseProduct(int id) { if ((id<0) || (id>=NBproduct)) return; fclose(product[id]->lfid); fclose(product[id]->dfid); FREE(product[id]->pos); FREE(product[id]->par); FREE(product[id]); } /* End of external operation CloseProduct */ /******************************************************************************/ /* */ /* OPERATION : ExtractPixel */ /* */ /* ROLE : This function extract parameter(s) from Polder pixel */ /* */ /* CALLING CONTEXT : int ExtractPixel(id, line ,column ,val,nbpar,...) */ /* */ /* id (int) (E) : product identifiant */ /* line (int) (E) : line number (in the Polder grid) */ /* column (int) (E) : column number (in the Polder grid) */ /* val (void*) (E/S) : pointer on values array */ /* nbpar (int) (E) : number of parameters to extract */ /* ... : parameter list (see in UserManual */ /* "PARAMETERS DESCRIPTION"*/ /* Note : The caller must allocate and free memory for values array */ /* there is no control of buffer size. */ /* */ /* RETURN VALUE : on success, return PLD_OK */ /* otherwise, return a error code like : */ /* PLD_UNDEF_PID Product identifiant undefined */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_NOMEM memory allocation error */ /* PLD_INVAL invalid parameter */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int ExtractPixel(int id, int line, int column, void* val, int nbpar, ...) { unsigned char *buffer; int status; va_list argument; int *type; int *pos; int mode; /* extraction mode for directionnels parametres */ int cas_br_i, cas_br_j, option_br; int i,p; int err; int num; /* number of record of the pixel */ /* Initialize */ type = NULL; pos = NULL; buffer = NULL; /* Parameters control */ if ((id<0) || (id>=NBproduct)) { err = PLD_UNDEF_PID; goto error; } if (product[id]==NULL) { err = PLD_UNDEF_PID; goto error; } if (!nbpar) { err = PLD_INVAL; goto error; } /* allocate the parameter list */ type = (int*) malloc(sizeof(int)*nbpar); pos = (int*) malloc(sizeof(int)*nbpar); buffer = (unsigned char*) malloc(product[id]->pixlgt); if ((pos == NULL) || (type == NULL) || (buffer == NULL)) { err = PLD_NOMEM; goto error; } /* decode parameter list */ va_start(argument,nbpar); for (i=0,p=0;i> 13; cas_br_j = (*(type+i) & CAS_BR_J) >> 9; option_br = *(type+i) & OPT_BR; if ((mode) && (!product[id]->nb_par_dir)) { err = PLD_INVAL; goto error; } switch(mode) { case ALL: p += 14; break; case LIST_02: p += 2; break; case LIST_03: p += 3; break; case LIST_04: p += 4; break; case LIST_05: p += 5; break; default: if (cas_br_i==0 && cas_br_j==0) p++; else { if (option_br) p=p+(cas_br_i+1)*(cas_br_j+1); else p=p+cas_br_i*cas_br_j; } } } va_end(argument); /* read the pixel in Polder product */ status = ReadPixel(id,line,column,buffer); if (status) { err = status; goto error; } for (i=0;i=NBproduct)) { err = PLD_UNDEF_PID; goto error; } if (product[id]==NULL) { err = PLD_UNDEF_PID; goto error; } if (!nbpar) { err = PLD_INVAL; goto error; } /* allocate the parameter list */ type = (int*) malloc(sizeof(int)*nbpar); pos = (int*) malloc(sizeof(int)*nbpar); buffer = (unsigned char*) malloc(product[id]->pixlgt); if ((pos == NULL) || (type == NULL) || (buffer == NULL)) { err = PLD_NOMEM; goto error; } /* decode parameter list */ va_start(argument,nbpar); for (i=0,p=0;i> 13; cas_br_j = (*(type+i) & CAS_BR_J) >> 9; option_br = *(type+i) & OPT_BR; if ((mode) && (!product[id]->nb_par_dir)) { err = PLD_INVAL; goto error; } switch(mode) { case ALL: p += 14; break; case LIST_02: p += 2; break; case LIST_03: p += 3; break; case LIST_04: p += 4; break; case LIST_05: p += 5; break; default: if (cas_br_i==0 && cas_br_j==0) p++; else { if (option_br) p=p+(cas_br_i+1)*(cas_br_j+1); else p=p+cas_br_i*cas_br_j; } } } va_end(argument); /* read the pixel in Polder product */ status = ReadNextPixel(id,*line,*column,0,buffer); if (status<0) { err = status; goto error; } *line= get_linenumber(buffer, product[id]->is_big_endian); *column= get_colnumber(buffer, product[id]->is_big_endian); for (i=0;i Last line) */ /* PLD_OUTSIDE line outside the product */ /* PLD_PIXEL_UNDEFINED pixel not observed */ /* PLD_FILESIZE error on accessing data */ /* */ /* TYPE : int */ /* */ /******************************************************************************/ int ExtractBlock(int id, int lineN, int colW, int lineS, int colE, void *val, int fmt, int nbpar, ...) { unsigned char* buffer, *buf; int status; int height=lineS-lineN+1; int width; int col; float *tmp; int *type; int *pos; int mode; int cas_br_i, cas_br_j, option_br; va_list argument; int p,i,l,c; int pixels; int nbband; int err; int indic; int cntCol; int MAXCOL; int Taille; float * val_local; /* Initialisations */ buffer = NULL; tmp = NULL; type = NULL; pos = NULL; MAXCOL = product[id]->maxpix; val_local = (float *) val; /* Test if case crossover the 180 meridian */ if (colE=NBproduct)) { err = PLD_UNDEF_PID; goto error; } if (product[id]==NULL) { err = PLD_UNDEF_PID; goto error; } if (lineN > lineS) { err = PLD_LIG_INVAL; goto error; } /* Memory allocation for parameters list */ buffer = (unsigned char*) malloc(product[id]->pixlgt*product[id]->pixline); type = (int*) malloc(sizeof(int)*nbpar); pos = (int*) malloc(sizeof(int)*nbpar); if ((pos==NULL) || (type==NULL) || (buffer==NULL)) { err = PLD_NOMEM; goto error; } va_start(argument,nbpar); for (i=0,p=0;i> 13; cas_br_j = (*(type+i) & CAS_BR_J) >> 9; option_br = *(type+i) & OPT_BR; if ((mode) && (product[id]->type % 4)) { err = PLD_INVAL; goto error; } switch(mode) { case ALL: p += 14; break; case LIST_02: p += 2; break; case LIST_03: p += 3; break; case LIST_04: p += 4; break; case LIST_05: p += 5; break; default: if (cas_br_i==0 && cas_br_j==0) p++; else { if (option_br) p=p+(cas_br_i+1)*(cas_br_j+1); else p=p+cas_br_i*cas_br_j; } } } va_end(argument); nbband = p; tmp = (float*) malloc(sizeof(float)*nbband); if (tmp==NULL) { err = PLD_NOMEM; goto error; } Taille = width*height * nbband; for (i=0; i< Taille; i++) val_local[i] = -999; for (l=lineN;l<=lineS;l++) { pixels = ReadLine(id,l,buffer); /* An error is accepted on the current line */ for (c=0;cpixlgt; col = get_colnumber(buf, product[id]->is_big_endian); if (((colE=colW) || (col<=colE))) || ((colE>=colW) && (col>=colW) && (col<=colE))) { if (col >= colW) cntCol = col - colW; else cntCol = col - colW + MAXCOL; p = (l-lineN)*width + cntCol; for (i=0;i=NBproduct)) { err = PLD_UNDEF_PID; goto error; } if (product[id]==NULL) { err = PLD_UNDEF_PID; goto error; } if (!nbpar) { err = PLD_INVAL; goto error; } /* Allocate memory */ buffer = (unsigned char*) malloc(product[id]->pixlgt); if (buffer == NULL) { err = PLD_NOMEM; goto error; } /* Read the pixel */ status = ReadPixel(id,line,column,buffer); if (status) { err = status; goto error; } va_start(argument,nbpar); /* for all parameters to extract */ for (i=0;imaxpix; } /* GetProductMaxpix ** function: returns the product type. ** id: product identifiant. ** return: the product type. */ int GetProductType (int id) { return product[id]->type; } /******************************************************************************/ /******************************************************************************/ /* */ /* definition of OPERATIONS for calls from FORTRAN */ /* */ /* The parameter exchange is made by reference and not by value */ /* These functions make a link with C-written library */ /* The resolution of functions name is different according to the systems */ /* */ /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ /* */ /* On IBM,SUN,DEC,PC/LINUX system */ /* */ /******************************************************************************/ #define INITPOLDER_F77 F77_FUNC(initpolder,INITPOLDER) #define OPENPRODUCT_F77 F77_FUNC(openproduct,OPENPRODUCT) #define CLOSEPRODUCT_F77 F77_FUNC(closeproduct,CLOSEPRODUCT) #define EXTRACTPIXEL_F77 F77_FUNC(extractpixel,EXTRACTPIXEL) #define EXTRACTNEXTPIXEL_F77 F77_FUNC(extractnextpixel,EXTRACTNEXTPIXEL) #define EXTRACTPIXELDQX_F77 F77_FUNC(extractpixeldqx,EXTRACTPIXELDQX) #define EXTRACTBLOCK_F77 F77_FUNC(extractblock,EXTRACTBLOCK) void INITPOLDER_F77(int * status,int * nbproduct, int * VerboseMode) { *status = InitPolder(* nbproduct,* VerboseMode); } void OPENPRODUCT_F77(int* id,char* filename,int lg) { char *c; char * tmp; tmp = (char *)malloc((lg+1)*sizeof(char)); strncpy(tmp,filename,lg); tmp[lg] = '\0'; c = strchr(tmp,' '); if (c != NULL) *c = '\0'; *id = OpenProduct(tmp); } void CLOSEPRODUCT_F77(int *id) { CloseProduct(*id); } void EXTRACTPIXEL_F77(int * status,int* id, int *line, int *column, void* val, int *nbpar, ...) { /* be careful : in fortran , exchange maximum 100 parameters */ int *type[100]; int i; va_list argument; if ((!*nbpar) || (*nbpar > 100)) { *status = PLD_INVAL; if (verbose) { fprintf(stderr,"[extractpixel]: "); polder_error(*status); } return; } /* decodage de la liste des parametres */ va_start(argument,nbpar); for (i=0;i<*nbpar;i++) { type[i] = va_arg(argument,int*); } for (i=*nbpar;i<100;i++) type[i] = (int*) malloc(sizeof(int)); va_end(argument); *status = ExtractPixel(*id,*line,*column,val,*nbpar, *type[0],*type[1],*type[2],*type[3],*type[4],*type[5],*type[6],*type[7],*type[8],*type[9], *type[10],*type[11],*type[12],*type[13],*type[14],*type[15],*type[16],*type[17],*type[18],*type[19], *type[20],*type[21],*type[22],*type[23],*type[24],*type[25],*type[26],*type[27],*type[28],*type[29], *type[30],*type[31],*type[32],*type[33],*type[34],*type[35],*type[36],*type[37],*type[38],*type[39], *type[40],*type[41],*type[42],*type[43],*type[44],*type[45],*type[46],*type[47],*type[48],*type[49], *type[50],*type[51],*type[52],*type[53],*type[54],*type[55],*type[56],*type[57],*type[58],*type[59], *type[60],*type[61],*type[62],*type[63],*type[64],*type[65],*type[66],*type[67],*type[68],*type[69], *type[70],*type[71],*type[72],*type[73],*type[74],*type[75],*type[76],*type[77],*type[78],*type[79], *type[80],*type[81],*type[82],*type[83],*type[84],*type[85],*type[86],*type[87],*type[88],*type[89], *type[90],*type[91],*type[92],*type[93],*type[94],*type[95],*type[96],*type[97],*type[98],*type[99] ); for (i=*nbpar;i<100;i++) free(type[i]); return; } void EXTRACTNEXTPIXEL_F77(int * status,int* id, int *line, int *column, void* val, int *nbpar, ...) { /* be careful : in fortran , exchange maximum 100 parameters */ int *type[100]; int i; va_list argument; if ((!*nbpar) || (*nbpar > 100)) { *status = PLD_INVAL; if (verbose) { fprintf(stderr,"[extractnextpixel]: "); polder_error(*status); } return; } /* decodage de la liste des parametres */ va_start(argument,nbpar); for (i=0;i<*nbpar;i++) { type[i] = va_arg(argument,int*); } for (i=*nbpar;i<100;i++) type[i] = (int*) malloc(sizeof(int)); va_end(argument); *status = ExtractNextPixel(*id,line,column,val,*nbpar, *type[0],*type[1],*type[2],*type[3],*type[4],*type[5],*type[6],*type[7],*type[8],*type[9], *type[10],*type[11],*type[12],*type[13],*type[14],*type[15],*type[16],*type[17],*type[18],*type[19], *type[20],*type[21],*type[22],*type[23],*type[24],*type[25],*type[26],*type[27],*type[28],*type[29], *type[30],*type[31],*type[32],*type[33],*type[34],*type[35],*type[36],*type[37],*type[38],*type[39], *type[40],*type[41],*type[42],*type[43],*type[44],*type[45],*type[46],*type[47],*type[48],*type[49], *type[50],*type[51],*type[52],*type[53],*type[54],*type[55],*type[56],*type[57],*type[58],*type[59], *type[60],*type[61],*type[62],*type[63],*type[64],*type[65],*type[66],*type[67],*type[68],*type[69], *type[70],*type[71],*type[72],*type[73],*type[74],*type[75],*type[76],*type[77],*type[78],*type[79], *type[80],*type[81],*type[82],*type[83],*type[84],*type[85],*type[86],*type[87],*type[88],*type[89], *type[90],*type[91],*type[92],*type[93],*type[94],*type[95],*type[96],*type[97],*type[98],*type[99] ); for (i=*nbpar;i<100;i++) free(type[i]); return; } void EXTRACTPIXELDQX_F77(int * status,int* id, int *line, int *column, unsigned short int * val, int *nbpar, ...) { /* be careful : in fortran , exchange maximum 100 parameters */ int *type[100]; int i; va_list argument; if ((!*nbpar) || (*nbpar > 100)) { *status = PLD_INVAL; if (verbose) { fprintf(stderr,"[extractpixeldqx]: "); polder_error(*status); } return; } /* decodage de la liste des parametres */ va_start(argument,nbpar); for (i=0;i<*nbpar;i++) { type[i] = va_arg(argument,int*); } for (i=*nbpar;i<100;i++) type[i] = (int*) malloc(sizeof(int)); va_end(argument); * status = ExtractPixelDQX(*id,*line,*column,val,*nbpar, *type[0],*type[1],*type[2],*type[3],*type[4],*type[5],*type[6],*type[7],*type[8],*type[9], *type[10],*type[11],*type[12],*type[13],*type[14],*type[15],*type[16],*type[17],*type[18],*type[19], *type[20],*type[21],*type[22],*type[23],*type[24],*type[25],*type[26],*type[27],*type[28],*type[29], *type[30],*type[31],*type[32],*type[33],*type[34],*type[35],*type[36],*type[37],*type[38],*type[39], *type[40],*type[41],*type[42],*type[43],*type[44],*type[45],*type[46],*type[47],*type[48],*type[49], *type[50],*type[51],*type[52],*type[53],*type[54],*type[55],*type[56],*type[57],*type[58],*type[59], *type[60],*type[61],*type[62],*type[63],*type[64],*type[65],*type[66],*type[67],*type[68],*type[69], *type[70],*type[71],*type[72],*type[73],*type[74],*type[75],*type[76],*type[77],*type[78],*type[79], *type[80],*type[81],*type[82],*type[83],*type[84],*type[85],*type[86],*type[87],*type[88],*type[89], *type[90],*type[91],*type[92],*type[93],*type[94],*type[95],*type[96],*type[97],*type[98],*type[99] ); for (i=*nbpar;i<100;i++) free(type[i]); } void EXTRACTBLOCK_F77(int * status,int *id, int *lineN, int *colW, int *lineS, int *colE, void *val,int *fmt, int *nbpar, ...) { /* be careful : in fortran , exchange maximum 100 parameters */ int *type[100]; int i; va_list argument; if ((!*nbpar) || (*nbpar > 100)) { *status = PLD_INVAL; if (verbose) { fprintf(stderr,"[extractblock]: "); polder_error(*status); } return; } /* decode parameters list */ va_start(argument,nbpar); for (i=0;i<*nbpar;i++) { type[i] = va_arg(argument,int*); } for (i=*nbpar;i<100;i++) type[i] = (int*) malloc(sizeof(int)); va_end(argument); * status = ExtractBlock(*id, *lineN, *colW, *lineS, *colE, val, *fmt,*nbpar, *type[0],*type[1],*type[2],*type[3],*type[4],*type[5],*type[6],*type[7],*type[8],*type[9], *type[10],*type[11],*type[12],*type[13],*type[14],*type[15],*type[16],*type[17],*type[18],*type[19], *type[20],*type[21],*type[22],*type[23],*type[24],*type[25],*type[26],*type[27],*type[28],*type[29], *type[30],*type[31],*type[32],*type[33],*type[34],*type[35],*type[36],*type[37],*type[38],*type[39], *type[40],*type[41],*type[42],*type[43],*type[44],*type[45],*type[46],*type[47],*type[48],*type[49], *type[50],*type[51],*type[52],*type[53],*type[54],*type[55],*type[56],*type[57],*type[58],*type[59], *type[60],*type[61],*type[62],*type[63],*type[64],*type[65],*type[66],*type[67],*type[68],*type[69], *type[70],*type[71],*type[72],*type[73],*type[74],*type[75],*type[76],*type[77],*type[78],*type[79], *type[80],*type[81],*type[82],*type[83],*type[84],*type[85],*type[86],*type[87],*type[88],*type[89], *type[90],*type[91],*type[92],*type[93],*type[94],*type[95],*type[96],*type[97],*type[98],*type[99] ); for (i=*nbpar;i<100;i++) free(type[i]); }