sandbox/nlemoine/esri-binary-grids.h
output_flt(): ESRI Binary Float Grid (.FLT,.HDR) format
The Esri Binary Float Grid format consists of 2 files: a binary .FLT image file and ASCII .HDR header file with the same file name but different file extension. For example, Test.FLT and Test.HDR.
The arguments are:
- f
- a scalar field (compulsory).
- file
- an array of char, path to the output file (with .FLT extension)
- \Delta
- size of a grid element. Default is 1/N.
- linear
- whether to use bilinear or first-order interpolation. Default is first-order.
- box
- the lower-left and upper-right coordinates of the domain to consider. Default is the entire domain.
- mask
- if set, this field will be used to mask out, the regions of the domain for which mask is negative.
struct OutputFLT {
scalar f;
char * file;
double Delta;
bool linear;
double box[2][2];
scalar mask;
};
trace
int output_flt (struct OutputFLT p)
{
FILE * flt , * hdr ;
scalar input = p.f;
char * pch;
char buffer[100];
double * data_double;
char hdrfile[200];
// default values
if (p.box[0][0] == 0. && p.box[0][1] == 0. &&
.box[1][0] == 0. && p.box[1][1] == 0.) {
p.box[0][0] = X0; p.box[0][1] = Y0;
p.box[1][0] = X0 + L0; p.box[1][1] = Y0 + L0;
pif (p.Delta == 0) p.Delta = L0/N;
}
double Delta = p.Delta;
int nx = (p.box[1][0] - p.box[0][0])/Delta;
int ny = (p.box[1][1] - p.box[0][1])/Delta;
= (double *)malloc(nx*ny*sizeof(double));
data_double for(int i=0;i<(nx*ny);i++)
[i] = nodata;
data_double
// data
for (int j = ny-1; j >= 0; j--) {
double yp = Delta*j + p.box[0][1] + Delta/2.; // center of pixel
for (int i = 0; i < nx; i++) {
double xp = Delta*i + p.box[0][0] + Delta/2., v;
float vf;
if (p.mask.i) { // masking
if (p.linear) {
double m = interpolate (p.mask, xp, yp);
if (m < 0.)
= nodata;
v
else= interpolate (p.f, xp, yp);
v }
else {
= locate (xp, yp);
Point point if (point.level < 0 || val(p.mask) < 0.)
= nodata;
v
else= val(p.f);
v }
}
else if (p.linear)
= interpolate (p.f, xp, yp);
v else {
= locate (xp, yp);
Point point = point.level >= 0 ? val(p.f) : nodata;
v }
if (v == nodata)
[i+(ny-1-j)*nx] = -9999.;
data_double
else[i+(ny-1-j)*nx] = v;
data_double
}
}
if (pid() == 0) { // master writes .FLT and .HDR files
@if _MPI(MPI_IN_PLACE, data_double, nx*ny, MPI_DOUBLE, MPI_MAX, 0,
MPI_Reduce );
MPI_COMM_WORLD
@endif
// Set path to header file
// hdrfile = (char *)malloc(sizeof(char)*strlen(p.file));
(hdrfile,p.file);
strcpy
= hdrfile + strlen(hdrfile)-3;
pch // strncpy (pch,"hdr",3);
(pch,"hdr",3);
memcpy
if(!(hdr = fopen (hdrfile, "w")))
{
printf("Failed to open header file %s\n",hdrfile);
return -1;
}
// header
fprintf (hdr, "ncols %d\n", nx);
fprintf (hdr, "nrows %d\n", ny);
fprintf (hdr, "xllcorner %.8g\n", p.box[0][0]);
fprintf (hdr, "yllcorner %.8g\n", p.box[0][1]);
fprintf (hdr, "cellsize %.8g\n", Delta);
fprintf (hdr, "nodata_value -9999\n");
fprintf (hdr, "byteorder LSBFIRST\n");
fflush(hdr);
fclose(hdr);
// free(hdrfile);
// open flt file
bool opened = false;
if( !(flt = fopen (p.file, "wb")) ) {
(p.file);
perror exit(1);
}
else= true;
opened
for(int i=0;i<(nx*ny);i++)
{
float vf = (float)data_double[i];
(&vf,1,sizeof(float),flt);
fwrite}
fclose(flt);
}
@if _MPIelse // slave does not write anything
(data_double, NULL, nx*ny, MPI_DOUBLE, MPI_MAX, 0,
MPI_Reduce );
MPI_COMM_WORLD
@endif
free(data_double);
return(0);
}
int SYSTEM_IS_LITTLE_ENDIAN(void)
{
// First, we declare a 16-bit integer (short int), which has the value 0x0001
short int word = 0x0001;
// then we get a pointer and dereference it
char *b = (char *)&word;
// If the LSB is stored at lower address (e.g. the value that pointer points to), then system is LSBFIRST i.e. Litte Endian
return (b[0] ? 1 : 0);
}
float ReverseFloat( float inFloat )
{
float retVal;
char *floatToConvert = ( char* ) & inFloat;
char *returnFloat = ( char* ) & retVal;
// swap the bytes into a temporary buffer
[0] = floatToConvert[3];
returnFloat[1] = floatToConvert[2];
returnFloat[2] = floatToConvert[1];
returnFloat[3] = floatToConvert[0];
returnFloat
return retVal;
}
void lower_string(char s[]) {
int c = 0;
while (s[c] != '\0') {
if (s[c] >= 'A' && s[c] <= 'Z') {
[c] = s[c] + 32;
s}
++;
c}
}
input_flt(): ESRI Binary Float Grid (.FLT,.HDR) format
The Esri Binary Float Grid format consists of 2 files: a binary .FLT image file and ASCII .HDR header file with the same file name but different file extension. For example, Test.FLT and Test.HDR. http://surferhelp.goldensoftware.com/subsys/subsys_ESRI_binary_float_grid_file_descr.htm This is the reciprocal function of output_flt().
The arguments and their default values are:
- s
- the scalar where the data will be stored. No default value. You must specify this parameter
- file
- the name of the file to read from. The path to the header file is assumed to be the same as the binary file with the extension “.hdr”
- nodatavalue
- the value of the NoDataValue. Default is the same as that defined in the raster file.
- linear
- if true, the raster data is bilinearly interpolated. Default is false.
struct InputFLT {
scalar s;
char * file;
double nodatavalue;
bool linear;
};
int input_flt (struct InputFLT p)
{
FILE * flt , * hdr ;
scalar input = p.s;
char * hdrfile, * pch;
char buffer[100];
double DeltaGRD;
int nx, ny,i,j;
double XG0, YG0, ndv,center,dx,dy;
bool lsbfirst,reverse_bytes;
float f;
// Get path to header file
= (char *)malloc(sizeof(char)*strlen(p.file));
hdrfile (hdrfile,p.file);
strcpy
= hdrfile + strlen(hdrfile)-3;
pch (pch,"hdr",3);
strncpy
if(!(hdr = fopen (hdrfile, "r")))
{
printf("Failed to open header file %s\n",hdrfile);
return -1;
}
// Parse header file
while(fscanf(hdr,"%s",buffer)!=EOF)
{
lower_string(buffer);
if(!(strcmp(buffer,"ncols")))
fscanf(hdr,"%d",& nx);
if(!(strcmp(buffer,"nrows")))
fscanf(hdr,"%d",& ny);
if(!(strcmp(buffer,"cellsize")))
fscanf(hdr,"%lf",& DeltaGRD);
if(!(strcmp(buffer,"xllcenter")))
{
fscanf(hdr,"%lf",& XG0);
=1.0;
center}
if(!(strcmp(buffer,"yllcenter")))
{
fscanf(hdr,"%lf",& YG0);
=1.0;
center}
if(!(strcmp(buffer,"xllcorner")))
{
fscanf(hdr,"%lf",& XG0);
=0.0;
center}
if(!(strcmp(buffer,"yllcorner")))
{
fscanf(hdr,"%lf",& YG0);
=0.0;
center}
if(!(strcmp(buffer,"nodata_value")))
fscanf(hdr,"%lf",& ndv);
if(!(strcmp(buffer,"byteorder")))
{
fscanf(hdr,"%s",buffer);
lower_string(buffer);
= !strcmp(buffer,"lsbfirst");
lsbfirst }
}
-= 0.5*DeltaGRD*center;
XG0 -= 0.5*DeltaGRD*center;
YG0
fclose(hdr);
bool opened = false;
if( !(flt = fopen (p.file, "rb")) ) {
(p.file);
perror exit(1);
}
else= true;
opened
//default value of NoData value
if (!p.nodatavalue)
.nodatavalue = ndv;
p
// Allocation of pointers to columns' start (size : nx)
double ** value ;
if( !(value = (double **) malloc(nx*sizeof(double *)) ) )
return(-1);
// Allocation of each column (each of size ny)
for(i=0;i<nx;i++)
{
if ( !(value[i] = (double *) malloc(ny*sizeof(double)) ) )
return(-1);
}
// read the data (float to double conversion and byte reverse if necessary)
if ( ( lsbfirst && !SYSTEM_IS_LITTLE_ENDIAN() ) |
( !lsbfirst && SYSTEM_IS_LITTLE_ENDIAN() ) )
= true;
reverse_bytes
else= false;
reverse_bytes
for(j = ny-1; j >= 0; j--){
for(i = 0 ; i < nx; i++){
(&f,sizeof(float),1,flt);
freadif (reverse_bytes)
= ReverseFloat(f);
f [i][j] = f ;
value}}
printf(" %d values read\n",nx*ny);
double LGx0 = nx*DeltaGRD;
double LGy0 = ny*DeltaGRD;
bool warning = false;
bool internal,incl;
double val;
double onehalf=1./2.;
double xllcenter = XG0+DeltaGRD/2., yllcenter = YG0+DeltaGRD/2.;
foreach() {
= (x - xllcenter)/DeltaGRD ; // relative offset in x w.r.t. center of LL pixel
dx = (int)floor(dx);
i
= (y - yllcenter)/DeltaGRD ; // relative offset in y w.r.t. center of LL pixel
dy = (int)floor(dy);
j
= (i >= 0 &&
internal < nx-1 &&
i >= 0 &&
j < ny-1 );
j
if (p.linear && internal ) { // bi-linear interpolation
-= i;
dx -= j;
dy
= (1.-dx)*(1.-dy)*value[i][j]
val + dx*(1.-dy)*value[i+1][j]
+ (1.-dx)*dy*value[i][j+1]
+ dx*dy*value[i+1][j+1];
}
else {
// Test if the point in the Basilisk area is included in the raster area
= (x >= XG0 &&
incl <= XG0 + LGx0 &&
x >= YG0 &&
y <= YG0 + LGy0 );
y if(incl) {
// snap relative offsets dx and dy to nearest integers
= (int)(dx+onehalf);
i = (int)(dy+onehalf);
j = value[i][j];
val }
else {
= p.nodatavalue;
val = true;
warning }
}
[] = val ;
input}
// Deallocation of each column
for(i=0;i<nx;i++)
free(value[i]);
// Deallocation of pointers to columns' start
free(value);
free(hdrfile);
if (warning)
fprintf (stderr,
"input_flt(): Warning: Raster data is not covering all"
" the simulation area\n");
fclose (flt);
return(0);
}