Merge branch 'release-v4.6.0'
[WPS.git] / geogrid / src / read_geogrid.c
blob219f8e993e30e2b441d24589dda75e79dd4381c2
1 /* File: read_geogrid.c
3 Sample subroutine to read an array from the geogrid binary format.
5 Notes: Depending on the compiler and compiler flags, the name of
6 the read_geogrid() routine may need to be adjusted with respect
7 to the number of trailing underscores when calling from Fortran.
9 Michael G. Duda, NCAR/MMM
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
16 #ifdef _UNDERSCORE
17 #define read_geogrid read_geogrid_
18 #endif
19 #ifdef _DOUBLEUNDERSCORE
20 #define read_geogrid read_geogrid__
21 #endif
23 #define BIG_ENDIAN 0
24 #define LITTLE_ENDIAN 1
26 int read_geogrid(
27 char * fname, /* The name of the file to read from */
28 int * len, /* The length of the filename */
29 float * rarray, /* The array to be filled */
30 int * nx, /* x-dimension of the array */
31 int * ny, /* y-dimension of the array */
32 int * nz, /* z-dimension of the array */
33 int * isigned, /* 0=unsigned data, 1=signed data */
34 int * endian, /* 0=big endian, 1=little endian */
35 float * scalefactor, /* value to multiply array elements by before truncation to integers */
36 int * wordsize, /* number of bytes to use for each array element */
37 int * status)
39 size_t i, cnt, narray;
40 int ival;
41 int A2, B2;
42 int A3, B3, C3;
43 int A4, B4, C4, D4;
44 unsigned char * c;
45 char local_fname[1024];
46 FILE * bfile;
48 *status = 0;
50 narray = (size_t)(*nx) * (size_t)(*ny) * (size_t)(*nz);
52 /* Make a null-terminated local copy of the filename */
53 strncpy(local_fname,fname,*len);
54 local_fname[*len]='\0';
56 /* Attempt to open file for reading */
57 if (!(bfile = fopen(local_fname,"rb")))
59 *status = 1;
60 return 1;
63 /* Allocate memory to hold bytes from file and read data */
64 c = (unsigned char *)malloc(sizeof(unsigned char)*(*wordsize) * narray);
65 cnt = fread((void *)c, sizeof(unsigned char), narray*(size_t)(*wordsize), bfile);
67 fclose(bfile);
69 if (cnt == 0)
71 *status = 1;
72 return 1;
75 /*
76 Set up byte offsets for each wordsize depending on byte order.
77 A, B, C, D give the offsets of the LSB through MSB (i.e., for
78 word ABCD, A=MSB, D=LSB) in the array from the beginning of a word
80 if (*endian == BIG_ENDIAN) {
81 A2 = 0; B2 = 1;
82 A3 = 0; B3 = 1; C3 = 2;
83 A4 = 0; B4 = 1; C4 = 2; D4 = 3;
85 else {
86 B2 = 0; A2 = 1;
87 C3 = 0; B3 = 1; A3 = 2;
88 D4 = 0; C4 = 1; B4 = 2; A4 = 3;
91 /* Convert words from native byte order */
92 switch(*wordsize) {
93 case 1:
94 for(i=0; i<narray; i++)
96 ival = (int)(c[i]);
97 if ((*isigned) && (ival > (1 << 7))) ival -= (1 << 8);
98 rarray[i] = (float)ival;
100 break;
102 case 2:
103 for(i=0; i<narray; i++)
105 ival = (int)((c[2*i+A2]<<8) | (c[2*i+B2]));
106 if ((*isigned) && (ival > (1 << 15))) ival -= (1 << 16);
107 rarray[i] = (float)ival;
109 break;
111 case 3:
112 for(i=0; i<narray; i++)
114 ival = (int)((c[3*i+A3]<<16) | (c[3*i+B3]<<8) | c[3*i+C3]);
115 if ((*isigned) * (ival > (1 << 23))) ival -= (1 << 24);
116 rarray[i] = (float)ival;
118 break;
120 case 4:
121 for(i=0; i<narray; i++)
123 ival = (int)((c[4*i+A4]<<24) | (c[4*i+B4]<<16) | (c[4*i+C4]<<8) | c[4*i+D4]);
124 if ((*isigned) && (ival > (1 << 31))) ival -= (1 << 32);
125 rarray[i] = (float)ival;
127 break;
130 free(c);
132 /* Scale real-valued array by scalefactor */
133 if (*scalefactor != 1.0)
135 for (i=0; i<narray; i++)
136 rarray[i] = rarray[i] * (*scalefactor);
139 return 0;