NASA Logo
Ocean Color Science Software

ocssw V2022
OutFile.cpp
Go to the documentation of this file.
1 #include <xtiffio.h>
2 #include <geo_normalize.h>
3 
4 #include "OutFile.h"
5 
6 #include <stdio.h>
7 #include <iostream>
8 #include <math.h>
9 #include <timeutils.h>
10 #include <nc4utils.h>
11 #include <string>
12 #include <float.h>
13 #include <regex>
14 
15 #include <hdf.h>
16 #include <mfhdf.h>
17 
18 #include <boost/algorithm/string/trim.hpp>
19 #include <boost/algorithm/string/case_conv.hpp>
20 #include <boost/algorithm/string/predicate.hpp>
21 #include <boost/algorithm/string.hpp>
22 #include <stack>
23 
24 #include <geo_tiffp.h>
25 
26 using namespace std;
27 
28 const std::unordered_map<std::string, std::vector<int32_t>>& get_wv3d_2d_name_to_3d_expansion();
29 const std::unordered_map<std::string, std::string>& get_wv3d_3d_name_to_2d_name();
30 size_t get_len_wv3d();
31 
33  std::vector<std::string> key_words;
34  const std::string delim = " ";
35  boost::split(key_words, long_name_with_wv, boost::is_any_of(delim));
36  const std::string start = "at";
37  const std::string end = "nm";
39  std::string wv_prefix;
40  std::stack<std::string> stack;
41  for (const auto& word : key_words) {
42  if (stack.empty()) {
43  if (word != "at") {
44  if (!out.empty())
45  out += delim;
46  out += word;
47  } else {
48  stack.push(word);
49  }
50  } else {
51  if (word != "nm") {
52  stack.push(word);
53  } else {
54  while (!stack.empty()) {
55  if (!wv_prefix.empty())
56  wv_prefix += delim;
57  wv_prefix += stack.top();
58  stack.pop();
59  }
60  }
61  }
62  }
64  // {
65  // std::cout << "OUT LONG NAME WITHOUT PREFIX " << out << " THE PREFIX "
66  // << wv_prefix << std::endl;
67  // }
68  return out;
69 }
70 
71 //------------------------------------------------------------------------------
72 // OutFile::ProductStuff
73 //------------------------------------------------------------------------------
74 
75 OutFile::ProductStuff::ProductStuff(int32_t width, const productInfo_t* productInfo, double landPixelValue) {
76  this->width = width;
77  this->productInfo = allocateProductInfo();
78  copyProductInfo(this->productInfo, productInfo);
79  dataStorage = UByteDS;
80  scaleType = Linear;
81  scale = 1.0;
82  offset = 0.0;
83  minOutputVal = 0;
84  maxOutputVal = 255;
85  minVal = minOutputVal;
86  maxVal = maxOutputVal;
87  missingValue = fillPix;
88  lineData = (double*)allocateMemory(width * sizeof(double), "OutFile::ProductStuff::lineData");
89  this->landPixelValue = landPixelValue;
90 }
91 
93  width = pStuff.width;
94  productInfo = allocateProductInfo();
95  copyProductInfo(productInfo, pStuff.productInfo);
96  dataStorage = pStuff.dataStorage;
97  scaleType = pStuff.scaleType;
98  scale = pStuff.scale;
99  offset = pStuff.offset;
100  minOutputVal = pStuff.minOutputVal;
101  maxOutputVal = pStuff.maxOutputVal;
102  minVal = pStuff.minVal;
103  maxVal = pStuff.maxVal;
104  missingValue = pStuff.missingValue;
105  lineData = (double*)allocateMemory(width * sizeof(double), "OutFile::ProductStuff::lineData");
106  landPixelValue = pStuff.landPixelValue;
107 }
108 
110  freeProductInfo(productInfo);
111  free(lineData);
112 }
113 
120 void OutFile::ProductStuff::setScale(double min, double max, ScaleType scaleType) {
121  this->scaleType = scaleType;
122  minVal = min;
123  maxVal = max;
124  switch (scaleType) {
125  case Linear:
126  offset = min;
127  scale = (max - offset) / (maxOutputVal - minOutputVal);
128  break;
129  case Log:
130  offset = log10(min);
131  scale = (log10(max) - offset) / (maxOutputVal - minOutputVal);
132  break;
133  case ArcTan:
134  offset = min;
135  scale = max;
136  minVal = calcPhysicalVal(minOutputVal);
137  maxVal = calcPhysicalVal(maxOutputVal);
138  break;
139  default:
140  printf("-E- OutFile::setScale - invalid scaleType = %d\n", (int)scaleType);
141  exit(EXIT_FAILURE);
142  }
143 }
144 
145 void OutFile::ProductStuff::setScale(double min, double max, ScaleType scaleType, double minOutput,
146  double maxOutput) {
147  minOutputVal = minOutput;
148  maxOutputVal = maxOutput;
149  setScale(min, max, scaleType);
150 }
151 
159  this->scaleType = scaleType;
160  this->scale = scale;
161  this->offset = offset;
162 
163  // have to set these so calcPhysicalVal does not limit the physical val
164  minVal = 0 - FLT_MAX;
165  maxVal = FLT_MAX;
166  minVal = calcPhysicalVal(minOutputVal);
167  maxVal = calcPhysicalVal(maxOutputVal);
168 }
169 
170 void OutFile::ProductStuff::setScaleOffset(double scale, double offset, ScaleType scaleType, double minOutput,
171  double maxOutput) {
172  minOutputVal = minOutput;
173  maxOutputVal = maxOutput;
174  setScaleOffset(scale, offset, scaleType);
175 }
176 
178  double outVal;
179 
180  if (val == badPixelValue)
181  return missingValue;
182 
183  if (val == landPixelValue)
184  return landPix;
185 
186  // don't scale if output type is floating point
187  if (dataStorage == FloatDS || dataStorage == DoubleDS)
188  return val;
189 
190  switch (scaleType) {
191  case Linear:
192  outVal = (val - offset) / scale;
193  break;
194  case Log:
195  if (val < 0)
196  return minOutputVal;
197  else
198  outVal = (log10(val) - offset) / scale;
199  break;
200  case ArcTan:
201  outVal = scale * ((atan(0.5 * val - offset) / atan(offset)) + 1);
202  break;
203  default:
204  printf("-E- OutFile::ProductStuff::calcOutputVal - invalid scaleType = %d\n", (int)scaleType);
205  exit(EXIT_FAILURE);
206  }
207 
208  if (outVal < minOutputVal)
209  return minOutputVal;
210  if (outVal > maxOutputVal)
211  return maxOutputVal;
212  return outVal;
213 }
214 
216  double physicalVal;
217 
218  if (val == missingValue)
219  return badPixelValue;
220 
221  // don't scale if out output type is floating point
222  if (dataStorage == FloatDS || dataStorage == DoubleDS)
223  return val;
224 
225  switch (scaleType) {
226  case Linear:
227  physicalVal = val * scale + offset;
228  break;
229  case Log:
230  physicalVal = pow(10, val * scale + offset);
231  break;
232  case ArcTan:
233  physicalVal = (tan((val / scale - 1) * atan(offset)) + offset) / 0.5;
234  break;
235  default:
236  printf("-E- OutFile::ProductStuff::calcPhysicalVal - invalid scaleType = %d\n", (int)scaleType);
237  exit(EXIT_FAILURE);
238  }
239 
240  if (physicalVal < minVal)
241  return minVal;
242  if (physicalVal > maxVal)
243  return maxVal;
244  return physicalVal;
245 }
246 
247 void OutFile::ProductStuff::calcOutputLineVals(void* lineBuffer) const {
248  switch (dataStorage) {
249  case ByteDS:
250  for (int i = 0; i < width; i++)
251  ((int8_t*)lineBuffer)[i] = round(calcOutputVal(lineData[i]));
252  break;
253  case UByteDS:
254  for (int i = 0; i < width; i++)
255  ((uint8_t*)lineBuffer)[i] = round(calcOutputVal(lineData[i]));
256  break;
257  case ShortDS:
258  for (int i = 0; i < width; i++)
259  ((int16_t*)lineBuffer)[i] = round(calcOutputVal(lineData[i]));
260  break;
261  case UShortDS:
262  for (int i = 0; i < width; i++)
263  ((uint16_t*)lineBuffer)[i] = round(calcOutputVal(lineData[i]));
264  break;
265  case IntDS:
266  for (int i = 0; i < width; i++)
267  ((int32_t*)lineBuffer)[i] = round(calcOutputVal(lineData[i]));
268  break;
269  case UIntDS:
270  for (int i = 0; i < width; i++)
271  ((uint32_t*)lineBuffer)[i] = round(calcOutputVal(lineData[i]));
272  break;
273  case FloatDS:
274  for (int i = 0; i < width; i++)
275  ((float*)lineBuffer)[i] = lineData[i];
276  break;
277  case DoubleDS:
278  for (int i = 0; i < width; i++)
279  ((double*)lineBuffer)[i] = lineData[i];
280  break;
281  default:
282  printf("-E- OutFile::ProductStuff::calcOutputLineVals - unrecognized data type = %d\n",
283  dataStorage);
284  exit(EXIT_FAILURE);
285  }
286 }
287 
288 //------------------------------------------------------------------------------
289 // OutFile
290 //------------------------------------------------------------------------------
291 
293  landPixelValue = -32766.0;
294  width = 0;
295  height = 0;
296  qualityData = NULL;
297  currentLine = 0;
298  colorType = Grayscale;
299  fileMinVal = DBL_MAX;
300  fileMaxVal = 0 - DBL_MAX;
301  resolution = 0;
302  deflate = 0;
303  fullLatLon = LatLon2D;
304  latData = NULL;
305  lonData = NULL;
306 
307  red = (uint8_t*)allocateMemory(256, "red");
308  green = (uint8_t*)allocateMemory(256, "green");
309  blue = (uint8_t*)allocateMemory(256, "blue");
310 
311  // init to grayscale
312  for (int i = 0; i < 256; i++) {
313  red[i] = i;
314  green[i] = i;
315  blue[i] = i;
316  }
317  rgb_land = (uint8_t*)allocateMemory(3, "rgb_land");
318  rgb_land[0] = 160;
319  rgb_land[1] = 82;
320  rgb_land[2] = 45;
321  transparent = false;
322 
323  metaData = (meta_l3bType*)allocateMemory(sizeof(meta_l3bType), "OutFile::metaData");
324  metaData->north = 90.0;
325  metaData->south = -90.0;
326  metaData->east = 180.0;
327  metaData->west = -180.0;
328 
329  mapProjection = "Undefined";
330 }
331 
333  free(red);
334  free(green);
335  free(blue);
336  free(rgb_land);
337  for (size_t i = 0; i < productStuff.size(); i++) {
338  delete productStuff[i];
339  }
340  productStuff.clear();
341  free(metaData);
342  if (qualityData)
343  free(qualityData);
344 }
345 
347  switch (productStuff[prod]->scaleType) {
348  case Log:
349  return "Log";
350  case Linear:
351  return "Linear";
352  case ArcTan:
353  return "ArcTan";
354  }
355  return "Linear";
356 }
357 
358 void OutFile::setSize(int32_t width, int32_t height) {
359  this->width = width;
360  this->height = height;
361  if (qualityData) {
362  free(qualityData);
363  qualityData = (uint8_t*)allocateMemory(width, "OutFile::qualityData");
364  }
365  currentLine = 0;
366 
367  for (size_t i = 0; i < productStuff.size(); i++) {
368  delete productStuff[i];
369  }
370  productStuff.clear();
371 }
372 
373 int32_t OutFile::getWidth() const {
374  return width;
375 }
376 
377 int32_t OutFile::getHeight() const {
378  return height;
379 }
380 
381 void OutFile::setFileName(string fileName) {
382  this->fileName = fileName;
383 }
384 
385 void OutFile::setPixel(int32_t x, double val, int32_t prod) {
386  if (x < 0 || x >= width) {
387  fprintf(stderr, "-E- OutFile::setPixel - x=%d is not within range, width=%d.\n", x, width);
388  exit(EXIT_FAILURE);
389  }
390  productStuff[prod]->lineData[x] = val;
391  if (val > fileMaxVal)
392  fileMaxVal = val;
393  if (val < fileMinVal)
394  fileMinVal = val;
395 }
396 
397 void OutFile::setPixelRGB(int32_t x, float red, float green, float blue) {
398  fprintf(stderr, "-E- OutFile::setPixelRGB - RGB not implemented with this file type.\n");
399  exit(EXIT_FAILURE);
400 }
401 
403  transparent = true;
404 }
405 
406 void OutFile::setQuality(int32_t x, uint8_t val) {
407  if (x < 0 || x >= width) {
408  fprintf(stderr, "-E- OutFile::setQuality - x=%d is not within range, width=%d.\n", x, width);
409  exit(EXIT_FAILURE);
410  }
411  if (!qualityData) {
412  fprintf(stderr, "-E- OutFile::setQuality - qualityData id NULL.\n");
413  exit(EXIT_FAILURE);
414  }
415  qualityData[x] = val;
416 }
417 
418 void OutFile::landPixel(int32_t x) {
419  if (x < 0 || x >= width) {
420  fprintf(stderr, "-E- OutFile::landPixel - x=%d is not within range, width=%d.\n", x, width);
421  exit(EXIT_FAILURE);
422  }
423  for (size_t prod = 0; prod < productStuff.size(); prod++)
424  productStuff[prod]->lineData[x] = landPixelValue;
425  if (qualityData)
426  qualityData[x] = qualityUnused;
427 }
428 
429 void OutFile::fillPixel(int32_t x) {
430  if (x < 0 || x >= width) {
431  fprintf(stderr, "-E- OutFile::fillPixel - x=%d is not within range, width=%d.\n", x, width);
432  exit(EXIT_FAILURE);
433  }
434  for (size_t prod = 0; prod < productStuff.size(); prod++)
435  productStuff[prod]->lineData[x] = badPixelValue;
436  if (qualityData)
437  qualityData[x] = qualityUnused;
438 }
439 
440 void OutFile::missingPixel(int32_t x) {
441  if (x < 0 || x >= width) {
442  fprintf(stderr, "-E- OutFile::missingPixel - x=%d is not within range, width=%d.\n", x, width);
443  exit(EXIT_FAILURE);
444  }
445  for (size_t prod = 0; prod < productStuff.size(); prod++)
446  productStuff[prod]->lineData[x] = badPixelValue;
447  if (qualityData)
448  qualityData[x] = qualityUnused;
449 }
450 
451 void OutFile::setLatLon(double* lat, double* lon) {
452  if (fullLatLon == LatLon2D) {
453  // NcVar::putVar takes care of converting double to float
454  latData = lat;
455  lonData = lon;
456  }
457 }
458 
459 bool OutFile::setPalette(const char* paletteName, bool applyMask) {
460  char* dataRoot;
461  string paletteFileName;
462  short r[256], g[256], b[256];
463 
464  if ((dataRoot = getenv("OCDATAROOT")) == NULL) {
465  printf("OCDATAROOT environment variable is not defined.\n");
466  return (EXIT_FAILURE);
467  }
468  paletteFileName = dataRoot;
469  paletteFileName += "/common/palette/";
470  paletteFileName += paletteName;
471  paletteFileName += ".pal";
472 
473  if (getlut_file((char*)paletteFileName.c_str(), r, g, b)) {
474  fprintf(stderr, "Error reading palette file %s\n", paletteFileName.c_str());
475  return false;
476  }
477  if (applyMask) {
478  r[landPix] = rgb_land[0];
479  g[landPix] = rgb_land[1];
480  b[landPix] = rgb_land[2];
481  r[fillPix] = 0;
482  g[fillPix] = 0;
483  b[fillPix] = 0;
484  }
485  for (int i = 0; i < 256; i++) {
486  red[i] = r[i];
487  green[i] = g[i];
488  blue[i] = b[i];
489  }
490 
491  return true;
492 }
493 
494 void OutFile::setLandRGB(const char* rgb_land_string) {
495  vector<string> rgb;
496  boost::split(rgb, rgb_land_string, boost::is_any_of(","));
497 
498  rgb_land[0] = std::stoi(rgb[0]);
499  rgb_land[1] = std::stoi(rgb[1]);
500  rgb_land[2] = std::stoi(rgb[2]);
501 }
502 
504  *this->metaData = *metaData;
505 }
506 
512 int32_t OutFile::addProduct(productInfo_t* productInfo) {
513  ProductStuff* stuff = new ProductStuff(width, productInfo, landPixelValue);
514 
515  // setup display scaling
516  if (!strcmp(productInfo->displayScale, "linear"))
517  stuff->setScale(productInfo->displayMin, productInfo->displayMax, Linear);
518  else if (!strcmp(productInfo->displayScale, "log"))
519  stuff->setScale(productInfo->displayMin, productInfo->displayMax, Log);
520  else if (!strcmp(productInfo->displayScale, "arctan"))
521  stuff->setScale(productInfo->displayMin, productInfo->displayMax, ArcTan);
522  else {
523  printf("-E- OutFile::addProduct - invalid displayScale = %s\n", productInfo->displayScale);
524  exit(EXIT_FAILURE);
525  }
526 
527  productStuff.push_back(stuff);
528  return productStuff.size() - 1;
529 }
530 
531 int32_t OutFile::addProductNonDisplay(productInfo_t* productInfo) {
532  ProductStuff* stuff = new ProductStuff(width, productInfo, landPixelValue);
533 
534  if (!strcmp(productInfo->dataType, "byte")) {
535  stuff->dataStorage = ByteDS;
536  stuff->minOutputVal = SCHAR_MIN;
537  stuff->maxOutputVal = SCHAR_MAX;
538  } else if (!strcmp(productInfo->dataType, "ubyte")) {
539  stuff->dataStorage = UByteDS;
540  stuff->minOutputVal = 0;
541  stuff->maxOutputVal = UCHAR_MAX;
542  } else if (!strcmp(productInfo->dataType, "short")) {
543  stuff->dataStorage = ShortDS;
544  stuff->minOutputVal = SHRT_MIN;
545  stuff->maxOutputVal = SHRT_MAX;
546  } else if (!strcmp(productInfo->dataType, "ushort")) {
547  stuff->dataStorage = UShortDS;
548  stuff->minOutputVal = 0;
549  stuff->maxOutputVal = USHRT_MAX;
550  } else if (!strcmp(productInfo->dataType, "int")) {
551  stuff->dataStorage = IntDS;
552  stuff->minOutputVal = INT_MIN;
553  stuff->maxOutputVal = INT_MAX;
554  } else if (!strcmp(productInfo->dataType, "uint")) {
555  stuff->dataStorage = UIntDS;
556  stuff->minOutputVal = 0;
557  stuff->maxOutputVal = UINT_MAX;
558  } else if (!strcmp(productInfo->dataType, "float")) {
559  stuff->dataStorage = FloatDS;
560  stuff->minOutputVal = 0;
561  stuff->maxOutputVal = 0;
562  } else if (!strcmp(productInfo->dataType, "double")) {
563  stuff->dataStorage = DoubleDS;
564  stuff->minOutputVal = 0;
565  stuff->maxOutputVal = 0;
566  } else {
567  printf("-E- OutFile::addProductNonDisplay - invalid data type = %s\n", productInfo->dataType);
568  exit(EXIT_FAILURE);
569  }
570 
571  // setup scaling
572  stuff->setScaleOffset(productInfo->scaleFactor, productInfo->addOffset, Linear);
573  stuff->missingValue = productInfo->fillValue;
574 
575  productStuff.push_back(stuff);
576  return productStuff.size() - 1;
577 }
578 
579 void OutFile::setMapProjection(string projection) {
580  mapProjection = projection;
581 }
582 
583 void OutFile::setProj4Info(string projStr, double minX, double maxY) {
584  proj4String = projStr;
585 
586  for (int i = 0; i < 6; i++)
587  tiepoints[i] = 0;
588  tiepoints[3] = minX;
589  tiepoints[4] = maxY;
590 
591  pixscale[0] = resolution;
592  pixscale[1] = resolution;
593  pixscale[2] = 0;
594 }
595 
596 void OutFile::setNumFilledPixels(int32_t num) {
597  if (metaData) {
598  metaData->data_bins = num;
599  }
600 }
601 
603  if (metaData)
604  return metaData->data_bins;
605  else
606  return -1;
607 }
608 
610  if (metaData) {
611  float numPix = width * height;
612  return metaData->data_bins / numPix * 100.0;
613  } else
614  return -1;
615 }
616 
618  fileMinVal = DBL_MAX;
619  fileMaxVal = 0 - DBL_MAX;
620 }
621 
622 void OutFile::setResolution(string resolutionStr) {
623  resolution = string2resolution(resolutionStr);
624 }
625 
627  if (val) {
628  // if width is not set yet allocate some dummy memory to flag we want
629  // to do SST quality processing.
630  if (width <= 0) {
631  if (!qualityData)
632  qualityData = (uint8_t*)allocateMemory(2, "OutFile::qualityData");
633  } else {
634  if (qualityData)
635  free(qualityData);
636  qualityData = (uint8_t*)allocateMemory(width, "OutFile::qualityData");
637  }
638  } else {
639  if (qualityData) {
640  free(qualityData);
641  qualityData = NULL;
642  }
643  }
644 }
645 
647  if (qualityData)
648  return true;
649  else
650  return false;
651 }
652 
653 //------------------------------------------------------------------------------
654 // OutFile_pgm
655 //------------------------------------------------------------------------------
656 
658  outfp = NULL;
659  fileData = NULL;
660 }
661 
663  if (outfp)
664  fclose(outfp);
665  if (fileData)
666  free(fileData);
667 }
668 
669 void OutFile_pgm::setSize(int32_t width, int32_t height) {
671  if (fileData)
672  free(fileData);
673  fileData = (uint8_t*)allocateMemory(width, "OutFile_pgm::fileData");
674 }
675 
677  outfp = fopen(fileName.c_str(), "w");
678  if (!outfp)
679  return false;
680 
681  /* Write pgm header */
682  fprintf(outfp, "P5\n");
683  fprintf(outfp, "%d %d\n", width, height);
684  fprintf(outfp, "255\n");
685 
686  return true;
687 }
688 
690  for (int i = 0; i < width; i++)
691  fileData[i] = (uint8_t)productStuff[0]->calcOutputVal(productStuff[0]->lineData[i]);
692  fwrite(fileData, 1, width, outfp);
693  currentLine++;
694 }
695 
697  fclose(outfp);
698  outfp = NULL;
699  return true;
700 }
701 
702 //------------------------------------------------------------------------------
703 // OutFile_ppm
704 //------------------------------------------------------------------------------
705 
706 void OutFile_ppm::setSize(int32_t width, int32_t height) {
708  if (fileData)
709  free(fileData);
710  fileData = (uint8_t*)allocateMemory(width * 3, "OutFile_ppm::fileData");
711 }
712 
714  outfp = fopen(fileName.c_str(), "w");
715  if (!outfp)
716  return false;
717 
718  /*
719  * Write ppm file header
720  */
721  fprintf(outfp, "P6\n");
722  fprintf(outfp, "%d %d\n", width, height);
723  fprintf(outfp, "255\n");
724 
725  return true;
726 }
727 
729  int j = 0;
730  for (int i = 0; i < width; i++) {
731  uint8_t val = (uint8_t)round(productStuff[0]->calcOutputVal(productStuff[0]->lineData[i]));
732  fileData[j++] = red[val];
733  fileData[j++] = green[val];
734  fileData[j++] = blue[val];
735  }
736  fwrite(fileData, 1, width * 3, outfp);
737  currentLine++;
738 }
739 
740 //------------------------------------------------------------------------------
741 // OutFile_ppm_rgb
742 //------------------------------------------------------------------------------
743 
745  outfp = NULL;
746  fileData = NULL;
747 }
748 
750  if (outfp)
751  fclose(outfp);
752  if (fileData)
753  free(fileData);
754 }
755 
756 void OutFile_ppm_rgb::setSize(int32_t width, int32_t height) {
758  if (fileData)
759  free(fileData);
760  fileData = (uint8_t*)allocateMemory(width * 3, "OutFile_ppm_rgb::fileData");
761 }
762 
764  outfp = fopen(fileName.c_str(), "w");
765  if (!outfp)
766  return false;
767 
768  /*
769  * Write ppm file header
770  */
771  fprintf(outfp, "P6\n");
772  fprintf(outfp, "%d %d\n", width, height);
773  fprintf(outfp, "255\n");
774  return true;
775 }
776 
778  fclose(outfp);
779  outfp = NULL;
780  return true;
781 }
782 
783 void OutFile_ppm_rgb::setPixel(int32_t x, double val, int32_t prod) {
784  fprintf(stderr,
785  "-E- OutFile_ppm_rgb::setPixel - only RGB is implemented with this file type.\n");
786  exit(EXIT_FAILURE);
787 }
788 
789 void OutFile_ppm_rgb::setPixelRGB(int32_t x, float red, float green, float blue) {
790  if (x < 0 || x >= width) {
791  fprintf(stderr,
792  "-E- OutFile_ppm_rgb::setPixel - x=%d is not within range, width=%d.\n",
793  x, width);
794  exit(EXIT_FAILURE);
795  }
796 
797  uint8_t* ptr = fileData + x * 3;
798 
799  *ptr = round(productStuff[0]->calcOutputVal(red));
800  ptr++;
801  *ptr = round(productStuff[0]->calcOutputVal(green));
802  ptr++;
803  *ptr = round(productStuff[0]->calcOutputVal(blue));
804 
805  // do this to keep the file min/max reasonable
806  if (red > fileMaxVal)
807  fileMaxVal = red;
808  if (red < fileMinVal)
809  fileMinVal = red;
810 }
811 
813  if (x < 0 || x >= width) {
814  fprintf(stderr,
815  "-E- OutFile_ppm_rgb::landPixel - x=%d is not within range, width=%d.\n",
816  x, width);
817  exit(EXIT_FAILURE);
818  }
819  uint8_t* ptr = fileData + x * 3;
820  *ptr = landPix;
821  ptr++;
822  *ptr = landPix;
823  ptr++;
824  *ptr = landPix;
825 }
826 
828  if (x < 0 || x >= width) {
829  fprintf(stderr,
830  "-E- OutFile_ppm_rgb::fillPixel - x=%d is not within range, width=%d.\n",
831  x, width);
832  exit(EXIT_FAILURE);
833  }
834  uint8_t* ptr = fileData + x * 3;
835  *ptr = fillPix;
836  ptr++;
837  *ptr = fillPix;
838  ptr++;
839  *ptr = fillPix;
840 }
841 
843  if (x < 0 || x >= width) {
844  fprintf(stderr,
845  "-E- OutFile_ppm_rgb::missingPixel - x=%d is not within range, width=%d.\n",
846  x, width);
847  exit(EXIT_FAILURE);
848  }
849  uint8_t* ptr = fileData + x * 3;
850  *ptr = fillPix;
851  ptr++;
852  *ptr = fillPix;
853  ptr++;
854  *ptr = fillPix;
855 }
856 
858  fwrite(fileData, 1, width * 3, outfp);
859  currentLine++;
860 }
861 
862 //------------------------------------------------------------------------------
863 // OutFile_png
864 //------------------------------------------------------------------------------
865 
867  isColor = color;
868  outfp = NULL;
869  fileData = NULL;
870  info_ptr = NULL;
871  png_ptr = NULL;
872  num_text = 10;
873 }
874 
876  if (outfp)
877  fclose(outfp);
878  if (fileData)
879  free(fileData);
880 }
881 
882 void OutFile_png::setSize(int32_t width, int32_t height) {
884  if (fileData)
885  free(fileData);
886  fileData = (uint8_t*)allocateMemory(width, "OutFile_png::fileData");
887 }
888 
890  outfp = fopen(fileName.c_str(), "w");
891  if (!outfp)
892  return false;
893 
894  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
895  if (!png_ptr) {
896  fprintf(stderr, "-E- Unable to create PNG write structure.\n");
897  exit(EXIT_FAILURE);
898  }
899 
900  info_ptr = png_create_info_struct(png_ptr);
901  if (!info_ptr) {
902  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
903  fprintf(stderr, "-E- Unable to create PNG info structure.\n");
904  exit(EXIT_FAILURE);
905  }
906  if (setjmp(png_jmpbuf(png_ptr))) {
907  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
908  fprintf(stderr, "-E- Unable to call PNG setjmp().\n");
909  exit(EXIT_FAILURE);
910  }
911  png_init_io(png_ptr, outfp);
912 
913  png_text text_ptr[num_text];
914  text_ptr[0].key = "projString";
915  text_ptr[0].text = const_cast<char*>(proj4String.c_str());
916  text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
917  text_ptr[1].key = "resolution";
918  text_ptr[1].text = const_cast<char*>(std::to_string(resolution).c_str());
919  text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
920  text_ptr[2].key = "north";
921  text_ptr[2].text = const_cast<char*>(std::to_string(metaData->north).c_str());
922  text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE;
923  text_ptr[3].key = "south";
924  text_ptr[3].text = const_cast<char*>(std::to_string(metaData->south).c_str());
925  text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE;
926  text_ptr[4].key = "east";
927  text_ptr[4].text = const_cast<char*>(std::to_string(metaData->east).c_str());
928  text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE;
929  text_ptr[5].key = "west";
930  text_ptr[5].text = const_cast<char*>(std::to_string(metaData->west).c_str());
931  text_ptr[5].compression = PNG_TEXT_COMPRESSION_NONE;
932  text_ptr[6].key = "minX";
933  text_ptr[6].text = const_cast<char*>(std::to_string(tiepoints[3]).c_str());
934  text_ptr[6].compression = PNG_TEXT_COMPRESSION_NONE;
935  text_ptr[7].key = "maxY";
936  text_ptr[7].text = const_cast<char*>(std::to_string(tiepoints[4]).c_str());
937  text_ptr[7].compression = PNG_TEXT_COMPRESSION_NONE;
938  text_ptr[8].key = "height";
939  text_ptr[8].text = const_cast<char*>(std::to_string(height).c_str());
940  text_ptr[8].compression = PNG_TEXT_COMPRESSION_NONE;
941  text_ptr[9].key = "width";
942  text_ptr[9].text = const_cast<char*>(std::to_string(width).c_str());
943  text_ptr[9].compression = PNG_TEXT_COMPRESSION_NONE;
944  png_set_text(png_ptr, info_ptr, text_ptr, num_text);
945 
946  if (isColor) {
947  // color palette
948  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
949  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
950 
951  uint8_t pal[256 * 3];
952  for (int i = 0; i < 256; i++) {
953  pal[i * 3] = red[i];
954  pal[i * 3 + 1] = green[i];
955  pal[i * 3 + 2] = blue[i];
956  }
957  png_set_PLTE(png_ptr, info_ptr, (png_const_colorp)pal, 256);
958 
959  if (transparent) {
960  uint8_t transPal[256];
961  for (int i = 0; i < 255; i++) {
962  transPal[i] = 255;
963  }
964  transPal[255] = 0;
965  png_set_tRNS(png_ptr, info_ptr, transPal, 256, NULL);
966  }
967  } else {
968  // Grayscale
969  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
970  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
971  }
972  png_write_info(png_ptr, info_ptr);
973 
974  return true;
975 }
976 
978  for (int i = 0; i < width; i++)
979  fileData[i] = (uint8_t)round(productStuff[0]->calcOutputVal(productStuff[0]->lineData[i]));
980  png_write_row(png_ptr, (png_bytep)fileData);
981  currentLine++;
982 }
983 
985  png_write_end(png_ptr, info_ptr);
986  png_destroy_write_struct(&png_ptr, &info_ptr);
987 
988  fclose(outfp);
989  outfp = NULL;
990  return true;
991 }
992 
993 //------------------------------------------------------------------------------
994 // OutFile_png_rgb
995 //------------------------------------------------------------------------------
996 
998  outfp = NULL;
999  fileData = NULL;
1000  info_ptr = NULL;
1001  png_ptr = NULL;
1002  num_text = 10;
1003 }
1004 
1006  if (outfp)
1007  fclose(outfp);
1008  if (fileData)
1009  free(fileData);
1010 }
1011 
1012 void OutFile_png_rgb::setSize(int32_t width, int32_t height) {
1014  if (fileData)
1015  free(fileData);
1016  int samplesPerPixel = 3;
1017  if (transparent)
1018  samplesPerPixel = 4;
1019  fileData = (uint8_t*)allocateMemory(width * samplesPerPixel, "OutFile_png_rgb::fileData");
1020 }
1021 
1023  outfp = fopen(fileName.c_str(), "w");
1024  if (!outfp)
1025  return false;
1026 
1027  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1028  if (!png_ptr) {
1029  fprintf(stderr, "-E- Unable to create PNG write structure.\n");
1030  exit(EXIT_FAILURE);
1031  }
1032 
1033  info_ptr = png_create_info_struct(png_ptr);
1034  if (!info_ptr) {
1035  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
1036  fprintf(stderr, "-E- Unable to create PNG info structure.\n");
1037  exit(EXIT_FAILURE);
1038  }
1039  if (setjmp(png_jmpbuf(png_ptr))) {
1040  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
1041  fprintf(stderr, "-E- Unable to call PNG setjmp().\n");
1042  exit(EXIT_FAILURE);
1043  }
1044  png_init_io(png_ptr, outfp);
1045 
1046  png_text text_ptr[num_text];
1047  text_ptr[0].key = "projString";
1048  text_ptr[0].text = const_cast<char*>(proj4String.c_str());
1049  text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
1050  text_ptr[1].key = "resolution";
1051  text_ptr[1].text = const_cast<char*>(std::to_string(resolution).c_str());
1052  text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
1053  text_ptr[2].key = "north";
1054  text_ptr[2].text = const_cast<char*>(std::to_string(metaData->north).c_str());
1055  text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE;
1056  text_ptr[3].key = "south";
1057  text_ptr[3].text = const_cast<char*>(std::to_string(metaData->south).c_str());
1058  text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE;
1059  text_ptr[4].key = "east";
1060  text_ptr[4].text = const_cast<char*>(std::to_string(metaData->east).c_str());
1061  text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE;
1062  text_ptr[5].key = "west";
1063  text_ptr[5].text = const_cast<char*>(std::to_string(metaData->west).c_str());
1064  text_ptr[5].compression = PNG_TEXT_COMPRESSION_NONE;
1065  text_ptr[6].key = "minX";
1066  text_ptr[6].text = const_cast<char*>(std::to_string(tiepoints[3]).c_str());
1067  text_ptr[6].compression = PNG_TEXT_COMPRESSION_NONE;
1068  text_ptr[7].key = "maxY";
1069  text_ptr[7].text = const_cast<char*>(std::to_string(tiepoints[4]).c_str());
1070  text_ptr[7].compression = PNG_TEXT_COMPRESSION_NONE;
1071  text_ptr[8].key = "height";
1072  text_ptr[8].text = const_cast<char*>(std::to_string(height).c_str());
1073  text_ptr[8].compression = PNG_TEXT_COMPRESSION_NONE;
1074  text_ptr[9].key = "width";
1075  text_ptr[9].text = const_cast<char*>(std::to_string(width).c_str());
1076  text_ptr[9].compression = PNG_TEXT_COMPRESSION_NONE;
1077  png_set_text(png_ptr, info_ptr, text_ptr, num_text);
1078 
1079  if (transparent)
1080  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
1081  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1082  else
1083  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
1084  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1085  png_write_info(png_ptr, info_ptr);
1086 
1087  return true;
1088 }
1089 
1091  if (setjmp(png_jmpbuf(png_ptr))) {
1092  fprintf(stderr, "-E- OutFile_png_rgb::close - Unable to call PNG setjmp().\n");
1093  exit(EXIT_FAILURE);
1094  }
1095  png_write_end(png_ptr, info_ptr);
1096  png_destroy_write_struct(&png_ptr, &info_ptr);
1097 
1098  fclose(outfp);
1099  outfp = NULL;
1100  return true;
1101 }
1102 
1103 void OutFile_png_rgb::setPixel(int32_t x, double val, int32_t prod) {
1104  fprintf(stderr,
1105  "-E- OutFile_png_rgb::setPixel - only RGB is implemented with this file type.\n");
1106  exit(EXIT_FAILURE);
1107 }
1108 
1109 void OutFile_png_rgb::setPixelRGB(int32_t x, float red, float green, float blue) {
1110  if (x < 0 || x >= width) {
1111  fprintf(stderr,
1112  "-E- OutFile_png_rgb::setPixel - x=%d is not within range, width=%d.\n",
1113  x, width);
1114  exit(EXIT_FAILURE);
1115  }
1116 
1117  int samplesPerPixel = 3;
1118  if (transparent)
1119  samplesPerPixel = 4;
1120  uint8_t* ptr = fileData + x * samplesPerPixel;
1121 
1122  *ptr = round(productStuff[0]->calcOutputVal(red));
1123  ptr++;
1124  *ptr = round(productStuff[0]->calcOutputVal(green));
1125  ptr++;
1126  *ptr = round(productStuff[0]->calcOutputVal(blue));
1127  if (transparent) {
1128  ptr++;
1129  if (red == badPixelValue || green == badPixelValue || blue == badPixelValue) {
1130  *ptr = 0; // transparent
1131  } else {
1132  *ptr = 255;
1133  }
1134  }
1135 
1136  // do this to keep the file min/max reasonable
1137  if (red > fileMaxVal)
1138  fileMaxVal = red;
1139  if (red < fileMinVal)
1140  fileMinVal = red;
1141 }
1142 
1144  if (x < 0 || x >= width) {
1145  fprintf(stderr,
1146  "-E- OutFile_png_rgb::landPixel - x=%d is not within range, width=%d.\n",
1147  x, width);
1148  exit(EXIT_FAILURE);
1149  }
1150  int samplesPerPixel = 3;
1151  if (transparent)
1152  samplesPerPixel = 4;
1153  uint8_t* ptr = fileData + x * samplesPerPixel;
1154  *ptr = landPix;
1155  ptr++;
1156  *ptr = landPix;
1157  ptr++;
1158  *ptr = landPix;
1159  if (transparent) {
1160  ptr++;
1161  *ptr = 255;
1162  }
1163 }
1164 
1166  if (x < 0 || x >= width) {
1167  fprintf(stderr,
1168  "-E- OutFile_png_rgb::fillPixel - x=%d is not within range, width=%d.\n",
1169  x, width);
1170  exit(EXIT_FAILURE);
1171  }
1172  int samplesPerPixel = 3;
1173  if (transparent)
1174  samplesPerPixel = 4;
1175  uint8_t* ptr = fileData + x * samplesPerPixel;
1176  *ptr = fillPix;
1177  ptr++;
1178  *ptr = fillPix;
1179  ptr++;
1180  *ptr = fillPix;
1181  if (transparent) {
1182  ptr++;
1183  *ptr = 0;
1184  }
1185 }
1186 
1188  if (x < 0 || x >= width) {
1189  fprintf(stderr,
1190  "-E- OutFile_png_rgb::missingPixel - x=%d is not within range, width=%d.\n",
1191  x, width);
1192  exit(EXIT_FAILURE);
1193  }
1194  int samplesPerPixel = 3;
1195  if (transparent)
1196  samplesPerPixel = 4;
1197  uint8_t* ptr = fileData + x * samplesPerPixel;
1198  *ptr = fillPix;
1199  ptr++;
1200  *ptr = fillPix;
1201  ptr++;
1202  *ptr = fillPix;
1203  if (transparent) {
1204  ptr++;
1205  *ptr = 0;
1206  }
1207 }
1208 
1210  if (setjmp(png_jmpbuf(png_ptr))) {
1211  fprintf(stderr, "-E- OutFile_png_rgb::writeLine - Unable to call PNG setjmp().\n");
1212  exit(EXIT_FAILURE);
1213  }
1214 
1215  png_write_row(png_ptr, (png_bytep)fileData);
1216  currentLine++;
1217 }
1218 
1219 //------------------------------------------------------------------------------
1220 // OutFile_tiff
1221 //------------------------------------------------------------------------------
1222 
1224  close();
1225 }
1226 
1228  currentLine = 0;
1229 
1230  // open TIFF file
1231  tiff = XTIFFOpen(fileName.c_str(), "w");
1232  if (tiff == NULL) {
1233  cerr << "-E- Could not open outgoing TIFF image" << endl;
1234  exit(EXIT_FAILURE);
1235  }
1236 
1237  // extend the TIFF tags to write pversion
1238  ttag_t TIFFTAG_GDALMetadata = 42112;
1239  static const TIFFFieldInfo xtiffFieldInfo[] = {
1240  {TIFFTAG_GDALMetadata, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE, "GDALMetadata"}};
1241  TIFFMergeFieldInfo(tiff, xtiffFieldInfo, 1);
1242  std::string tagVal = "<GDALMetadata>\n <Item name=\"OBPG_version\">";
1243  tagVal += metaData->pversion;
1244  tagVal += "</Item>\n";
1245  tagVal += "</GDALMetadata>\n";
1246  TIFFSetField(tiff, TIFFTAG_GDALMetadata, tagVal.c_str());
1247 
1248  TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width);
1249  TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height);
1250  TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1251  TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
1252  TIFFSetField(tiff, TIFFTAG_PREDICTOR, PREDICTOR_NONE);
1253  TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, height);
1254 
1255  // open GeoTIFF interface
1256  bool hasGeotiffInfo = false;
1257  gtif = GTIFNew(tiff);
1258  if (gtif == NULL) {
1259  cerr << "-E- Could not create geoTIFF structure" << endl;
1260  exit(EXIT_FAILURE);
1261  }
1262 
1263  // define GeoTIFF keys for lat/lon projection
1264  if (mapProjection == "Equidistant Cylindrical" || mapProjection == "PlateCarree") {
1265  double north, south, east, west;
1266  if (metaData) {
1267  north = metaData->north;
1268  south = metaData->south;
1269  east = metaData->east;
1270  west = metaData->west;
1271  } else {
1272  north = 90.0;
1273  south = -90.0;
1274  east = 180.0;
1275  west = -180.0;
1276  }
1277 
1278  // pixel width, height in degrees
1279  pixscale[0] = (east - west) / width;
1280  pixscale[1] = (north - south) / height;
1281 
1282  // top left corner pixel lat, lon
1283  for (int i = 0; i < 6; i++)
1284  tiepoints[i] = 0;
1285  tiepoints[3] = west;
1286  tiepoints[4] = north;
1287 
1288  GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelGeographic);
1289  GTIFKeySet(gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, GCS_WGS_84);
1290  hasGeotiffInfo = true;
1291  }
1292  // otherwise, parse the proj4 string
1293  else
1294  hasGeotiffInfo = (GTIFSetFromProj4(gtif, proj4String.c_str()));
1295 
1296  if (!hasGeotiffInfo) {
1297  if (proj4String.find("EPSG:") != string::npos)
1298  hasGeotiffInfo = true;
1299  }
1300 
1301  if (hasGeotiffInfo) {
1302  // write GeoTIFF keys
1303  GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea);
1304  static const std::string& epsg_regex_str{"EPSG:(\\d+)\\b"};
1305  static const std::regex epsg_regex{epsg_regex_str};
1306  std::smatch matches;
1307  if (std::regex_search(proj4String, matches, epsg_regex)) {
1308  unsigned short epsg = std::stoi(matches[1]);
1309  GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, epsg);
1310  }
1311  GTIFWriteKeys(gtif);
1312 
1313  // write GeoTIFF tags in map units
1314  TIFFSetField(tiff, GTIFF_PIXELSCALE, 3, pixscale);
1315  TIFFSetField(tiff, GTIFF_TIEPOINTS, 6, tiepoints);
1316  }
1317 
1318  // define colormap
1319  setTiffColor();
1320  return true;
1321 }
1322 
1324  if (gtif) {
1325  GTIFFree(gtif);
1326  XTIFFClose(tiff);
1327  tiff = NULL;
1328  gtif = NULL;
1329  }
1330  return true;
1331 }
1332 
1333 //----- OutFile_tiff_color -----
1334 
1336  if (fileData)
1337  free(fileData);
1338 }
1339 
1340 void OutFile_tiff_color::setSize(int32_t width, int32_t height) {
1342  if (fileData)
1343  free(fileData);
1344 
1345  // if transparent we need to use RGBA mode instead of indexed color map
1346  if (transparent) {
1347  fileData = (uint8_t*)allocateMemory(width * 4, "OutFile_tiff_color::fileData");
1348  } else {
1349  fileData = (uint8_t*)allocateMemory(width, "OutFile_tiff_color::fileData");
1350  }
1351 }
1352 
1354  if (transparent) {
1355  for (int i = 0; i < width; i++) {
1356  uint8_t* ptr = fileData + i * 4;
1357 
1358  uint8_t alpha = 255; // opaque
1359 
1360  uint8_t scaledVal = (uint8_t)round(productStuff[0]->calcOutputVal(productStuff[0]->lineData[i]));
1361  if (productStuff[0]->lineData[i] == badPixelValue) {
1362  alpha = 0; // transparent
1363  }
1364  *ptr = red[scaledVal];
1365  ptr++;
1366  *ptr = green[scaledVal];
1367  ptr++;
1368  *ptr = blue[scaledVal];
1369  ptr++;
1370  *ptr = alpha;
1371  }
1372  } else {
1373  for (int i = 0; i < width; i++)
1374  fileData[i] = (uint8_t)round(productStuff[0]->calcOutputVal(productStuff[0]->lineData[i]));
1375  }
1376 
1377  if (TIFFWriteScanline(tiff, (void*)fileData, currentLine) == 0) {
1378  cerr << "-E- Could not write TIFF image line " << currentLine << endl;
1379  exit(EXIT_FAILURE);
1380  }
1381 
1382  currentLine++;
1383 }
1384 
1386  if (transparent) {
1387  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1388  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
1389  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4);
1390  uint16_t out[1];
1391  out[0] = EXTRASAMPLE_ASSOCALPHA;
1392  TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &out);
1393  TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
1394  } else {
1395  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
1396  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
1397  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1398 
1399  int ncolors = 256; // convert bytes to short
1400  uint16_t* rr = (uint16_t*)malloc(ncolors * sizeof(uint16_t));
1401  uint16_t* gg = (uint16_t*)malloc(ncolors * sizeof(uint16_t));
1402  uint16_t* bb = (uint16_t*)malloc(ncolors * sizeof(uint16_t));
1403  if (rr == NULL || gg == NULL || bb == NULL) {
1404  cerr << "-E- Could not allocate memory for TIFF color map" << endl;
1405  exit(EXIT_FAILURE);
1406  }
1407  for (int i = 0; i < ncolors; i++) {
1408  rr[i] = red[i] << 8;
1409  gg[i] = green[i] << 8;
1410  bb[i] = blue[i] << 8;
1411  }
1412  TIFFSetField(tiff, TIFFTAG_COLORMAP, rr, gg, bb);
1413  free(rr);
1414  free(gg);
1415  free(bb);
1416  }
1417 }
1418 
1419 //----- OutFile_tiff_gray -----
1420 
1422  this->landPixelValue = badPixelValue; // Grayscale outputs a floating point value
1423 }
1424 
1426  if (fileData)
1427  free(fileData);
1428 }
1429 
1430 void OutFile_tiff_gray::setSize(int32_t width, int32_t height) {
1432  if (fileData)
1433  free(fileData);
1434  fileData = (float*)allocateMemory(width * sizeof(float), "OutFile_tiff_gray::fileData");
1435 }
1436 
1438  for (int i = 0; i < width; i++)
1439  fileData[i] = productStuff[0]->lineData[i];
1440 
1441  if (TIFFWriteScanline(tiff, (void*)fileData, currentLine) == 0) {
1442  cerr << "-E- Could not write TIFF image line " << currentLine << endl;
1443  exit(EXIT_FAILURE);
1444  }
1445  currentLine++;
1446 }
1447 
1449  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1450  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 32);
1451  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
1452  TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1453 }
1454 
1455 //----- OutFile_tiff_rgb -----
1456 
1458  if (fileData)
1459  free(fileData);
1460 }
1461 
1462 void OutFile_tiff_rgb::setSize(int32_t width, int32_t height) {
1464  if (fileData)
1465  free(fileData);
1466  if (transparent) {
1467  fileData = (uint8_t*)allocateMemory(width * 4, "OutFile_tiff_rgb::fileData");
1468  } else {
1469  fileData = (uint8_t*)allocateMemory(width * 3, "OutFile_tiff_rgb::fileData");
1470  }
1471 }
1472 
1474  if (TIFFWriteScanline(tiff, (void*)fileData, currentLine) == 0) {
1475  cerr << "-E- Could not write TIFF image line " << currentLine << endl;
1476  exit(EXIT_FAILURE);
1477  }
1478  currentLine++;
1479 }
1480 
1482  TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1483  TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
1484  if (transparent) {
1485  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4);
1486  } else {
1487  TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1488  }
1489  TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
1490 }
1491 
1492 void OutFile_tiff_rgb::setPixel(int32_t x, double val, int32_t prod) {
1493  if (x < 0 || x >= width) {
1494  fprintf(stderr,
1495  "-E- OutFile_tiff_rgb::setPixel - x=%d is not within range, width=%d.\n",
1496  x, width);
1497  exit(EXIT_FAILURE);
1498  }
1499 
1500  uint8_t samplesPerPixel = 3;
1501  if (transparent) {
1502  samplesPerPixel = 4;
1503  }
1504  uint8_t* ptr = fileData + x * samplesPerPixel;
1505 
1506  uint8_t alpha = 255; // opaque
1507 
1508  uint8_t scaledVal = round(productStuff[0]->calcOutputVal(val));
1509  if (val == badPixelValue) {
1510  alpha = 0; // transparent
1511  }
1512  *ptr = red[scaledVal];
1513  ptr++;
1514  *ptr = green[scaledVal];
1515  ptr++;
1516  *ptr = blue[scaledVal];
1517  if (transparent) {
1518  ptr++;
1519  *ptr = alpha;
1520  }
1521 }
1522 
1523 void OutFile_tiff_rgb::setPixelRGB(int32_t x, float red, float green, float blue) {
1524  if (x < 0 || x >= width) {
1525  fprintf(stderr,
1526  "-E- OutFile_tiff_rgb::setPixel - x=%d is not within range, width=%d.\n",
1527  x, width);
1528  exit(EXIT_FAILURE);
1529  }
1530 
1531  uint8_t alpha = 255; // opaque
1532 
1533  uint8_t samplesPerPixel = 3;
1534  if (transparent) {
1535  samplesPerPixel = 4;
1536  }
1537  uint8_t* ptr = fileData + x * samplesPerPixel;
1538 
1539  *ptr = round(productStuff[0]->calcOutputVal(red));
1540  ptr++;
1541  *ptr = round(productStuff[0]->calcOutputVal(green));
1542  ptr++;
1543  *ptr = round(productStuff[0]->calcOutputVal(blue));
1544  if (transparent) {
1545  if (red == badPixelValue || green == badPixelValue || blue == badPixelValue) {
1546  alpha = 0; // transparent
1547  }
1548  ptr++;
1549  *ptr = alpha;
1550  }
1551 
1552  if (red > fileMaxVal) // keep file min/max reasonable
1553  fileMaxVal = red;
1554  if (red < fileMinVal)
1555  fileMinVal = red;
1556 }
1557 
1559  if (x < 0 || x >= width) {
1560  fprintf(stderr,
1561  "-E- OutFile_tiff_rgb::landPixel - x=%d is not within range, width=%d.\n",
1562  x, width);
1563  exit(EXIT_FAILURE);
1564  }
1565 
1566  uint8_t samplesPerPixel = 3;
1567  if (transparent) {
1568  samplesPerPixel = 4;
1569  }
1570  uint8_t* ptr = fileData + x * samplesPerPixel;
1571  *ptr = landPix;
1572  ptr++;
1573  *ptr = landPix;
1574  ptr++;
1575  *ptr = landPix;
1576  if (transparent) {
1577  ptr++;
1578  *ptr = 255;
1579  }
1580 }
1581 
1583  if (x < 0 || x >= width) {
1584  fprintf(stderr,
1585  "-E- OutFile_tiff_rgb::fillPixel - x=%d is not within range, width=%d.\n",
1586  x, width);
1587  exit(EXIT_FAILURE);
1588  }
1589 
1590  uint8_t samplesPerPixel = 3;
1591  if (transparent) {
1592  samplesPerPixel = 4;
1593  }
1594  uint8_t* ptr = fileData + x * samplesPerPixel;
1595  *ptr = fillPix;
1596  ptr++;
1597  *ptr = fillPix;
1598  ptr++;
1599  *ptr = fillPix;
1600  if (transparent) {
1601  ptr++;
1602  *ptr = 0;
1603  }
1604 }
1605 
1607  if (x < 0 || x >= width) {
1608  fprintf(stderr,
1609  "-E- OutFile_tiff_rgb::missingPixel - x=%d is not within range, width=%d.\n",
1610  x, width);
1611  exit(EXIT_FAILURE);
1612  }
1613 
1614  uint8_t samplesPerPixel = 3;
1615  if (transparent) {
1616  samplesPerPixel = 4;
1617  }
1618  uint8_t* ptr = fileData + x * samplesPerPixel;
1619  *ptr = fillPix;
1620  ptr++;
1621  *ptr = fillPix;
1622  ptr++;
1623  *ptr = fillPix;
1624  if (transparent) {
1625  ptr++;
1626  *ptr = 0;
1627  }
1628 }
1629 
1630 //------------------------------------------------------------------------------
1631 // OutFile_hdf4
1632 //------------------------------------------------------------------------------
1633 
1635  fileData = NULL;
1636  sdfid = -1;
1637  sdsid = -1;
1638  quality_sdsid = -1;
1639  hdfDataType = DFNT_FLOAT32;
1640 }
1641 
1643  if (fileData)
1644  free(fileData);
1645 }
1646 
1647 void OutFile_hdf4::setSize(int32_t width, int32_t height) {
1649  if (fileData)
1650  free(fileData);
1651  fileData = NULL;
1652 }
1653 
1655  const char* tmpStr;
1656  float tmpFloat;
1657  int32_t tmpInt32;
1658 
1659  currentLine = 0;
1660 
1661  sdfid = SDstart(fileName.c_str(), DFACC_CREATE);
1662 
1663  if (sdfid < 0) {
1664  printf("-E- Could not create HDF4 file %s\n", fileName.c_str());
1665  exit(EXIT_FAILURE);
1666  }
1667 
1669 
1670  string prodName;
1671  size_t pos = fileName.find_last_of('/');
1672  if (pos == string::npos)
1673  prodName = fileName;
1674  else
1675  prodName = fileName.substr(pos + 1);
1676  DPTB(SDsetattr(sdfid, "Product Name", DFNT_CHAR, prodName.size() + 1, (VOIDP)prodName.c_str()));
1677  DPTB(SDsetattr(sdfid, "Sensor Name", DFNT_CHAR, strlen(metaData->sensor_name) + 1,
1678  (VOIDP)metaData->sensor_name));
1679  DPTB(SDsetattr(sdfid, "Sensor", DFNT_CHAR, strlen(metaData->sensor) + 1, (VOIDP)metaData->sensor));
1680  DPTB(SDsetattr(sdfid, "Title", DFNT_CHAR, strlen(metaData->title) + 1, (VOIDP)metaData->title));
1681  DPTB(SDsetattr(sdfid, "Data Center", DFNT_CHAR, strlen(metaData->data_center) + 1,
1682  (VOIDP)metaData->data_center));
1683  DPTB(
1684  SDsetattr(sdfid, "Station Name", DFNT_CHAR, strlen(metaData->station) + 1, (VOIDP)metaData->station));
1685  DPTB(SDsetattr(sdfid, "Station Latitude", DFNT_FLOAT32, 1, (VOIDP)&metaData->station_lat));
1686  DPTB(SDsetattr(sdfid, "Station Longitude", DFNT_FLOAT32, 1, (VOIDP)&metaData->station_lon));
1687  DPTB(SDsetattr(sdfid, "Mission", DFNT_CHAR, strlen(metaData->mission) + 1, (VOIDP)metaData->mission));
1688  DPTB(SDsetattr(sdfid, "Mission Characteristics", DFNT_CHAR, strlen(metaData->mission_char) + 1,
1689  (VOIDP)metaData->mission_char));
1690  DPTB(SDsetattr(sdfid, "Sensor Characteristics", DFNT_CHAR, strlen(metaData->sensor_char) + 1,
1691  (VOIDP)metaData->sensor_char));
1692  DPTB(SDsetattr(sdfid, "Product Type", DFNT_CHAR, strlen(metaData->prod_type) + 1,
1693  (VOIDP)metaData->prod_type));
1694  DPTB(SDsetattr(sdfid, "Processing Version", DFNT_CHAR, strlen(metaData->pversion) + 1,
1695  (VOIDP)metaData->pversion));
1696  DPTB(SDsetattr(sdfid, "Software Name", DFNT_CHAR, strlen(metaData->soft_name) + 1,
1697  (VOIDP)metaData->soft_name));
1698  DPTB(SDsetattr(sdfid, "Software Version", DFNT_CHAR, strlen(metaData->soft_ver) + 1,
1699  (VOIDP)metaData->soft_ver));
1700  DPTB(SDsetattr(sdfid, "Processing Time", DFNT_CHAR, strlen(metaData->ptime) + 1, (VOIDP)metaData->ptime));
1701  DPTB(SDsetattr(sdfid, "Input Files", DFNT_CHAR, strlen(metaData->infiles) + 1, (VOIDP)metaData->infiles));
1702  DPTB(SDsetattr(sdfid, "Processing Control", DFNT_CHAR, strlen(metaData->proc_con) + 1,
1703  (VOIDP)metaData->proc_con));
1704  DPTB(SDsetattr(sdfid, "Input Parameters", DFNT_CHAR, strlen(metaData->input_parms) + 1,
1705  (VOIDP)metaData->input_parms));
1706  DPTB(SDsetattr(sdfid, "L2 Flag Names", DFNT_CHAR, strlen(metaData->flag_names) + 1,
1707  (VOIDP)metaData->flag_names));
1708 
1709  short syear, sday, eyear, eday;
1710  double ssec, esec;
1711  int32_t smsec, emsec;
1712  unix2yds(metaData->startTime, &syear, &sday, &ssec);
1713  smsec = (int32_t)(ssec * 1000.0);
1714  unix2yds(metaData->endTime, &eyear, &eday, &esec);
1715  emsec = (int32_t)(esec * 1000.0);
1716  DPTB(SDsetattr(sdfid, "Period Start Year", DFNT_INT16, 1, (VOIDP)&syear));
1717  DPTB(SDsetattr(sdfid, "Period Start Day", DFNT_INT16, 1, (VOIDP)&sday));
1718  DPTB(SDsetattr(sdfid, "Period End Year", DFNT_INT16, 1, (VOIDP)&eyear));
1719  DPTB(SDsetattr(sdfid, "Period End Day", DFNT_INT16, 1, (VOIDP)&eday));
1720  tmpStr = ydhmsf(metaData->startTime, 'G');
1721  DPTB(SDsetattr(sdfid, "Start Time", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1722  tmpStr = ydhmsf(metaData->endTime, 'G');
1723  DPTB(SDsetattr(sdfid, "End Time", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1724  DPTB(SDsetattr(sdfid, "Start Year", DFNT_INT16, 1, (VOIDP)&syear));
1725  DPTB(SDsetattr(sdfid, "Start Day", DFNT_INT16, 1, (VOIDP)&sday));
1726  DPTB(SDsetattr(sdfid, "Start Millisec", DFNT_INT32, 1, (VOIDP)&smsec));
1727  DPTB(SDsetattr(sdfid, "End Year", DFNT_INT16, 1, (VOIDP)&eyear));
1728  DPTB(SDsetattr(sdfid, "End Day", DFNT_INT16, 1, (VOIDP)&eday));
1729  DPTB(SDsetattr(sdfid, "End Millisec", DFNT_INT32, 1, (VOIDP)&emsec));
1730 
1731  DPTB(SDsetattr(sdfid, "Start Orbit", DFNT_INT32, 1, (VOIDP)&metaData->start_orb));
1732  DPTB(SDsetattr(sdfid, "End Orbit", DFNT_INT32, 1, (VOIDP)&metaData->end_orb));
1733  DPTB(SDsetattr(sdfid, "Orbit", DFNT_INT32, 1, (VOIDP)&metaData->orbit));
1734  DPTB(SDsetattr(sdfid, "Map Projection", DFNT_CHAR, mapProjection.size() + 1, mapProjection.c_str()));
1735  DPTB(SDsetattr(sdfid, "Latitude Units", DFNT_CHAR, 14, (VOIDP) "degrees North"));
1736  DPTB(SDsetattr(sdfid, "Longitude Units", DFNT_CHAR, 13, (VOIDP) "degrees East"));
1737  DPTB(SDsetattr(sdfid, "Northernmost Latitude", DFNT_FLOAT32, 1, (VOIDP)&metaData->north));
1738  DPTB(SDsetattr(sdfid, "Southernmost Latitude", DFNT_FLOAT32, 1, (VOIDP)&metaData->south));
1739  DPTB(SDsetattr(sdfid, "Westernmost Longitude", DFNT_FLOAT32, 1, (VOIDP)&metaData->west));
1740  DPTB(SDsetattr(sdfid, "Easternmost Longitude", DFNT_FLOAT32, 1, (VOIDP)&metaData->east));
1741 
1742  float latStep = (metaData->north - metaData->south) / (float)getHeight();
1743  DPTB(SDsetattr(sdfid, "Latitude Step", DFNT_FLOAT32, 1, (VOIDP)&latStep));
1744  float lonStep;
1745  if (metaData->east < metaData->west)
1746  lonStep = (360 + metaData->east - metaData->west) / (float)getWidth();
1747  else
1748  lonStep = (metaData->east - metaData->west) / (float)getWidth();
1749  DPTB(SDsetattr(sdfid, "Longitude Step", DFNT_FLOAT32, 1, (VOIDP)&lonStep));
1750 
1751  tmpFloat = metaData->south + latStep / 2.0;
1752  DPTB(SDsetattr(sdfid, "SW Point Latitude", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1753  tmpFloat = metaData->west + lonStep / 2.0;
1754  DPTB(SDsetattr(sdfid, "SW Point Longitude", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1755 
1756  tmpInt32 = metaData->data_bins;
1757  DPTB(SDsetattr(sdfid, "Data Bins", DFNT_INT32, 1, (VOIDP)&tmpInt32));
1758 
1759  tmpInt32 = getHeight();
1760  DPTB(SDsetattr(sdfid, "Number of Lines", DFNT_INT32, 1, (VOIDP)&tmpInt32));
1761  tmpInt32 = getWidth();
1762  DPTB(SDsetattr(sdfid, "Number of Columns", DFNT_INT32, 1, (VOIDP)&tmpInt32));
1763  DPTB(SDsetattr(sdfid, "Parameter", DFNT_CHAR, strlen(productStuff[0]->productInfo->description) + 1,
1764  (VOIDP)productStuff[0]->productInfo->description));
1765  DPTB(SDsetattr(sdfid, "Measure", DFNT_CHAR, 5, (VOIDP) "Mean"));
1766  DPTB(SDsetattr(sdfid, "Units", DFNT_CHAR, strlen(productStuff[0]->productInfo->units) + 1,
1767  (VOIDP)productStuff[0]->productInfo->units));
1768 
1769  // we only use linear scaling for data storage
1770  tmpStr = "linear";
1771  DPTB(SDsetattr(sdfid, "Scaling", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1772  tmpStr = "(Slope*l3m_data) + Intercept = Parameter value";
1773  DPTB(SDsetattr(sdfid, "Scaling Equation", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1774 
1775  float tmpScale;
1776  float tmpOffset;
1777  const char* imageScalingApplied;
1778 
1779  switch (productStuff[0]->dataStorage) {
1780  case FloatDS:
1781  case DoubleDS:
1782  tmpScale = 1.0;
1783  tmpOffset = 0.0;
1784  imageScalingApplied = "No";
1785  break;
1786  default:
1787  tmpScale = productStuff[0]->scale;
1788  tmpOffset = productStuff[0]->offset;
1789  if (tmpScale == 1.0 && tmpOffset == 0.0)
1790  imageScalingApplied = "No";
1791  else
1792  imageScalingApplied = "Yes";
1793  }
1794 
1795  DPTB(SDsetattr(sdfid, "Slope", DFNT_FLOAT32, 1, (VOIDP)&tmpScale));
1796  DPTB(SDsetattr(sdfid, "Intercept", DFNT_FLOAT32, 1, (VOIDP)&tmpOffset));
1797 
1798  tmpFloat = productStuff[0]->productInfo->validMin;
1799  DPTB(SDsetattr(sdfid, "Data Minimum", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1800  tmpFloat = productStuff[0]->productInfo->validMax;
1801  DPTB(SDsetattr(sdfid, "Data Maximum", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1802  tmpFloat = productStuff[0]->productInfo->displayMin;
1803  DPTB(SDsetattr(sdfid, "Suggested Image Scaling Minimum", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1804  tmpFloat = productStuff[0]->productInfo->displayMax;
1805  DPTB(SDsetattr(sdfid, "Suggested Image Scaling Maximum", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1806 
1807  tmpStr = strdup(productStuff[0]->productInfo->displayScale);
1808  upcase((char*)tmpStr);
1809  DPTB(SDsetattr(sdfid, "Suggested Image Scaling Type", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1810  free((void*)tmpStr);
1811 
1812  DPTB(SDsetattr(sdfid, "Suggested Image Scaling Applied", DFNT_CHAR, strlen(imageScalingApplied) + 1,
1813  (VOIDP)imageScalingApplied));
1814  DPTB(SDsetattr(sdfid, "_lastModified", DFNT_CHAR, strlen(metaData->ptime) + 1, (VOIDP)metaData->ptime));
1815 
1816  // delete file data
1817  if (fileData) {
1818  free(fileData);
1819  fileData = NULL;
1820  }
1821 
1822  int32_t dims[2];
1823  dims[0] = height;
1824  dims[1] = width;
1825 
1826  if (!strcmp(productStuff[0]->productInfo->dataType, "byte")) {
1827  hdfDataType = DFNT_INT8;
1828  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1829  int8_t tmp = productStuff[0]->missingValue;
1830  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1831  fileData = allocateMemory(width * sizeof(int8_t), "OutFile_hdf4::open fileData");
1832  } else if (!strcmp(productStuff[0]->productInfo->dataType, "ubyte")) {
1833  hdfDataType = DFNT_UINT8;
1834  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1835  uint8_t tmp = productStuff[0]->missingValue;
1836  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1837  fileData = allocateMemory(width * sizeof(uint8_t), "OutFile_hdf4::open fileData");
1838  } else if (!strcmp(productStuff[0]->productInfo->dataType, "short")) {
1839  hdfDataType = DFNT_INT16;
1840  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1841  int16_t tmp = productStuff[0]->missingValue;
1842  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1843  fileData = allocateMemory(width * sizeof(int16_t), "OutFile_hdf4::open fileData");
1844  } else if (!strcmp(productStuff[0]->productInfo->dataType, "ushort")) {
1845  hdfDataType = DFNT_UINT16;
1846  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1847  uint16_t tmp = productStuff[0]->missingValue;
1848  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1849  fileData = allocateMemory(width * sizeof(uint16_t), "OutFile_hdf4::open fileData");
1850  } else if (!strcmp(productStuff[0]->productInfo->dataType, "int")) {
1851  hdfDataType = DFNT_INT32;
1852  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1853  int32_t tmp = productStuff[0]->missingValue;
1854  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1855  fileData = allocateMemory(width * sizeof(int32_t), "OutFile_hdf4::open fileData");
1856  } else if (!strcmp(productStuff[0]->productInfo->dataType, "uint")) {
1857  hdfDataType = DFNT_UINT32;
1858  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1859  uint32_t tmp = productStuff[0]->missingValue;
1860  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1861  fileData = allocateMemory(width * sizeof(uint32_t), "OutFile_hdf4::open fileData");
1862  } else if (!strcmp(productStuff[0]->productInfo->dataType, "float")) {
1863  hdfDataType = DFNT_FLOAT32;
1864  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1865  float tmp = productStuff[0]->missingValue;
1866  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1867  fileData = allocateMemory(width * sizeof(float), "OutFile_hdf4::open fileData");
1868  } else if (!strcmp(productStuff[0]->productInfo->dataType, "double")) {
1869  hdfDataType = DFNT_FLOAT64;
1870  sdsid = SDcreate(sdfid, "l3m_data", hdfDataType, 2, dims);
1871  double tmp = productStuff[0]->missingValue;
1872  DPTB(SDsetattr(sdsid, "Fill", hdfDataType, 1, (VOIDP)&tmp));
1873  fileData = allocateMemory(width * sizeof(double), "OutFile_hdf4::open fileData");
1874  } else {
1875  printf("-E- Data type %s, not supported\n", productStuff[0]->productInfo->dataType);
1876  exit(EXIT_FAILURE);
1877  }
1878 
1879  tmpStr = "linear";
1880  DPTB(SDsetattr(sdsid, "Scaling", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1881  tmpStr = "(Slope*l3m_data) + Intercept = Parameter value";
1882  DPTB(SDsetattr(sdsid, "Scaling Equation", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1883  DPTB(SDsetattr(sdsid, "Slope", DFNT_FLOAT32, 1, (VOIDP)&tmpScale));
1884  DPTB(SDsetattr(sdsid, "Intercept", DFNT_FLOAT32, 1, (VOIDP)&tmpOffset));
1885 
1886  // create the SST quality data set
1887  if (qualityData) {
1888  quality_sdsid = SDcreate(sdfid, "l3m_qual", DFNT_UINT8, 2, dims);
1889  int32_t validRange[2];
1890  validRange[0] = 0;
1891  validRange[1] = 2;
1892  DPTB(SDsetattr(quality_sdsid, "valid_range", DFNT_INT32, 2, (VOIDP)validRange));
1893  }
1894 
1895  return true;
1896 }
1897 
1899  productStuff[0]->calcOutputLineVals(fileData);
1900 
1901  int32_t start[2];
1902  int32_t count[2];
1903 
1904  start[0] = currentLine;
1905  start[1] = 0;
1906  count[0] = 1;
1907  count[1] = width;
1908 
1909  if ((SDwritedata(sdsid, start, NULL, count, (VOIDP)fileData)) < 0) {
1910  printf("\n-E- OutFile_hdf4::writeLine(): SDwritedata unsuccessful\n");
1911  exit(EXIT_FAILURE);
1912  }
1913 
1914  if (qualityData) {
1915  if ((SDwritedata(quality_sdsid, start, NULL, count, (VOIDP)qualityData)) < 0) {
1916  printf("\n-E- OutFile_hdf4::writeLine(): SDwritedata unsuccessful\n");
1917  exit(EXIT_FAILURE);
1918  }
1919  }
1920 
1921  currentLine++;
1922 }
1923 
1925  if (fileData) {
1926  free(fileData);
1927  fileData = NULL;
1928  }
1929 
1930  if (metaData) {
1931  int32_t tmpInt = metaData->data_bins;
1932  DPTB(SDsetattr(sdfid, "Data Bins", DFNT_INT32, 1, (VOIDP)&tmpInt));
1933  }
1934  float tmpFloat = getFileMinVal();
1935  DPTB(SDsetattr(sdfid, "Data Minimum", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1936  tmpFloat = getFileMaxVal();
1937  DPTB(SDsetattr(sdfid, "Data Maximum", DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1938 
1939  if (qualityData) {
1940  SDendaccess(quality_sdsid);
1941  quality_sdsid = -1;
1942  }
1943  SDendaccess(sdsid);
1944  sdsid = -1;
1945  SDend(sdfid);
1946  sdfid = -1;
1947 
1948  /*-----------------------------------------------------------------------*/
1949  /* write map_palette */
1950 
1951  // make sure a palette has been loaded
1952  if (red && green && blue) {
1953  uint8_t data[768];
1954  int j = 0;
1955  for (int i = 0; i < 256; i++) {
1956  data[j++] = red[i];
1957  data[j++] = green[i];
1958  data[j++] = blue[i];
1959  }
1960 
1961  if ((DFPaddpal(fileName.c_str(), (VOIDP)data)) < 0) {
1962  printf("-E- OutFile_hdf4::close - Error writing map_palette.\n");
1963  return false;
1964  }
1965 
1966  uint16_t pal_ref;
1967  if ((pal_ref = DFPlastref()) > 0) {
1968  if ((DFANputlabel(fileName.c_str(), DFTAG_IP8, pal_ref, (char*)"palette")) < 0) {
1969  printf("-E- OutFile_hdf4::close - Error writing palette label\n");
1970  return false;
1971  }
1972  }
1973  }
1974  return true;
1975 }
1976 
1977 int32_t OutFile_hdf4::addProduct(productInfo_t* productInfo) {
1978  return addProductNonDisplay(productInfo);
1979 }
1980 
1981 //------------------------------------------------------------------------------
1982 // OutFile_netcdf4
1983 //------------------------------------------------------------------------------
1984 
1985 using namespace netCDF;
1986 
1988  ncFile = NULL;
1989  fileData = NULL;
1991 }
1992 
1994  if (fileData) {
1995  free(fileData);
1996  fileData = NULL;
1997  }
1998 }
1999 
2000 void OutFile_netcdf4::setSize(int32_t width, int32_t height) {
2002  if (fileData) {
2003  free(fileData);
2004  fileData = NULL;
2005  }
2006 }
2007 
2008 // modifications must be done here
2010  const char* tmpStr;
2011  currentLine = 0;
2012 
2013  try {
2014  // open file
2015  ncFile = new NcFile(fileName.c_str(), NcFile::replace);
2016 
2017  // write global metadata
2018  string prodName;
2019  size_t pos = fileName.find_last_of('/');
2020  if (pos == string::npos)
2021  prodName = fileName;
2022  else
2023  prodName = fileName.substr(pos + 1);
2024  ncFile->putAtt("product_name", prodName.c_str());
2025 
2026  ncFile->putAtt("instrument", metaData->sensor);
2027  std::string source = "satellite observations from ";
2028  source += metaData->sensor;
2029  ncFile->putAtt("title", metaData->title);
2030  ncFile->putAtt("project", PROJECT);
2031 
2032  if (strcmp(metaData->mission, "") != 0) {
2033  ncFile->putAtt("platform", metaData->mission);
2034  source += "-";
2035  source += metaData->mission;
2036  }
2037  ncFile->putAtt("source", source);
2038 
2039  ncFile->putAtt("temporal_range", metaData->prod_type);
2040  ncFile->putAtt("processing_version", metaData->pversion);
2041 
2043  ncFile->putAtt("date_created", metaData->ptime);
2044  ncFile->putAtt("history", metaData->proc_con);
2045 
2046  ncFile->putAtt("l2_flag_names", metaData->flag_names);
2047 
2048  ncFile->putAtt("time_coverage_start", unix2isodate(metaData->startTime, 'G'));
2049  ncFile->putAtt("time_coverage_end", unix2isodate(metaData->endTime, 'G'));
2050  ncFile->putAtt("start_orbit_number", ncInt, metaData->start_orb);
2051  ncFile->putAtt("end_orbit_number", ncInt, metaData->end_orb);
2052  ncFile->putAtt("map_projection", mapProjection.c_str());
2053 
2054  ncFile->putAtt("latitude_units", metaData->lat_units);
2055  ncFile->putAtt("longitude_units", metaData->lon_units);
2056 
2057  ncFile->putAtt("northernmost_latitude", ncFloat, metaData->north);
2058  ncFile->putAtt("southernmost_latitude", ncFloat, metaData->south);
2059  ncFile->putAtt("westernmost_longitude", ncFloat, metaData->west);
2060  ncFile->putAtt("easternmost_longitude", ncFloat, metaData->east);
2061  ncFile->putAtt("geospatial_lat_max", ncFloat, metaData->north);
2062  ncFile->putAtt("geospatial_lat_min", ncFloat, metaData->south);
2063  ncFile->putAtt("geospatial_lon_max", ncFloat, metaData->east);
2064  ncFile->putAtt("geospatial_lon_min", ncFloat, metaData->west);
2065 
2066  double latStep = (metaData->north - metaData->south) / (float)getHeight();
2067  double lonStep;
2068  if (metaData->east < metaData->west)
2069  lonStep = (360 + metaData->east - metaData->west) / (float)getWidth();
2070  else
2071  lonStep = (metaData->east - metaData->west) / (float)getWidth();
2072  ncFile->putAtt("latitude_step", ncFloat, latStep);
2073  ncFile->putAtt("longitude_step", ncFloat, lonStep);
2074  ncFile->putAtt("sw_point_latitude", ncFloat, metaData->south + latStep / 2.0);
2075  ncFile->putAtt("sw_point_longitude", ncFloat, metaData->west + lonStep / 2.0);
2076 
2077  string resolutionStr = resolution2string(resolution);
2078  ncFile->putAtt("spatialResolution", resolutionStr);
2079  ncFile->putAtt("geospatial_lon_resolution", resolutionStr);
2080  ncFile->putAtt("geospatial_lat_resolution", resolutionStr);
2081  ncFile->putAtt("geospatial_lat_units", metaData->lat_units);
2082  ncFile->putAtt("geospatial_lon_units", metaData->lon_units);
2083 
2084  ncFile->putAtt("number_of_lines", ncInt, height);
2085  ncFile->putAtt("number_of_columns", ncInt, width);
2086  ncFile->putAtt("measure", "Mean"); // FIXME
2087 
2088  ncFile->putAtt("suggested_image_scaling_minimum", ncFloat, productStuff[0]->productInfo->displayMin);
2089  ncFile->putAtt("suggested_image_scaling_maximum", ncFloat, productStuff[0]->productInfo->displayMax);
2090  if (!strcmp(productStuff[0]->productInfo->displayScale, "log"))
2091  tmpStr = "LOG";
2092  else if (!strcmp(productStuff[0]->productInfo->displayScale, "arctan"))
2093  tmpStr = "ATAN";
2094  else
2095  tmpStr = "LINEAR";
2096  ncFile->putAtt("suggested_image_scaling_type", tmpStr);
2097  ncFile->putAtt("suggested_image_scaling_applied", "No");
2098 
2099  ncFile->putAtt("_lastModified", metaData->ptime);
2100  ncFile->putAtt("Conventions", "CF-1.6 ACDD-1.3");
2101  ncFile->putAtt("institution", INSTITUTION);
2102  ncFile->putAtt("standard_name_vocabulary", STDNAME_VOCABULARY);
2103  ncFile->putAtt("naming_authority", NAMING_AUTHORITY);
2104 
2105  // create id
2106  string id = metaData->pversion;
2107  if (id == "Unspecified") {
2108  id = "L3/";
2109  } else {
2110  id += "/L3/";
2111  }
2112  id += metaData->product_name;
2113  ncFile->putAtt("id", id);
2114 
2115  ncFile->putAtt("license", LICENSE);
2116  ncFile->putAtt("creator_name", CREATOR_NAME);
2117  ncFile->putAtt("publisher_name", PUBLISHER_NAME);
2118  ncFile->putAtt("creator_email", CREATOR_EMAIL);
2119  ncFile->putAtt("publisher_email", PUBLISHER_EMAIL);
2120  ncFile->putAtt("creator_url", CREATOR_URL);
2121  ncFile->putAtt("publisher_url", PUBLISHER_URL);
2122 
2123  ncFile->putAtt("processing_level", "L3 Mapped");
2124  ncFile->putAtt("cdm_data_type", "grid"); // deprecated?
2125  if (proj4String.length() > 0)
2126  ncFile->putAtt("proj4_string", proj4String);
2127 
2128  // Some missions have DOIs
2129  if (clo_isSet(optionList, "doi")) {
2130  ncFile->putAtt("identifier_product_doi_authority", "http://dx.doi.org");
2131  ncFile->putAtt("identifier_product_doi", clo_getString(optionList, "doi"));
2132  }
2133  if (clo_isSet(optionList, "suite")) {
2134  const char* keywordStr = getGCMDKeywords(clo_getString(optionList, "suite"));
2135  if (keywordStr) {
2136  ncFile->putAtt("keywords", keywordStr);
2137  ncFile->putAtt("keywords_vocabulary", KEYWORDS_VOCABULARY);
2138  }
2139  } // suite was set
2140 
2141  // create group: processing_control
2142  NcGroup grp1 = ncFile->addGroup("processing_control");
2143  grp1.putAtt("software_name", metaData->soft_name);
2144  grp1.putAtt("software_version", metaData->soft_ver);
2145  if ((tmpStr = strrchr(metaData->infiles, '/')) != NULL)
2146  tmpStr++;
2147  else
2148  tmpStr = metaData->infiles;
2149  grp1.putAtt("input_sources", tmpStr);
2150  grp1.putAtt("l2_flag_names", metaData->flag_names);
2151 
2152  // create sub-group: input_parameters
2153  NcGroup grp2 = grp1.addGroup("input_parameters");
2154  char buf[2048];
2155  char* end_str;
2156  char* token = strtok_r(metaData->input_parms, "|", &end_str);
2157  while (token != NULL) {
2158  char* end_token;
2159  strcpy(buf, token);
2160  char* name = strtok_r(token, "=", &end_token);
2161  for (uint32_t i = 0; i < strlen(name); i++) {
2162  if (name[i] == ' ') {
2163  name[i] = 0;
2164  break;
2165  }
2166  }
2167  char* val = strtok_r(NULL, "|", &end_token);
2168  if (val == NULL)
2169  val = "";
2170  strcpy(buf, val);
2171  grp2.putAtt(name, buf);
2172  token = strtok_r(NULL, "|", &end_str);
2173  }
2174 
2175  // Define dimensions and coordinate variables
2176  vector<NcDim> dimIds;
2177  string coordinates;
2178 
2179  if (mapProjection == "Equidistant Cylindrical" // SMI
2180  || mapProjection == "PlateCarree" || (proj4String.find("+proj=eqc") != string::npos)) {
2181  dimIds.push_back(ncFile->addDim("lat", height));
2182  dimIds.push_back(ncFile->addDim("lon", width));
2183 
2184  if (fullLatLon != LatLonOff)
2185  fullLatLon = LatLon1D;
2186  } else {
2187  dimIds.push_back(ncFile->addDim("y", height));
2188  dimIds.push_back(ncFile->addDim("x", width));
2189  if (fullLatLon != LatLonOff) {
2190  fullLatLon = LatLon2D;
2191  coordinates = "lat lon";
2192  }
2193  }
2194 
2195  // Define variables
2196  size_t dataSize = 1;
2197  vector<NcDim> dimIds_2D;
2198  vector<NcDim> dimIds_3D;
2199  std::copy(dimIds.begin(), dimIds.end(), std::back_inserter(dimIds_2D));
2200 
2201  if (!get_wv3d_2d_name_to_3d_expansion().empty()) {
2202  std::copy(dimIds.begin(), dimIds.end(), std::back_inserter(dimIds_3D));
2203  dimIds_3D.push_back(ncFile->addDim("wavelength", get_len_wv3d()));
2204  // { std::cout << "Wavelength 3D is " << get_len_wv3d() << std::endl; }
2205 
2206  vector<NcDim> dimIdswv3d = {dimIds_3D[2]};
2207  NcVar var = ncFile->addVar("wavelength", ncInt, dimIdswv3d);
2208  var.putAtt("long_name", "wavelengths");
2209  var.putAtt("units", "nm");
2210  var.putAtt("_FillValue", ncInt, -32767);
2211  var.putAtt("valid_min", ncInt, 0);
2212  var.putAtt("valid_max", ncInt, 20000);
2213  auto data = (*get_wv3d_2d_name_to_3d_expansion().begin()).second;
2214  var.putVar(data.data());
2215  }
2216  auto dimIds_to_set = &dimIds_2D;
2217  size_t count_3d_counter = 0;
2218  for (size_t prodNum = 0; prodNum < productStuff.size(); prodNum++) {
2219  // determine maximum product size
2220  NcType varDataType = getDataType(productStuff[prodNum]->dataStorage);
2221  dataSize = std::max(dataSize, varDataType.getSize());
2222 
2223  // create variable
2224  productInfo_t* pInfo = productStuff[prodNum]->productInfo;
2225  std::string temp_wave_name = pInfo->paramDesignator;
2226  std::string temp_prefix = pInfo->prefix;
2227  std::string temp_descp = pInfo->description;
2228 
2230  std::string full_prod_name = getProductNameFull(pInfo);
2231  const std::string suffix_prod = pInfo->suffix;
2232  if (!suffix_prod.empty()) {
2233  // std::cout << "Prod " << full_prod_name << " has suffix "
2234  // << suffix_prod << std::endl;
2235  std::size_t pos = full_prod_name.find(suffix_prod);
2236  // std::cout << "Position is here " << pos << "\n";
2237  full_prod_name = full_prod_name.substr(0, pos);
2238  // std::cout << "Name without a suffix " << full_prod_name
2239  // << std::endl;
2240  }
2241  if (wv3d_3d_name_to_2d_name.count(full_prod_name) > 0) {
2242  const auto prod_name_no_suffix = wv3d_3d_name_to_2d_name.at(full_prod_name);
2243  const auto prod_name = prod_name_no_suffix + suffix_prod;
2244 
2245  if (product_3d_already_set.count(prod_name) > 0) {
2246  product_3d_already_set.at(prod_name)++;
2247  slice_2d_in_wv3d[prodNum] = product_3d_already_set.at(prod_name);
2248  index_2d_3d[prodNum] = index_2d_3d.at(prod2d_indexes_last_index.at(prod_name));
2249  continue;
2250  } else {
2251  product_3d_already_set[prod_name] = 0;
2252  slice_2d_in_wv3d[prodNum] = 0;
2253  }
2254  prod2d_indexes_last_index[prod_name] = prodNum;
2255  // std::cout << "Created 3D nc product name " << prod_name
2256  // << std::endl;
2257  // printf("%s = %d = %s\n", pInfo->prefix, pInfo->prod_ix,
2258  // pInfo->suffix);
2259 
2260  // std::cout << "Prod name " << prod_name << " "
2261  // << pInfo->productName << std::endl;
2262  dimIds_to_set = &dimIds_3D;
2263  if (pInfo->paramDesignator)
2264  free(pInfo->paramDesignator);
2265  if (pInfo->prefix)
2266  free(pInfo->prefix);
2267  const auto new_desc = remove_wv_from_long_name(pInfo->description);
2268  if (pInfo->description)
2269  free(pInfo->description);
2270  pInfo->paramDesignator = strdup("none");
2271  pInfo->prefix = strdup(prod_name_no_suffix.c_str());
2272  pInfo->description = strdup(new_desc.c_str());
2273  // {
2274  // std::cout << "Prefix is now " << pInfo->prefix << std::endl;
2275  // std::cout << "New Name is " << getProductNameFull(pInfo)
2276  // << std::endl;
2277  // }
2278  } else {
2279  dimIds_to_set = &dimIds_2D;
2280  }
2281  NcVar var = createProduct(pInfo, varDataType, *dimIds_to_set);
2282  // {
2283  // std::cout << "New var has been created "
2284  // << getProductNameFull(pInfo) << std::endl;
2285  // }
2286  index_2d_3d[prodNum] = count_3d_counter;
2287  count_3d_counter++;
2288  // reset pInfo to default
2289  {
2290  // {
2291  // std::cout << "temp_wave_name = " << temp_wave_name
2292  // << std::endl;
2293  // std::cout << "temp_prefix = " << temp_prefix << std::endl;
2294  // std::cout << "temp_descp = " << temp_descp << std::endl;
2295  // }
2296  if (wv3d_3d_name_to_2d_name.count(full_prod_name) > 0) {
2297  free(pInfo->paramDesignator);
2298  free(pInfo->prefix);
2299  free(pInfo->description);
2300  pInfo->paramDesignator = strdup(temp_wave_name.c_str());
2301  pInfo->prefix = strdup(temp_prefix.c_str());
2302  pInfo->description = strdup(temp_descp.c_str());
2303  }
2304  // std::cout << "prodNum = " << prodNum << "; Old Name is "
2305  // << getProductNameFull(pInfo) << std::endl;
2306  }
2307  initCompression(var);
2308  prodVars.push_back(var);
2309 
2310  // add display info
2311  var.putAtt("display_scale", pInfo->displayScale);
2312  var.putAtt("display_min", ncFloat, pInfo->displayMin);
2313  var.putAtt("display_max", ncFloat, pInfo->displayMax);
2314 
2315  // specify coordinates as needed
2316  if (coordinates.length() > 0)
2317  var.putAtt("coordinates", coordinates);
2318 
2319  } // for prodNum
2320  // {
2321  // for (const auto& pair : slice_2d_in_wv3d) {
2322  // std::cout << "prod number = " << pair.first
2323  // << " prod index = " << pair.second << std::endl;
2324  // }
2325  // for (const auto& var : prodVars) {
2326  // std::cout << var.getName() << " " << var.getDimCount()
2327  // << std::endl;
2328  // for (const auto& dim : var.getDims()) {
2329  // std::cout << dim.getName() << " " << dim.getSize() << "; ";
2330  // }
2331  // std::cout << "\n";
2332  // }
2333  // for (const auto& prodindexes : index_2d_3d) {
2334  // std::cout << "2d index " << prodindexes.first
2335  // << " 3d index = " << prodindexes.second << std::endl;
2336  // }
2337  // }
2338  // allocate buffer big enough for one line of the largest data type
2339  if (fileData)
2340  free(fileData);
2341  fileData = allocateMemory(width * dataSize, "OutFile_netcdf4::open fileData");
2342 
2343  // add the quality variable
2344  if (qualityData) {
2345  productInfo_t* qInfo = allocateProductInfo();
2346  if (qualityName.empty()) {
2347  qualityName = (string) "qual_" + getProductNameFull(productStuff[0]->productInfo);
2348  }
2349  if (!findProductInfo(qualityName.c_str(), metaData->sensorID, qInfo)) {
2350  cerr << "-E- OutFile_netcdf4::open - cannot find product " << qualityName << " in product.xml"
2351  << endl;
2352  exit(EXIT_FAILURE);
2353  }
2354  qInfo->fillValue = NC_FILL_UBYTE;
2355  qualVar = createProduct(qInfo, ncUbyte, dimIds);
2356  initCompression(qualVar);
2357  freeProductInfo(qInfo);
2358  }
2359 
2360  // add latitude and longitude variables
2361 
2362  productInfo_t* latInfo = allocateProductInfo();
2363  if (!findProductInfo("lat", metaData->sensorID, latInfo)) {
2364  cerr << "-E- OutFile_netcdf4::open - "
2365  "cannot find \"lat\" in product.xml"
2366  << endl;
2367  exit(EXIT_FAILURE);
2368  }
2369  productInfo_t* lonInfo = allocateProductInfo();
2370  if (!findProductInfo("lon", metaData->sensorID, lonInfo)) {
2371  cerr << "-E- OutFile_netcdf4::open - "
2372  "cannot find \"lon\" in product.xml"
2373  << endl;
2374  exit(EXIT_FAILURE);
2375  }
2376 
2377  if (fullLatLon == LatLon1D) {
2378  float* latarray = (float*)allocateMemory(getHeight() * sizeof(float), "latarray");
2379  for (int i = 0; i < getHeight(); i++)
2380  latarray[i] = metaData->north - latStep * i - latStep / 2.0;
2381  vector<NcDim> latDim;
2382  latDim.push_back(dimIds[0]);
2383  NcVar lat = createProduct(latInfo, ncFloat, latDim);
2384  lat.putVar(latarray);
2385  free(latarray);
2386 
2387  float* lonarray = (float*)allocateMemory(getWidth() * sizeof(float), "lonarray");
2388  for (int i = 0; i < getWidth(); i++) {
2389  lonarray[i] = metaData->west + lonStep * i + lonStep / 2.0;
2390  if(lonarray[i] > 180.0)
2391  lonarray[i] -= 360.0;
2392  }
2393  vector<NcDim> lonDim;
2394  lonDim.push_back(dimIds[1]);
2395  NcVar lon = createProduct(lonInfo, ncFloat, lonDim);
2396  lon.putVar(lonarray);
2397  free(lonarray);
2398  }
2399  else if (fullLatLon == LatLon2D) {
2400  latVar = createProduct(latInfo, ncFloat, dimIds);
2401  lonVar = createProduct(lonInfo, ncFloat, dimIds);
2402  initCompression(latVar);
2403  initCompression(lonVar);
2404  }
2405 
2406  freeProductInfo(latInfo);
2407  freeProductInfo(lonInfo);
2408 
2409  // store palette
2410  if (red && green && blue) {
2411  uint8_t data[768];
2412  int j = 0;
2413  for (int i = 0; i < 256; i++) {
2414  data[j++] = red[i];
2415  data[j++] = green[i];
2416  data[j++] = blue[i];
2417  }
2418  vector<NcDim> dimIds;
2419  dimIds.push_back(ncFile->addDim("rgb", 3));
2420  dimIds.push_back(ncFile->addDim("eightbitcolor", 256));
2421  NcVar var = ncFile->addVar("palette", ncUbyte, dimIds);
2422  var.putVar(data);
2423  }
2424 
2425  } catch (std::exception const& e) {
2426  cerr << "Exception: " << e.what() << endl;
2427  }
2428 
2429  return true;
2430 }
2431 // modifications must be done here
2433  vector<size_t> start(2);
2434  vector<size_t> count(2);
2435  start[0] = currentLine;
2436  start[1] = 0;
2437  count[0] = 1;
2438  count[1] = width;
2439  vector<size_t> start_3D = {start[0], start[1], 0};
2440  vector<size_t> count_3D = {count[0], count[1], 1};
2441  // calculate and write one line of data for each product
2442  for (size_t prodNum = 0; prodNum < productStuff.size(); prodNum++) {
2443  productStuff[prodNum]->calcOutputLineVals(fileData);
2444  const auto index_in_products = index_2d_3d.at(prodNum);
2445  // {
2446  // std::cout <<"\nWriting " << currentLine << " " << prodNum << "
2447  // :" << index_in_products << std::endl;
2448  // }
2449  if (slice_2d_in_wv3d.count(prodNum) == 0) {
2450  prodVars[index_in_products].putVar(start, count, fileData);
2451  } else {
2452  const auto slice_to_put = slice_2d_in_wv3d.at(prodNum);
2453  start_3D[2] = slice_to_put;
2454  prodVars[index_in_products].putVar(start_3D, count_3D, fileData);
2455  }
2456  }
2457 
2458  // write quality data for this line
2459  if (qualityData) {
2460  qualVar.putVar(start, count, qualityData);
2461  }
2462 
2463  // write lat, lon for this line
2464  if (fullLatLon == LatLon2D) {
2465  if (latData)
2466  latVar.putVar(start, count, latData);
2467  if (lonData)
2468  lonVar.putVar(start, count, lonData);
2469  }
2470 
2471  currentLine++;
2472 }
2473 
2475  if (metaData) {
2476  ncFile->putAtt("data_bins", ncInt64, metaData->data_bins);
2477  if (metaData->data_bins <= 0) {
2478  ncFile->putAtt("data_minimum", ncFloat, 0.0);
2479  ncFile->putAtt("data_maximum", ncFloat, 0.0);
2480  } else {
2481  ncFile->putAtt("data_minimum", ncFloat, (float)getFileMinVal());
2482  ncFile->putAtt("data_maximum", ncFloat, (float)getFileMaxVal());
2483  }
2484  }
2485  ncFile->close();
2486  prodVars.clear();
2487 
2488  if (fileData) {
2489  free(fileData);
2490  fileData = NULL;
2491  }
2492  if (qualityData) {
2493  free(qualityData);
2494  qualityData = NULL;
2495  }
2496 
2497  return true;
2498 }
2499 
2500 int32_t OutFile_netcdf4::addProduct(productInfo_t* productInfo) {
2501  return addProductNonDisplay(productInfo);
2502 }
2503 
2504 void OutFile_netcdf4::initCompression(NcVar var) {
2505  // if deflate level below 0 then don't deflate
2506  if (getDeflate() < 1)
2507  return;
2508 
2509  vector<NcDim> dims = var.getDims();
2510  vector<size_t> chunksize;
2511  /*
2512  * vary chunk size based on dimensions
2513  * looking to keep the chunks around 32Kb, hopefully no larger than 200Kb
2514  */
2515 
2516  switch(dims.size()) {
2517  case 1:
2518  chunksize.push_back(MIN(dims[0].getSize(), 2048));
2519  break;
2520  case 2:
2521  chunksize.push_back(MIN(dims[0].getSize(), 512));
2522  chunksize.push_back(MIN(dims[1].getSize(), 1024));
2523  break;
2524  case 3:
2525  chunksize.push_back(MIN(dims[0].getSize(), 16));
2526  chunksize.push_back(MIN(dims[1].getSize(), 1024));
2527  chunksize.push_back(MIN(dims[2].getSize(), 8));
2528  break;
2529  default:
2530  printf("-E- OutFile_netcdf4::initCompression - bad rank for variable %s\n", var.getName().c_str());
2531  exit(EXIT_FAILURE);
2532  }
2533 
2534  var.setChunking(NcVar::nc_CHUNKED, chunksize);
2535  var.setCompression(true, true, getDeflate());
2536 }
2537 
2538 NcVar OutFile_netcdf4::createProduct(productInfo_t* pInfo, const NcType& ncType,
2539  const std::vector<netCDF::NcDim> ncDim) {
2540  // create variable
2541  NcVar var = ncFile->addVar(getProductNameFull(pInfo), ncType, ncDim);
2542 
2543  // add standard metadata
2544  if (pInfo->description)
2545  var.putAtt("long_name", pInfo->description);
2546  if (pInfo->scaleFactor != 1.0 || pInfo->addOffset != 0.0) {
2547  var.putAtt("scale_factor", ncFloat, pInfo->scaleFactor);
2548  var.putAtt("add_offset", ncFloat, pInfo->addOffset);
2549  }
2550  if (pInfo->units != NULL && strcmp(pInfo->units, "dimensionless") != 0)
2551  var.putAtt("units", pInfo->units);
2552  if (pInfo->standardName != NULL && strcmp(pInfo->standardName, "") != 0)
2553  var.putAtt("standard_name", pInfo->standardName);
2554  try {
2555  if (pInfo->fillValue)
2556  var.putAtt("_FillValue", ncType, pInfo->fillValue);
2557  } catch (std::exception const& e) {
2558  cerr << "FillValue exception: " << e.what() << endl;
2559  }
2560  if (pInfo->validMin != PRODUCT_DEFAULT_validMin || pInfo->validMax != PRODUCT_DEFAULT_validMax) {
2561  var.putAtt("valid_min", ncType, (pInfo->validMin - pInfo->addOffset) / pInfo->scaleFactor);
2562  var.putAtt("valid_max", ncType, (pInfo->validMax - pInfo->addOffset) / pInfo->scaleFactor);
2563  }
2564  if (pInfo->reference != NULL && strcmp(pInfo->reference, "") != 0)
2565  var.putAtt("reference", pInfo->reference);
2566  if (pInfo->comment != NULL && strcmp(pInfo->comment, "") != 0)
2567  var.putAtt("comment", pInfo->comment);
2568 
2569  return var;
2570 }
2571 
2572 NcType OutFile_netcdf4::getDataType(DataStorage dataStorage) {
2573  switch (dataStorage) {
2574  case ByteDS:
2575  return NC_BYTE; // ncByte
2576  case UByteDS:
2577  return NC_UBYTE; // ncUbyte
2578  case ShortDS:
2579  return NC_SHORT; // ncShort
2580  case UShortDS:
2581  return NC_USHORT; // ncUshort
2582  case IntDS:
2583  return NC_INT; // ncInt
2584  case UIntDS:
2585  return NC_UINT; // ncUint
2586  case FloatDS:
2587  return NC_FLOAT; // ncFloat
2588  case DoubleDS:
2589  return NC_DOUBLE; // ncDouble
2590  default:
2591  cerr << "-E- OutFile_netcdf4::getDataType - illegal data storage "
2592  "type = "
2593  << dataStorage << endl;
2594  exit(EXIT_FAILURE);
2595  }
2596 }
char * ydhmsf(double dtime, char zone)
Definition: ydhmsf.c:12
virtual void fillPixel(int32_t x)
Definition: OutFile.cpp:827
virtual void setMetaData(meta_l3bType *metaData)
Definition: OutFile.cpp:503
virtual void writeLine()
Definition: OutFile.cpp:1473
virtual bool open()
Definition: OutFile.cpp:1654
char product_name[SM_ATTRSZ]
Definition: meta_l3b.h:16
#define MIN(x, y)
Definition: rice.h:169
int r
Definition: decode_rs.h:73
virtual void setPixel(int32_t x, double val, int32_t prod=0)
Definition: OutFile.cpp:385
virtual bool close()
Definition: OutFile.cpp:1090
void red(int iz1, int iz2, int jz1, int jz2, int jm1, int jm2, int jmf, int ic1, int jc1, int jcf, int kc, float ***c, float **s)
int16 eday
Definition: l1_czcs_hdf.c:17
virtual int addProductNonDisplay(productInfo_t *productInfo)
Definition: OutFile.cpp:531
std::unordered_map< size_t, size_t > index_2d_3d
Definition: OutFile.h:108
virtual bool open()
Definition: OutFile.cpp:676
std::string qualityName
Definition: OutFile.h:115
void setScaleOffset(double scale, double offset, ScaleType scaleType)
Definition: OutFile.cpp:158
void freeProductInfo(productInfo_t *info)
int j
Definition: decode_rs.h:73
const char * getGCMDKeywords(const char *suite)
char * clo_getString(clo_optionList_t *list, const char *key)
Definition: clo.c:1357
virtual bool open()
Definition: OutFile.cpp:763
virtual void writeLine()
Definition: OutFile.cpp:1353
virtual void landPixel(int32_t x)
Definition: OutFile.cpp:418
char station[SM_ATTRSZ]
Definition: meta_l3b.h:25
virtual void setPixelRGB(int32_t x, float red, float green, float blue)
Definition: OutFile.cpp:397
virtual int32_t getHeight() const
Definition: OutFile.cpp:377
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
FILE * outfp
Definition: OutFile.h:252
void calcOutputLineVals(void *lineBuffer) const
Definition: OutFile.cpp:247
virtual void writeLine()
Definition: OutFile.cpp:857
virtual int addProduct(productInfo_t *productInfo)
Definition: OutFile.cpp:1977
#define PRODUCT_DEFAULT_validMax
Definition: productInfo.h:35
#define STDNAME_VOCABULARY
Definition: OutFile.h:31
virtual void writeLine()
Definition: OutFile.cpp:728
virtual void resetFileMinMax()
Definition: OutFile.cpp:617
char infiles[LG_ATTRSZ]
Definition: meta_l3b.h:38
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
#define FALSE
Definition: rice.h:164
virtual void missingPixel(int32_t x)
Definition: OutFile.cpp:440
#define NULL
Definition: decode_rs.h:63
double * latData
Definition: OutFile.h:127
char mission[SM_ATTRSZ]
Definition: meta_l3b.h:21
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 out
Definition: HISTORY.txt:422
std::string fileName
Definition: OutFile.h:111
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:2000
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that resolution
Definition: HISTORY.txt:188
@ ByteDS
Definition: OutFile.h:57
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:756
@ LatLonOff
Definition: OutFile.h:65
virtual void writeLine()
Definition: OutFile.cpp:689
ProductStuff(int32_t width, const productInfo_t *productInfo, double landPixelValue)
Definition: OutFile.cpp:75
const std::unordered_map< std::string, std::string > & get_wv3d_3d_name_to_2d_name()
Definition: l3mapgen.cpp:57
char sensor_char[SM_ATTRSZ]
Definition: meta_l3b.h:24
std::unordered_map< size_t, size_t > slice_2d_in_wv3d
Definition: OutFile.h:109
#define PUBLISHER_URL
Definition: OutFile.h:38
double * lonData
Definition: OutFile.h:128
virtual void writeLine()
Definition: OutFile.cpp:977
int32_t start_orb
Definition: meta_l3b.h:42
char input_parms[LG_ATTRSZ]
Definition: meta_l3b.h:36
virtual ~OutFile_tiff_rgb()
Definition: OutFile.cpp:1457
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:1340
std::string mapProjection
Definition: OutFile.h:137
int clo_isSet(clo_optionList_t *list, const char *key)
Definition: clo.c:2270
float32 * pos
Definition: l1_czcs_hdf.c:35
#define TRUE
Definition: rice.h:165
ScaleType
Definition: OutFile.h:52
virtual bool getQualityProcessing()
Definition: OutFile.cpp:646
int16 eyear
Definition: l1_czcs_hdf.c:17
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
std::vector< ProductStuff * > productStuff
Definition: OutFile.h:143
double calcOutputVal(double val) const
Definition: OutFile.cpp:177
virtual std::string getScaleTypeString(int32_t prod=0)
Definition: OutFile.cpp:346
int syear
Definition: l1_czcs_hdf.c:15
#define CREATOR_EMAIL
Definition: OutFile.h:33
string prodName
Definition: l3mapgen.cpp:99
@ IntDS
Definition: OutFile.h:57
virtual void writeLine()
Definition: OutFile.cpp:2432
ScaleType scaleType
Definition: OutFile.h:74
@ FloatDS
Definition: OutFile.h:57
virtual void landPixel(int32_t x)
Definition: OutFile.cpp:812
char flag_names[SM_ATTRSZ]
Definition: meta_l3b.h:37
double fileMaxVal
Definition: OutFile.h:122
double calcPhysicalVal(double val) const
Definition: OutFile.cpp:215
bool applyMask
Definition: l3mapgen.cpp:107
#define NAMING_AUTHORITY
Definition: OutFile.h:26
int32 smsec
Definition: l1_czcs_hdf.c:16
virtual bool close()
Definition: OutFile.cpp:696
@ string
virtual void fillPixel(int32_t x)
Definition: OutFile.cpp:429
TIFF * tiff
Definition: OutFile.h:339
uint8_t * qualityData
Definition: OutFile.h:116
#define LICENSE
Definition: OutFile.h:25
virtual void landPixel(int32_t x)
Definition: OutFile.cpp:1558
virtual ~OutFile_hdf4()
Definition: OutFile.cpp:1642
#define PUBLISHER_EMAIL
Definition: OutFile.h:37
virtual void fillPixel(int32_t x)
Definition: OutFile.cpp:1165
virtual void setMapProjection(std::string projection)
Definition: OutFile.cpp:579
int sday
Definition: l1_czcs_hdf.c:15
#define DPTB(function)
Definition: passthebuck.h:24
int32_t height
Definition: OutFile.h:113
float station_lon
Definition: meta_l3b.h:27
uint8_t * fileData
Definition: OutFile.h:253
uint8_t * blue
Definition: OutFile.h:132
double fileMinVal
Definition: OutFile.h:121
virtual void setLandRGB(const char *rgb_land_string)
Definition: OutFile.cpp:494
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:358
virtual void setPixel(int32_t x, double val, int32_t prod=0)
Definition: OutFile.cpp:783
#define PUBLISHER_NAME
Definition: OutFile.h:36
char sensor[SM_ATTRSZ]
Definition: meta_l3b.h:23
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:706
double landPixelValue
Definition: OutFile.h:107
virtual ~OutFile_ppm_rgb()
Definition: OutFile.cpp:749
char lon_units[SM_ATTRSZ]
Definition: meta_l3b.h:45
data_t tmp
Definition: decode_rs.h:74
virtual void setTiffColor()=0
GTIF * gtif
Definition: OutFile.h:340
double endTime
Definition: meta_l3b.h:40
double resolution
Definition: OutFile.h:123
virtual ~OutFile_tiff_gray()
Definition: OutFile.cpp:1425
productInfo_t * allocateProductInfo()
void get_time(char *pr_time)
Definition: get_time.c:28
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:1647
virtual bool open()
Definition: OutFile.cpp:2009
std::unordered_map< std::string, std::string > wv3d_3d_name_to_2d_name
Definition: l3mapgen.cpp:48
char * strdup(const char *)
char prod_type[SM_ATTRSZ]
Definition: meta_l3b.h:29
void setScale(double min, double max, ScaleType scaleType)
Definition: OutFile.cpp:120
virtual void setResolution(std::string resolutionStr)
virtual bool setPalette(const char *paletteName, bool applyMask)
Definition: OutFile.cpp:459
virtual void missingPixel(int32_t x)
Definition: OutFile.cpp:1187
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:882
double string2resolution(std::string resolutionStr)
static constexpr double badPixelValue
Definition: OutFile.h:106
virtual int addProduct(productInfo_t *productInfo)
Definition: OutFile.cpp:2500
@ LatLon1D
Definition: OutFile.h:65
#define INSTITUTION
Definition: OutFile.h:24
virtual float getPercentFilledPixels()
Definition: OutFile.cpp:609
char data_center[SM_ATTRSZ]
Definition: meta_l3b.h:20
virtual void fillPixel(int32_t x)
Definition: OutFile.cpp:1582
virtual double getFileMinVal()
Definition: OutFile.h:204
#define CREATOR_NAME
Definition: OutFile.h:32
virtual void missingPixel(int32_t x)
Definition: OutFile.cpp:842
virtual ~OutFile_png()
Definition: OutFile.cpp:875
std::string proj4String
Definition: OutFile.h:139
virtual int32_t getNumFilledPixels()
Definition: OutFile.cpp:602
@ DoubleDS
Definition: OutFile.h:57
virtual void writeLine()
Definition: OutFile.cpp:1437
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:1430
virtual ~OutFile_tiff()
Definition: OutFile.cpp:1223
void unix2yds(double usec, short *year, short *day, double *secs)
double tiepoints[6]
Definition: OutFile.h:140
virtual void writeLine()
Definition: OutFile.cpp:1209
virtual void setPixelRGB(int32_t x, float red, float green, float blue)
Definition: OutFile.cpp:1523
virtual bool close()
Definition: OutFile.cpp:777
@ landPix
Definition: OutFile.h:61
#define KEYWORDS_VOCABULARY
Definition: OutFile.h:27
virtual void setTiffColor()
Definition: OutFile.cpp:1385
virtual void missingPixel(int32_t x)
Definition: OutFile.cpp:1606
virtual ~OutFile_tiff_color()
Definition: OutFile.cpp:1335
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
float north
Definition: meta_l3b.h:49
std::string resolution2string(double resolution)
LatLonType fullLatLon
Definition: OutFile.h:126
size_t get_len_wv3d()
Definition: l3mapgen.cpp:61
virtual void setQuality(int32_t x, uint8_t val)
Definition: OutFile.cpp:406
string & trim(string &s, const string &delimiters)
Definition: EnvsatUtil.cpp:29
char title[SM_ATTRSZ]
Definition: meta_l3b.h:17
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
virtual bool open()
Definition: OutFile.cpp:1022
virtual bool open()
Definition: OutFile.cpp:1227
virtual bool open()
Definition: OutFile.cpp:889
clo_optionList_t * optionList
@ ShortDS
Definition: OutFile.h:57
virtual bool close()
Definition: OutFile.cpp:2474
float west
Definition: meta_l3b.h:52
int sensorID
Definition: meta_l3b.h:18
virtual ~OutFile_png_rgb()
Definition: OutFile.cpp:1005
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
data_t b[NROOTS+1]
Definition: decode_rs.h:77
int32_t orbit
Definition: meta_l3b.h:41
int getlut_file(char *lut_file, short *rlut, short *glut, short *blut)
Definition: getlut_file.c:8
int32 emsec
Definition: l1_czcs_hdf.c:18
double pixscale[3]
Definition: OutFile.h:141
virtual ~OutFile_pgm()
Definition: OutFile.cpp:662
const std::unordered_map< std::string, std::vector< int32_t > > & get_wv3d_2d_name_to_3d_expansion()
Definition: l3mapgen.cpp:53
virtual void setTransparency()
Definition: OutFile.cpp:402
char lat_units[SM_ATTRSZ]
Definition: meta_l3b.h:44
virtual void setTiffColor()
Definition: OutFile.cpp:1448
uint8_t * green
Definition: OutFile.h:131
virtual void setLatLon(double *lat, double *lon)
Definition: OutFile.cpp:451
float south
Definition: meta_l3b.h:50
char * upcase(char *instr)
Definition: upcase.c:10
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:1462
char proc_con[MD_ATTRSZ]
Definition: meta_l3b.h:35
OutFile_png(bool color)
Definition: OutFile.cpp:866
virtual void setPixel(int32_t x, double val, int32_t prod=0)
Definition: OutFile.cpp:1103
char * getProductNameFull(productInfo_t *info)
DataStorage dataStorage
Definition: OutFile.h:73
virtual bool close()
Definition: OutFile.cpp:1924
virtual void setPixelRGB(int32_t x, float red, float green, float blue)
Definition: OutFile.cpp:1109
#define CREATOR_URL
Definition: OutFile.h:34
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
double startTime
Definition: meta_l3b.h:39
char soft_ver[SM_ATTRSZ]
Definition: meta_l3b.h:33
void copyProductInfo(productInfo_t *dest, const productInfo_t *src)
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
virtual void setQualityProcessing(bool val)
Definition: OutFile.cpp:626
char mission_char[SM_ATTRSZ]
Definition: meta_l3b.h:22
#define PRODUCT_DEFAULT_validMin
Definition: productInfo.h:34
void copy(double **aout, double **ain, int n)
@ fillPix
Definition: OutFile.h:61
virtual ~OutFile_netcdf4()
Definition: OutFile.cpp:1993
virtual int32_t getWidth() const
Definition: OutFile.cpp:373
#define PROJECT
Definition: OutFile.h:35
virtual void setPixelRGB(int32_t x, float red, float green, float blue)
Definition: OutFile.cpp:789
void setProj4Info(std::string projStr, double minX, double maxY)
Definition: OutFile.cpp:583
char ptime[SM_ATTRSZ]
Definition: meta_l3b.h:34
virtual void setTiffColor()
Definition: OutFile.cpp:1481
bool transparent
Definition: OutFile.h:134
#define DBL_MAX
Definition: make_L3_v1.1.c:60
@ UByteDS
Definition: OutFile.h:57
virtual void landPixel(int32_t x)
Definition: OutFile.cpp:1143
char pversion[SM_ATTRSZ]
Definition: meta_l3b.h:30
l2prod offset
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
virtual void setPixel(int32_t x, double val, int32_t prod=0)
Definition: OutFile.cpp:1492
virtual bool open()
Definition: OutFile.cpp:713
virtual ~OutFile()
Definition: OutFile.cpp:332
meta_l3bType * metaData
Definition: OutFile.h:136
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:1012
virtual void setSize(int32_t width, int32_t height)
Definition: OutFile.cpp:669
float east
Definition: meta_l3b.h:51
@ UShortDS
Definition: OutFile.h:57
int64_t data_bins
Definition: meta_l3b.h:46
virtual int getDeflate()
Definition: OutFile.h:234
uint32_t currentLine
Definition: OutFile.h:117
@ LatLon2D
Definition: OutFile.h:65
double landPixelValue
Definition: OutFile.h:83
std::string remove_wv_from_long_name(const std::string &long_name_with_wv)
Definition: OutFile.cpp:32
int32_t width
Definition: OutFile.h:112
virtual bool close()
Definition: OutFile.cpp:1323
virtual bool close()
Definition: OutFile.cpp:984
char sensor_name[SM_ATTRSZ]
Definition: meta_l3b.h:19
int i
Definition: decode_rs.h:71
OutFile()
Definition: OutFile.cpp:292
virtual void setFileName(std::string fileName)
Definition: OutFile.cpp:381
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32_t end_orb
Definition: meta_l3b.h:43
virtual void setNumFilledPixels(int32_t num)
Definition: OutFile.cpp:596
uint8_t * red
Definition: OutFile.h:130
std::unordered_map< std::string, size_t > prod2d_indexes_last_index
Definition: OutFile.h:110
char soft_name[SM_ATTRSZ]
Definition: meta_l3b.h:32
virtual double getFileMaxVal()
Definition: OutFile.h:208
std::unordered_map< std::string, size_t > product_3d_already_set
Definition: OutFile.h:110
float station_lat
Definition: meta_l3b.h:26
productInfo_t * productInfo
Definition: OutFile.h:72
l2prod max
@ UIntDS
Definition: OutFile.h:57
virtual int32_t addProduct(productInfo_t *productInfo)
Definition: OutFile.cpp:512
virtual void writeLine()
Definition: OutFile.cpp:1898
int count
Definition: decode_rs.h:79