2 #include <geo_normalize.h>
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>
24 #include <geo_tiffp.h>
33 std::vector<std::string> key_words;
35 boost::split(key_words, long_name_with_wv, boost::is_any_of(delim));
40 std::stack<std::string> stack;
41 for (
const auto& word : key_words) {
54 while (!stack.empty()) {
55 if (!wv_prefix.empty())
57 wv_prefix += stack.top();
79 dataStorage = UByteDS;
85 minVal = minOutputVal;
86 maxVal = maxOutputVal;
87 missingValue = fillPix;
88 lineData = (
double*)
allocateMemory(width *
sizeof(
double),
"OutFile::ProductStuff::lineData");
89 this->landPixelValue = landPixelValue;
105 lineData = (
double*)
allocateMemory(width *
sizeof(
double),
"OutFile::ProductStuff::lineData");
121 this->scaleType = scaleType;
136 minVal = calcPhysicalVal(minOutputVal);
137 maxVal = calcPhysicalVal(maxOutputVal);
140 printf(
"-E- OutFile::setScale - invalid scaleType = %d\n", (
int)scaleType);
147 minOutputVal = minOutput;
148 maxOutputVal = maxOutput;
149 setScale(
min,
max, scaleType);
159 this->scaleType = scaleType;
164 minVal = 0 - FLT_MAX;
166 minVal = calcPhysicalVal(minOutputVal);
167 maxVal = calcPhysicalVal(maxOutputVal);
172 minOutputVal = minOutput;
173 maxOutputVal = maxOutput;
180 if (
val == badPixelValue)
183 if (
val == landPixelValue)
187 if (dataStorage == FloatDS || dataStorage == DoubleDS)
204 printf(
"-E- OutFile::ProductStuff::calcOutputVal - invalid scaleType = %d\n", (
int)scaleType);
208 if (outVal < minOutputVal)
210 if (outVal > maxOutputVal)
218 if (
val == missingValue)
219 return badPixelValue;
222 if (dataStorage == FloatDS || dataStorage == DoubleDS)
236 printf(
"-E- OutFile::ProductStuff::calcPhysicalVal - invalid scaleType = %d\n", (
int)scaleType);
240 if (physicalVal < minVal)
242 if (physicalVal > maxVal)
248 switch (dataStorage) {
250 for (
int i = 0;
i < width;
i++)
251 ((int8_t*)lineBuffer)[
i] = round(calcOutputVal(lineData[
i]));
254 for (
int i = 0;
i < width;
i++)
255 ((uint8_t*)lineBuffer)[
i] = round(calcOutputVal(lineData[
i]));
258 for (
int i = 0;
i < width;
i++)
259 ((int16_t*)lineBuffer)[
i] = round(calcOutputVal(lineData[
i]));
262 for (
int i = 0;
i < width;
i++)
263 ((uint16_t*)lineBuffer)[
i] = round(calcOutputVal(lineData[
i]));
266 for (
int i = 0;
i < width;
i++)
267 ((int32_t*)lineBuffer)[
i] = round(calcOutputVal(lineData[
i]));
270 for (
int i = 0;
i < width;
i++)
271 ((uint32_t*)lineBuffer)[
i] = round(calcOutputVal(lineData[
i]));
274 for (
int i = 0;
i < width;
i++)
275 ((
float*)lineBuffer)[
i] = lineData[
i];
278 for (
int i = 0;
i < width;
i++)
279 ((
double*)lineBuffer)[
i] = lineData[
i];
282 printf(
"-E- OutFile::ProductStuff::calcOutputLineVals - unrecognized data type = %d\n",
293 landPixelValue = -32766.0;
298 colorType = Grayscale;
303 fullLatLon = LatLon2D;
312 for (
int i = 0;
i < 256;
i++) {
324 metaData->north = 90.0;
325 metaData->south = -90.0;
326 metaData->east = 180.0;
327 metaData->west = -180.0;
329 mapProjection =
"Undefined";
337 for (
size_t i = 0;
i < productStuff.size();
i++) {
338 delete productStuff[
i];
340 productStuff.clear();
347 switch (productStuff[prod]->scaleType) {
360 this->height = height;
363 qualityData = (uint8_t*)
allocateMemory(width,
"OutFile::qualityData");
367 for (
size_t i = 0;
i < productStuff.size();
i++) {
368 delete productStuff[
i];
370 productStuff.clear();
382 this->fileName = fileName;
386 if (x < 0 || x >= width) {
387 fprintf(
stderr,
"-E- OutFile::setPixel - x=%d is not within range, width=%d.\n",
x, width);
390 productStuff[prod]->lineData[
x] =
val;
391 if (
val > fileMaxVal)
393 if (
val < fileMinVal)
398 fprintf(
stderr,
"-E- OutFile::setPixelRGB - RGB not implemented with this file type.\n");
407 if (x < 0 || x >= width) {
408 fprintf(
stderr,
"-E- OutFile::setQuality - x=%d is not within range, width=%d.\n",
x, width);
412 fprintf(
stderr,
"-E- OutFile::setQuality - qualityData id NULL.\n");
415 qualityData[
x] =
val;
419 if (x < 0 || x >= width) {
420 fprintf(
stderr,
"-E- OutFile::landPixel - x=%d is not within range, width=%d.\n",
x, width);
423 for (
size_t prod = 0; prod < productStuff.size(); prod++)
424 productStuff[prod]->lineData[
x] = landPixelValue;
426 qualityData[
x] = qualityUnused;
430 if (x < 0 || x >= width) {
431 fprintf(
stderr,
"-E- OutFile::fillPixel - x=%d is not within range, width=%d.\n",
x, width);
434 for (
size_t prod = 0; prod < productStuff.size(); prod++)
435 productStuff[prod]->lineData[
x] = badPixelValue;
437 qualityData[
x] = qualityUnused;
441 if (x < 0 || x >= width) {
442 fprintf(
stderr,
"-E- OutFile::missingPixel - x=%d is not within range, width=%d.\n",
x, width);
445 for (
size_t prod = 0; prod < productStuff.size(); prod++)
446 productStuff[prod]->lineData[
x] = badPixelValue;
448 qualityData[
x] = qualityUnused;
452 if (fullLatLon == LatLon2D) {
461 string paletteFileName;
462 short r[256],
g[256],
b[256];
464 if ((dataRoot = getenv(
"OCDATAROOT")) ==
NULL) {
465 printf(
"OCDATAROOT environment variable is not defined.\n");
466 return (EXIT_FAILURE);
468 paletteFileName = dataRoot;
469 paletteFileName +=
"/common/palette/";
470 paletteFileName += paletteName;
471 paletteFileName +=
".pal";
474 fprintf(
stderr,
"Error reading palette file %s\n", paletteFileName.c_str());
478 r[landPix] = rgb_land[0];
479 g[landPix] = rgb_land[1];
480 b[landPix] = rgb_land[2];
485 for (
int i = 0;
i < 256;
i++) {
496 boost::split(
rgb, rgb_land_string, boost::is_any_of(
","));
498 rgb_land[0] = std::stoi(
rgb[0]);
499 rgb_land[1] = std::stoi(
rgb[1]);
500 rgb_land[2] = std::stoi(
rgb[2]);
504 *this->metaData = *metaData;
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);
523 printf(
"-E- OutFile::addProduct - invalid displayScale = %s\n", productInfo->displayScale);
527 productStuff.push_back(stuff);
528 return productStuff.size() - 1;
534 if (!strcmp(productInfo->dataType,
"byte")) {
538 }
else if (!strcmp(productInfo->dataType,
"ubyte")) {
542 }
else if (!strcmp(productInfo->dataType,
"short")) {
546 }
else if (!strcmp(productInfo->dataType,
"ushort")) {
550 }
else if (!strcmp(productInfo->dataType,
"int")) {
554 }
else if (!strcmp(productInfo->dataType,
"uint")) {
558 }
else if (!strcmp(productInfo->dataType,
"float")) {
562 }
else if (!strcmp(productInfo->dataType,
"double")) {
567 printf(
"-E- OutFile::addProductNonDisplay - invalid data type = %s\n", productInfo->dataType);
572 stuff->
setScaleOffset(productInfo->scaleFactor, productInfo->addOffset, Linear);
575 productStuff.push_back(stuff);
576 return productStuff.size() - 1;
580 mapProjection = projection;
584 proj4String = projStr;
586 for (
int i = 0;
i < 6;
i++)
598 metaData->data_bins = num;
604 return metaData->data_bins;
611 float numPix = width * height;
612 return metaData->data_bins / numPix * 100.0;
632 qualityData = (uint8_t*)
allocateMemory(2,
"OutFile::qualityData");
636 qualityData = (uint8_t*)
allocateMemory(width,
"OutFile::qualityData");
682 fprintf(
outfp,
"P5\n");
684 fprintf(
outfp,
"255\n");
721 fprintf(
outfp,
"P6\n");
723 fprintf(
outfp,
"255\n");
764 outfp = fopen(
fileName.c_str(),
"w");
771 fprintf(outfp,
"P6\n");
773 fprintf(outfp,
"255\n");
785 "-E- OutFile_ppm_rgb::setPixel - only RGB is implemented with this file type.\n");
790 if (x < 0 || x >=
width) {
792 "-E- OutFile_ppm_rgb::setPixel - x=%d is not within range, width=%d.\n",
797 uint8_t* ptr = fileData +
x * 3;
813 if (x < 0 || x >=
width) {
815 "-E- OutFile_ppm_rgb::landPixel - x=%d is not within range, width=%d.\n",
819 uint8_t* ptr = fileData +
x * 3;
828 if (x < 0 || x >=
width) {
830 "-E- OutFile_ppm_rgb::fillPixel - x=%d is not within range, width=%d.\n",
834 uint8_t* ptr = fileData +
x * 3;
843 if (x < 0 || x >=
width) {
845 "-E- OutFile_ppm_rgb::missingPixel - x=%d is not within range, width=%d.\n",
849 uint8_t* ptr = fileData +
x * 3;
858 fwrite(fileData, 1,
width * 3, outfp);
890 outfp = fopen(
fileName.c_str(),
"w");
894 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
896 fprintf(
stderr,
"-E- Unable to create PNG write structure.\n");
900 info_ptr = png_create_info_struct(png_ptr);
902 png_destroy_write_struct(&png_ptr, (png_infopp)
NULL);
903 fprintf(
stderr,
"-E- Unable to create PNG info structure.\n");
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");
911 png_init_io(png_ptr, outfp);
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);
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);
951 uint8_t pal[256 * 3];
952 for (
int i = 0;
i < 256;
i++) {
957 png_set_PLTE(png_ptr, info_ptr, (png_const_colorp)pal, 256);
960 uint8_t transPal[256];
961 for (
int i = 0;
i < 255;
i++) {
965 png_set_tRNS(png_ptr, info_ptr, transPal, 256,
NULL);
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);
972 png_write_info(png_ptr, info_ptr);
980 png_write_row(png_ptr, (png_bytep)fileData);
985 png_write_end(png_ptr, info_ptr);
986 png_destroy_write_struct(&png_ptr, &info_ptr);
1016 int samplesPerPixel = 3;
1018 samplesPerPixel = 4;
1019 fileData = (uint8_t*)
allocateMemory(
width * samplesPerPixel,
"OutFile_png_rgb::fileData");
1023 outfp = fopen(
fileName.c_str(),
"w");
1027 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
1029 fprintf(
stderr,
"-E- Unable to create PNG write structure.\n");
1033 info_ptr = png_create_info_struct(png_ptr);
1035 png_destroy_write_struct(&png_ptr, (png_infopp)
NULL);
1036 fprintf(
stderr,
"-E- Unable to create PNG info structure.\n");
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");
1044 png_init_io(png_ptr, outfp);
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);
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);
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);
1091 if (setjmp(png_jmpbuf(png_ptr))) {
1092 fprintf(
stderr,
"-E- OutFile_png_rgb::close - Unable to call PNG setjmp().\n");
1095 png_write_end(png_ptr, info_ptr);
1096 png_destroy_write_struct(&png_ptr, &info_ptr);
1105 "-E- OutFile_png_rgb::setPixel - only RGB is implemented with this file type.\n");
1110 if (x < 0 || x >=
width) {
1112 "-E- OutFile_png_rgb::setPixel - x=%d is not within range, width=%d.\n",
1117 int samplesPerPixel = 3;
1119 samplesPerPixel = 4;
1120 uint8_t* ptr = fileData +
x * samplesPerPixel;
1144 if (x < 0 || x >=
width) {
1146 "-E- OutFile_png_rgb::landPixel - x=%d is not within range, width=%d.\n",
1150 int samplesPerPixel = 3;
1152 samplesPerPixel = 4;
1153 uint8_t* ptr = fileData +
x * samplesPerPixel;
1166 if (x < 0 || x >=
width) {
1168 "-E- OutFile_png_rgb::fillPixel - x=%d is not within range, width=%d.\n",
1172 int samplesPerPixel = 3;
1174 samplesPerPixel = 4;
1175 uint8_t* ptr = fileData +
x * samplesPerPixel;
1188 if (x < 0 || x >=
width) {
1190 "-E- OutFile_png_rgb::missingPixel - x=%d is not within range, width=%d.\n",
1194 int samplesPerPixel = 3;
1196 samplesPerPixel = 4;
1197 uint8_t* ptr = fileData +
x * samplesPerPixel;
1210 if (setjmp(png_jmpbuf(png_ptr))) {
1211 fprintf(
stderr,
"-E- OutFile_png_rgb::writeLine - Unable to call PNG setjmp().\n");
1215 png_write_row(png_ptr, (png_bytep)fileData);
1233 cerr <<
"-E- Could not open outgoing TIFF image" << endl;
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\">";
1244 tagVal +=
"</Item>\n";
1245 tagVal +=
"</GDALMetadata>\n";
1246 TIFFSetField(
tiff, TIFFTAG_GDALMetadata, tagVal.c_str());
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);
1256 bool hasGeotiffInfo =
false;
1259 cerr <<
"-E- Could not create geoTIFF structure" << endl;
1265 double north, south, east, west;
1283 for (
int i = 0;
i < 6;
i++)
1288 GTIFKeySet(
gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelGeographic);
1289 GTIFKeySet(
gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, GCS_WGS_84);
1290 hasGeotiffInfo =
true;
1296 if (!hasGeotiffInfo) {
1298 hasGeotiffInfo =
true;
1301 if (hasGeotiffInfo) {
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);
1311 GTIFWriteKeys(
gtif);
1356 uint8_t* ptr = fileData +
i * 4;
1358 uint8_t
alpha = 255;
1364 *ptr =
red[scaledVal];
1366 *ptr =
green[scaledVal];
1368 *ptr =
blue[scaledVal];
1378 cerr <<
"-E- Could not write TIFF image line " <<
currentLine << endl;
1387 TIFFSetField(
tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1388 TIFFSetField(
tiff, TIFFTAG_BITSPERSAMPLE, 8);
1389 TIFFSetField(
tiff, TIFFTAG_SAMPLESPERPIXEL, 4);
1391 out[0] = EXTRASAMPLE_ASSOCALPHA;
1392 TIFFSetField(
tiff, TIFFTAG_EXTRASAMPLES, 1, &
out);
1393 TIFFSetField(
tiff, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
1395 TIFFSetField(
tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
1396 TIFFSetField(
tiff, TIFFTAG_BITSPERSAMPLE, 8);
1397 TIFFSetField(
tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
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));
1404 cerr <<
"-E- Could not allocate memory for TIFF color map" << endl;
1407 for (
int i = 0;
i < ncolors;
i++) {
1408 rr[
i] =
red[
i] << 8;
1412 TIFFSetField(
tiff, TIFFTAG_COLORMAP, rr,
gg, bb);
1442 cerr <<
"-E- Could not write TIFF image line " <<
currentLine << endl;
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);
1475 cerr <<
"-E- Could not write TIFF image line " <<
currentLine << endl;
1482 TIFFSetField(
tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1483 TIFFSetField(
tiff, TIFFTAG_BITSPERSAMPLE, 8);
1485 TIFFSetField(
tiff, TIFFTAG_SAMPLESPERPIXEL, 4);
1487 TIFFSetField(
tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
1489 TIFFSetField(
tiff, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
1493 if (x < 0 || x >=
width) {
1495 "-E- OutFile_tiff_rgb::setPixel - x=%d is not within range, width=%d.\n",
1500 uint8_t samplesPerPixel = 3;
1502 samplesPerPixel = 4;
1504 uint8_t* ptr = fileData +
x * samplesPerPixel;
1506 uint8_t
alpha = 255;
1512 *ptr =
red[scaledVal];
1514 *ptr =
green[scaledVal];
1516 *ptr =
blue[scaledVal];
1524 if (x < 0 || x >=
width) {
1526 "-E- OutFile_tiff_rgb::setPixel - x=%d is not within range, width=%d.\n",
1531 uint8_t
alpha = 255;
1533 uint8_t samplesPerPixel = 3;
1535 samplesPerPixel = 4;
1537 uint8_t* ptr = fileData +
x * samplesPerPixel;
1559 if (x < 0 || x >=
width) {
1561 "-E- OutFile_tiff_rgb::landPixel - x=%d is not within range, width=%d.\n",
1566 uint8_t samplesPerPixel = 3;
1568 samplesPerPixel = 4;
1570 uint8_t* ptr = fileData +
x * samplesPerPixel;
1583 if (x < 0 || x >=
width) {
1585 "-E- OutFile_tiff_rgb::fillPixel - x=%d is not within range, width=%d.\n",
1590 uint8_t samplesPerPixel = 3;
1592 samplesPerPixel = 4;
1594 uint8_t* ptr = fileData +
x * samplesPerPixel;
1607 if (x < 0 || x >=
width) {
1609 "-E- OutFile_tiff_rgb::missingPixel - x=%d is not within range, width=%d.\n",
1614 uint8_t samplesPerPixel = 3;
1616 samplesPerPixel = 4;
1618 uint8_t* ptr = fileData +
x * samplesPerPixel;
1661 sdfid = SDstart(
fileName.c_str(), DFACC_CREATE);
1664 printf(
"-E- Could not create HDF4 file %s\n",
fileName.c_str());
1672 if (
pos == string::npos)
1676 DPTB(SDsetattr(sdfid,
"Product Name", DFNT_CHAR,
prodName.size() + 1, (VOIDP)
prodName.c_str()));
1713 smsec = (int32_t)(ssec * 1000.0);
1715 emsec = (int32_t)(esec * 1000.0);
1721 DPTB(SDsetattr(sdfid,
"Start Time", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1723 DPTB(SDsetattr(sdfid,
"End Time", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1735 DPTB(SDsetattr(sdfid,
"Latitude Units", DFNT_CHAR, 14, (VOIDP)
"degrees North"));
1736 DPTB(SDsetattr(sdfid,
"Longitude Units", DFNT_CHAR, 13, (VOIDP)
"degrees East"));
1749 DPTB(SDsetattr(sdfid,
"Longitude Step",
DFNT_FLOAT32, 1, (VOIDP)&lonStep));
1752 DPTB(SDsetattr(sdfid,
"SW Point Latitude",
DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1754 DPTB(SDsetattr(sdfid,
"SW Point Longitude",
DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1757 DPTB(SDsetattr(sdfid,
"Data Bins",
DFNT_INT32, 1, (VOIDP)&tmpInt32));
1760 DPTB(SDsetattr(sdfid,
"Number of Lines",
DFNT_INT32, 1, (VOIDP)&tmpInt32));
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,
1765 DPTB(SDsetattr(sdfid,
"Measure", DFNT_CHAR, 5, (VOIDP)
"Mean"));
1766 DPTB(SDsetattr(sdfid,
"Units", DFNT_CHAR, strlen(
productStuff[0]->productInfo->units) + 1,
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));
1777 const char* imageScalingApplied;
1784 imageScalingApplied =
"No";
1789 if (tmpScale == 1.0 && tmpOffset == 0.0)
1790 imageScalingApplied =
"No";
1792 imageScalingApplied =
"Yes";
1803 DPTB(SDsetattr(sdfid,
"Suggested Image Scaling Minimum",
DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1805 DPTB(SDsetattr(sdfid,
"Suggested Image Scaling Maximum",
DFNT_FLOAT32, 1, (VOIDP)&tmpFloat));
1809 DPTB(SDsetattr(sdfid,
"Suggested Image Scaling Type", DFNT_CHAR, strlen(tmpStr) + 1, (VOIDP)tmpStr));
1810 free((
void*)tmpStr);
1812 DPTB(SDsetattr(sdfid,
"Suggested Image Scaling Applied", DFNT_CHAR, strlen(imageScalingApplied) + 1,
1813 (VOIDP)imageScalingApplied));
1826 if (!strcmp(
productStuff[0]->productInfo->dataType,
"byte")) {
1827 hdfDataType = DFNT_INT8;
1828 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1830 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1832 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"ubyte")) {
1833 hdfDataType = DFNT_UINT8;
1834 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1836 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1838 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"short")) {
1840 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1842 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1844 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"ushort")) {
1845 hdfDataType = DFNT_UINT16;
1846 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1848 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1850 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"int")) {
1852 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1854 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1856 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"uint")) {
1857 hdfDataType = DFNT_UINT32;
1858 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1860 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1862 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"float")) {
1864 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1866 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1868 }
else if (!strcmp(
productStuff[0]->productInfo->dataType,
"double")) {
1869 hdfDataType = DFNT_FLOAT64;
1870 sdsid = SDcreate(sdfid,
"l3m_data", hdfDataType, 2, dims);
1872 DPTB(SDsetattr(sdsid,
"Fill", hdfDataType, 1, (VOIDP)&
tmp));
1875 printf(
"-E- Data type %s, not supported\n",
productStuff[0]->productInfo->dataType);
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));
1888 quality_sdsid = SDcreate(sdfid,
"l3m_qual", DFNT_UINT8, 2, dims);
1889 int32_t validRange[2];
1892 DPTB(SDsetattr(quality_sdsid,
"valid_range",
DFNT_INT32, 2, (VOIDP)validRange));
1909 if ((SDwritedata(sdsid,
start,
NULL,
count, (VOIDP)fileData)) < 0) {
1910 printf(
"\n-E- OutFile_hdf4::writeLine(): SDwritedata unsuccessful\n");
1916 printf(
"\n-E- OutFile_hdf4::writeLine(): SDwritedata unsuccessful\n");
1932 DPTB(SDsetattr(sdfid,
"Data Bins",
DFNT_INT32, 1, (VOIDP)&tmpInt));
1940 SDendaccess(quality_sdsid);
1955 for (
int i = 0;
i < 256;
i++) {
1962 printf(
"-E- OutFile_hdf4::close - Error writing map_palette.\n");
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");
1985 using namespace netCDF;
2015 ncFile =
new NcFile(
fileName.c_str(), NcFile::replace);
2020 if (
pos == string::npos)
2024 ncFile->putAtt(
"product_name",
prodName.c_str());
2027 std::string source =
"satellite observations from ";
2030 ncFile->putAtt(
"project",
PROJECT);
2037 ncFile->putAtt(
"source", source);
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);
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);
2078 ncFile->putAtt(
"spatialResolution", resolutionStr);
2079 ncFile->putAtt(
"geospatial_lon_resolution", resolutionStr);
2080 ncFile->putAtt(
"geospatial_lat_resolution", resolutionStr);
2084 ncFile->putAtt(
"number_of_lines", ncInt,
height);
2085 ncFile->putAtt(
"number_of_columns", ncInt,
width);
2086 ncFile->putAtt(
"measure",
"Mean");
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"))
2092 else if (!strcmp(
productStuff[0]->productInfo->displayScale,
"arctan"))
2096 ncFile->putAtt(
"suggested_image_scaling_type", tmpStr);
2097 ncFile->putAtt(
"suggested_image_scaling_applied",
"No");
2100 ncFile->putAtt(
"Conventions",
"CF-1.6 ACDD-1.3");
2107 if (
id ==
"Unspecified") {
2113 ncFile->putAtt(
"id",
id);
2115 ncFile->putAtt(
"license",
LICENSE);
2123 ncFile->putAtt(
"processing_level",
"L3 Mapped");
2124 ncFile->putAtt(
"cdm_data_type",
"grid");
2130 ncFile->putAtt(
"identifier_product_doi_authority",
"http://dx.doi.org");
2136 ncFile->putAtt(
"keywords", keywordStr);
2142 NcGroup grp1 = ncFile->addGroup(
"processing_control");
2149 grp1.putAtt(
"input_sources", tmpStr);
2153 NcGroup grp2 = grp1.addGroup(
"input_parameters");
2160 char*
name = strtok_r(
token,
"=", &end_token);
2161 for (uint32_t
i = 0;
i < strlen(
name);
i++) {
2162 if (
name[
i] ==
' ') {
2167 char*
val = strtok_r(
NULL,
"|", &end_token);
2171 grp2.putAtt(
name, buf);
2176 vector<NcDim> dimIds;
2181 dimIds.push_back(ncFile->addDim(
"lat",
height));
2182 dimIds.push_back(ncFile->addDim(
"lon",
width));
2187 dimIds.push_back(ncFile->addDim(
"y",
height));
2188 dimIds.push_back(ncFile->addDim(
"x",
width));
2191 coordinates =
"lat lon";
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));
2202 std::copy(dimIds.begin(), dimIds.end(), std::back_inserter(dimIds_3D));
2203 dimIds_3D.push_back(ncFile->addDim(
"wavelength",
get_len_wv3d()));
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);
2214 var.putVar(
data.data());
2216 auto dimIds_to_set = &dimIds_2D;
2217 size_t count_3d_counter = 0;
2218 for (
size_t prodNum = 0; prodNum <
productStuff.size(); prodNum++) {
2220 NcType varDataType = getDataType(
productStuff[prodNum]->dataStorage);
2221 dataSize =
std::max(dataSize, varDataType.getSize());
2224 productInfo_t* pInfo =
productStuff[prodNum]->productInfo;
2225 std::string temp_wave_name = pInfo->paramDesignator;
2232 if (!suffix_prod.empty()) {
2235 std::size_t
pos = full_prod_name.find(suffix_prod);
2237 full_prod_name = full_prod_name.substr(0,
pos);
2243 const auto prod_name = prod_name_no_suffix + suffix_prod;
2262 dimIds_to_set = &dimIds_3D;
2263 if (pInfo->paramDesignator)
2264 free(pInfo->paramDesignator);
2266 free(pInfo->prefix);
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());
2279 dimIds_to_set = &dimIds_2D;
2281 NcVar var = createProduct(pInfo, varDataType, *dimIds_to_set);
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());
2307 initCompression(var);
2308 prodVars.push_back(var);
2311 var.putAtt(
"display_scale", pInfo->displayScale);
2312 var.putAtt(
"display_min", ncFloat, pInfo->displayMin);
2313 var.putAtt(
"display_max", ncFloat, pInfo->displayMax);
2316 if (coordinates.length() > 0)
2317 var.putAtt(
"coordinates", coordinates);
2350 cerr <<
"-E- OutFile_netcdf4::open - cannot find product " <<
qualityName <<
" in product.xml"
2354 qInfo->fillValue = NC_FILL_UBYTE;
2355 qualVar = createProduct(qInfo, ncUbyte, dimIds);
2356 initCompression(qualVar);
2364 cerr <<
"-E- OutFile_netcdf4::open - "
2365 "cannot find \"lat\" in product.xml"
2371 cerr <<
"-E- OutFile_netcdf4::open - "
2372 "cannot find \"lon\" in product.xml"
2381 vector<NcDim> latDim;
2382 latDim.push_back(dimIds[0]);
2383 NcVar
lat = createProduct(latInfo, ncFloat, latDim);
2384 lat.putVar(latarray);
2390 if(lonarray[
i] > 180.0)
2391 lonarray[
i] -= 360.0;
2393 vector<NcDim> lonDim;
2394 lonDim.push_back(dimIds[1]);
2395 NcVar
lon = createProduct(lonInfo, ncFloat, lonDim);
2396 lon.putVar(lonarray);
2400 latVar = createProduct(latInfo, ncFloat, dimIds);
2401 lonVar = createProduct(lonInfo, ncFloat, dimIds);
2402 initCompression(latVar);
2403 initCompression(lonVar);
2413 for (
int i = 0;
i < 256;
i++) {
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);
2425 }
catch (std::exception
const& e) {
2426 cerr <<
"Exception: " << e.what() << endl;
2433 vector<size_t>
start(2);
2434 vector<size_t>
count(2);
2439 vector<size_t> start_3D = {
start[0],
start[1], 0};
2440 vector<size_t> count_3D = {
count[0],
count[1], 1};
2442 for (
size_t prodNum = 0; prodNum <
productStuff.size(); prodNum++) {
2444 const auto index_in_products =
index_2d_3d.at(prodNum);
2450 prodVars[index_in_products].putVar(
start,
count, fileData);
2453 start_3D[2] = slice_to_put;
2454 prodVars[index_in_products].putVar(start_3D, count_3D, fileData);
2478 ncFile->putAtt(
"data_minimum", ncFloat, 0.0);
2479 ncFile->putAtt(
"data_maximum", ncFloat, 0.0);
2481 ncFile->putAtt(
"data_minimum", ncFloat, (
float)
getFileMinVal());
2482 ncFile->putAtt(
"data_maximum", ncFloat, (
float)
getFileMaxVal());
2504 void OutFile_netcdf4::initCompression(NcVar var) {
2509 vector<NcDim> dims = var.getDims();
2510 vector<size_t> chunksize;
2516 switch(dims.size()) {
2518 chunksize.push_back(
MIN(dims[0].getSize(), 2048));
2521 chunksize.push_back(
MIN(dims[0].getSize(), 512));
2522 chunksize.push_back(
MIN(dims[1].getSize(), 1024));
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));
2530 printf(
"-E- OutFile_netcdf4::initCompression - bad rank for variable %s\n", var.getName().c_str());
2534 var.setChunking(NcVar::nc_CHUNKED, chunksize);
2535 var.setCompression(
true,
true,
getDeflate());
2538 NcVar OutFile_netcdf4::createProduct(productInfo_t* pInfo,
const NcType& ncType,
2539 const std::vector<netCDF::NcDim> ncDim) {
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);
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);
2555 if (pInfo->fillValue)
2556 var.putAtt(
"_FillValue", ncType, pInfo->fillValue);
2557 }
catch (std::exception
const& e) {
2558 cerr <<
"FillValue exception: " << e.what() << endl;
2561 var.putAtt(
"valid_min", ncType, (pInfo->validMin - pInfo->addOffset) / pInfo->scaleFactor);
2562 var.putAtt(
"valid_max", ncType, (pInfo->validMax - pInfo->addOffset) / pInfo->scaleFactor);
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);
2572 NcType OutFile_netcdf4::getDataType(DataStorage dataStorage) {
2573 switch (dataStorage) {
2591 cerr <<
"-E- OutFile_netcdf4::getDataType - illegal data storage "
2593 << dataStorage << endl;