OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
smitoppm.c
Go to the documentation of this file.
1 /* ========================================================================
2  * smitoppm - converts any SeaWiFS SMI map file to a ppm file
3  *
4  * Synopsis:
5  *
6  * smitoppm input-smi-filename > output-ppm-filename
7  *
8  * Description:
9  *
10  * Uses the SeaWiFS L3_Mapfiles interface to read the byte-scaled image and
11  * palette. Uses the bytescaled image to index into the palette, and writes
12  * a three-color image to standard output. The filename, product type,
13  * binning period, and other relevant meta-data are stored in the ppm file
14  * header as ascii comments.
15  *
16  * Modification history:
17  *
18  * Programmer Organization Date Description of change
19  * -------------- ------------ -------- ---------------------
20  * Bryan A. Franz GSC 10/06/97 Original development
21  * Joel M. Gales Futuretech 09/04/01 Support non-standard
22  * smi maps
23  * Joel M. Gales Futuretech 05/14/10 Don't get quality for
24  * HDF5 files & use datasize
25  * instead of datatype for
26  * non-byte processing.
27  * Joel M. Gales Futuretech 09/21/11 Add support for arctan
28  * scaling (SSS)
29  * Joel M. Gales Futuretech 06/14/13 Add support for NETCDF4
30  *
31  * Joel M. Gales Futuretech 09/27/13 Removed netcdf code
32  * HDF5 calls can be used
33  * for NETCDF4 files
34  * ======================================================================== */
35 
36 #include <stdio.h>
37 #include <unistd.h>
38 
39 typedef unsigned char byte;
40 #include "netcdf.h"
41 #include "map.h"
42 #include "mapproto_o.h"
43 #include "hdf5.h"
44 #include "mapproto.h"
45 
46 #include <math.h>
47 
48 #define NX 4096 /* Map grid x-dimension */
49 #define NY 2048 /* Map grid y-dimension */
50 #define MAXSTRNGLEN 255 /* Max generic string length */
51 
52 #define CMD_ARGS "b:w:s" /* Valid commandline options */
53 
54 #define VERSION "3.4"
55 
56 /* ------------------------------------------------------------------------- *
57  * usage - display proper calling sequence for this program *
58  * ------------------------------------------------------------------------- */
59 void usage(char *progname) {
60  fprintf(stderr, "%s %s (%s %s)\n", progname, VERSION, __DATE__, __TIME__);
61  fprintf(stderr, "\nUsage: %s input-smi-filename > output-ppm-filename",
62  progname);
63  fprintf(stderr, "\n");
64 
65 }
66 
67 /* ------------------------------------------------------------------------ *
68  * main *
69  * ------------------------------------------------------------------------ */
70 int main(int argc, char *argv[]) {
71 
72  int32 ix; /* Longitudinal bin index */
73  int32 iy; /* Latitudinal bin index */
74  int32 ic; /* Color bin index */
75  /* byte rgb[NY][NX][3];*/ /* Three-color image array */
76  byte *rgb; /* Three-color image array */
77 
78  int16 syear;
79  int16 sday;
80  int32 smsec;
81  int16 eyear;
82  int16 eday;
83  int32 emsec;
84  int32 status;
85  int32 nrows;
86  int32 ncols;
87  size_t datasize;
88 
89  char prod_type[MAXSTRNGLEN];
90  char l3m_name[MAXSTRNGLEN];
91 
92  /* byte image[NY][NX];*/
93  byte *image = NULL;
94  byte *quality;
95  byte palette[3 * 256];
96  meta_struct meta_l3m;
97 
98  uint16 ui16;
99  uint8 best = 0, worst = 254;
100  uint8 bio = 0;
101  float32 flt32;
102 
103  uint16 fill_val_int16 = 65535;
104  float32 fill_val_float = -32767.0;
105 
106  int maxval = 254;
107  int islog = 0;
108  int isatan = 0;
109  double slope;
110  double intercept;
111 
112  /* Parameters for getopt() */
113  extern int opterr;
114  extern int optind;
115  extern char *optarg;
116  int c;
117 
118  if (argc == 1) {
119  usage("smitoppm");
120  return 0;
121  }
122 
123  /* Process optional command-line arguments */
124  while ((c = getopt(argc, argv, CMD_ARGS)) != EOF) {
125  switch (c) {
126  case 'b':
127  best = atoi(optarg);
128  break;
129  case 'w':
130  worst = atoi(optarg);
131  break;
132  case 's':
133  bio = 1;
134  break;
135  }
136  }
137 
138  /*
139  * Read SMI palette and meta-data
140  */
141  status = get_l3m(argv[optind],
142  &syear, &sday, &smsec,
143  &eyear, &eday, &emsec,
144  prod_type, NULL,
145  NULL, palette, &meta_l3m);
146 
147  if (status < 0) {
148  fprintf(stderr, "%s: Error accessing %s as L3 SMI file\n",
149  argv[0], argv[optind]);
150  exit(1);
151  }
152 
153  nrows = meta_l3m.nrows;
154  ncols = meta_l3m.ncols;
155 
156 
157  if (H5Fis_hdf5(argv[optind])) {
158  if (H5Tget_size(meta_l3m.bintype) == 1) {
159  image = (byte *) calloc(nrows*ncols, sizeof (byte));
160  datasize = 1;
161  } else if (H5Tget_size(meta_l3m.bintype) == 2) {
162  image = (byte *) calloc(nrows*ncols, 2 * sizeof (byte));
163  datasize = 2;
164  } else if (H5Tget_size(meta_l3m.bintype) == 4) {
165  image = (byte *) calloc(nrows*ncols, 4 * sizeof (byte));
166  datasize = 4;
167  /*
168  fprintf(stderr,"PPM file cannot be generated from FLOAT L3m file.\n");
169  exit(-1);
170  */
171  }
172  } else {
173  if (meta_l3m.bintype == DFNT_UINT8) {
174  image = (byte *) calloc(nrows*ncols, sizeof (byte));
175  datasize = 1;
176  } else if (meta_l3m.bintype == DFNT_UINT16) {
177  image = (byte *) calloc(nrows*ncols, 2 * sizeof (byte));
178  datasize = 2;
179  } else if (meta_l3m.bintype == DFNT_FLOAT32) {
180  image = (byte *) calloc(nrows*ncols, 4 * sizeof (byte));
181  datasize = 4;
182  /*
183  printf("PPM file cannot be generated from FLOAT L3m file.\n");
184  exit(-1);
185  */
186  }
187  }
188 
189  rgb = (byte *) calloc(nrows * ncols * 3, sizeof (byte));
190  quality = (byte *) calloc(nrows*ncols, sizeof (byte));
191 
192  /*
193  * Read SMI image
194  */
195  status = get_l3m(argv[optind],
196  &syear, &sday, &smsec,
197  &eyear, &eday, &emsec,
198  prod_type, "l3m_name",
199  &image[0], NULL, NULL);
200 
201  if (status < 0) {
202  fprintf(stderr, "%s: Error accessing %s as L3 SMI file\n",
203  argv[0], argv[optind]);
204  exit(1);
205  }
206 
207  status = get_l3m(argv[optind],
208  &syear, &sday, &smsec,
209  &eyear, &eday, &emsec,
210  prod_type, "l3m_qual",
211  &quality[0], NULL, NULL);
212 
213  if (status < 0) {
214  best = 0;
215  worst = 254;
216  }
217 
218  if (datasize == 2) {
219 
220  for (iy = 0; iy < nrows; iy++) {
221  for (ix = 0; ix < ncols; ix++) {
222 
223  memcpy(&ui16, &image[2 * (iy * ncols + ix)], 2);
224 
225  if (ui16 == fill_val_int16)
226  image[iy * ncols + ix] = 255;
227  else {
228  if (bio) {
229  image[iy * ncols + ix] = (byte) (ui16 / 256);
230  if (ui16 == 32767) image[iy * ncols + ix] = 128;
231  } else if (strcmp(l3m_name, "Number of pixels per bin") == 0) {
232  image[iy * ncols + ix] =
233  (byte) (255 * (ui16 - meta_l3m.scaled_data_min) /
234  (meta_l3m.scaled_data_max - meta_l3m.scaled_data_min));
235  } else {
236  image[iy * ncols + ix] = (byte) (250 * ui16 / 65534);
237  }
238  }
239  } // col loop
240  } // row loop
241 
242  } else if (datasize == 4) {
243 
244  if (strcmp(meta_l3m.scaled_data_type, "LOG") == 0) {
245  islog = 1;
246  intercept = log10(meta_l3m.scaled_data_min);
247  slope = (log10(meta_l3m.scaled_data_max) - intercept) / maxval;
248  } else if (strcmp(meta_l3m.scaled_data_type, "ATAN") == 0) {
249  isatan = 1;
250  intercept = 17.5;
251  slope = 125.0;
252  } else {
253  intercept = meta_l3m.scaled_data_min;
254  slope = (meta_l3m.scaled_data_max - intercept) / maxval;
255  }
256  for (iy = 0; iy < nrows; iy++) {
257  for (ix = 0; ix < ncols; ix++) {
258 
259  memcpy(&flt32, &image[4 * (iy * ncols + ix)], 4);
260 
261  if (flt32 < (fill_val_float + 1E-5))
262  image[iy * ncols + ix] = 255;
263  else if (flt32 <= meta_l3m.scaled_data_min)
264  image[iy * ncols + ix] = (uint8) 0;
265  else if (flt32 >= meta_l3m.scaled_data_max)
266  image[iy * ncols + ix] = (uint8) maxval;
267  else {
268  if (islog)
269  image[iy * ncols + ix] = (uint8) ((log10(flt32) - intercept) / slope);
270  else if (isatan)
271  image[iy * ncols + ix] = (uint8) slope * ((atan(0.5 * flt32 - intercept) / atan(intercept)) + 1);
272  else
273  image[iy * ncols + ix] = (uint8) ((flt32 - intercept) / slope);
274  }
275  }
276  }
277  }
278 
279 
280  /*
281  * Convert from greyscale and palette to rgb array
282  */
283  for (iy = 0; iy < nrows; iy++)
284  for (ix = 0; ix < ncols; ix++)
285  for (ic = 0; ic < 3; ic++)
286  rgb[iy * (ncols * 3) + ix * 3 + ic] =
287  palette[image[iy * ncols + ix] * 3 + ic ];
288 
289 
290  /* Quality Filtering */
291  /* ----------------- */
292  for (iy = 0; iy < nrows; iy++)
293  for (ix = 0; ix < ncols; ix++)
294  if ((quality[iy * ncols + ix] < best) ||
295  (quality[iy * ncols + ix] > worst))
296  for (ic = 0; ic < 3; ic++)
297  rgb[iy * (ncols * 3) + ix * 3 + ic] =
298  palette[255 * 3 + ic ];
299 
300 
301  /*
302  * Write output ppm file
303  */
304  printf("P6\n");
305  printf("# File: %s\n", argv[optind]);
306  printf("# Dataset: %s\n", l3m_name);
307  printf("# Bin Period: %s\n", prod_type);
308  printf("# Start Time: %d %d %d\n", syear, sday, smsec);
309  printf("# End Time: %d %d %d\n", eyear, eday, emsec);
310  printf("%d\n", ncols);
311  printf("%d\n", nrows);
312  printf("255\n");
313  fwrite(&rgb[0], 1, ncols * nrows * 3, stdout);
314 
315  free(image);
316  free(quality);
317  free(rgb);
318 
319  exit(0);
320 }
321 
322 
323 
324 
int32_t bintype
Definition: map.h:79
integer, parameter int16
Definition: cubeio.f90:3
#define VERSION
Definition: smitoppm.c:54
int16 eday
Definition: l1_czcs_hdf.c:17
char * scaled_data_type
Definition: map.h:76
int status
Definition: l1_czcs_hdf.c:32
int main(int argc, char *argv[])
Definition: smitoppm.c:70
#define NULL
Definition: decode_rs.h:63
unsigned char byte
Definition: smitoppm.c:39
int32_t nrows
Definition: map.h:64
int16 eyear
Definition: l1_czcs_hdf.c:17
int syear
Definition: l1_czcs_hdf.c:15
int32 smsec
Definition: l1_czcs_hdf.c:16
int sday
Definition: l1_czcs_hdf.c:15
float scaled_data_max
Definition: map.h:75
int32_t ncols
Definition: map.h:65
make_L3 README txt Compiling set environment variables for HDBLIB and HDFINC to the appropriate HDF4 lib and include directories make_L3_v1 c o make_L3 LIB lib a I LIB I $HDFINC L $HDFLIB lmfhdf ldf lz ljpeg lm lmalloc Running make_L3 takes input from standard so the SeaWIFS level files should be piped to the program via the command line as in to be allocated by the program to buffer the compositing The the better Ideally it should be to fit the entire global image(with all the layers) at once. Otherwise the process will be buffered on disk. -bufstep
float32 slope[]
Definition: l2lists.h:30
#define MAXSTRNGLEN
Definition: smitoppm.c:50
void usage(char *progname)
Definition: smitoppm.c:59
int32 nrows
float32 intercept[]
Definition: l2lists.h:44
int32_t get_l3m(char *l3m_path, int16_t *syear, int16_t *sday, int32_t *smsec, int16_t *eyear, int16_t *eday, int32_t *emsec, char *prod_type, char *l3m_name, uint8_t *l3m_data, unsigned char *palette, meta_struct *meta_l3m)
Definition: get_l3m.c:72
int32 emsec
Definition: l1_czcs_hdf.c:18
#define CMD_ARGS
Definition: smitoppm.c:52
int16 ncols[121]
float scaled_data_min
Definition: map.h:74
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464