Skip to content

Commit 3546b33

Browse files
authored
App Fixes For GeoTiffs (#5824)
* Fixes apps that fail when passing a GeoTiff with ISIS metadata * Fix spiceserver issues when format is GTiff * Fixed serial number composition to handle Gtiffs * Fix csminit on GeoTiff in ISIS * Add try catch around check for json blob * Remove error throw from gdalDataset and change json blob detection * Move gdal label reading from Cube into the Pvl class * Revert autoseed and serialnumber label read changes * Revert other apps that read pvl labels * Remove try catch around read from debugging * Reverted serialnumber compose to access the label directly * Revert more label reads * Fixed throw in PVL class at the end contructor from file path * Update opencv to use the cmake config * Fix using opencv config for find_package * Fixed error throwing in Pvl contruction * Fixed other tests with new errors and label size change * Decide to open a cube using gdal or ISIS open logic based on the GDAL driver * Added changelog entry * Fix tests after changing how cube decides to open files as geotiffs vs cubes * Handle gdal metadata pointer comparison change * Change geotiff creation to default to .tif * Fix ecub creation * Changed check for using gdal to open images if the driver used is not the ISIS3 driver * Fixed gdal metadata check to read metadata if it is NOT a nullptr * Handle ISIS2 and ISIS3 gdal drivers when opening images
1 parent 474e3e2 commit 3546b33

File tree

18 files changed

+224
-204
lines changed

18 files changed

+224
-204
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ ctest FunctionalTestJigsawApollo to validate this output. [#5710](https://github
7070
- Changed 'jigsaw' attribute type to account for Linux compiler changes [#5904](https://github.com/DOI-USGS/ISIS3/pull/5904)
7171
- Updated GDAL to 3.12 and QT to 6.X [#5909](https://github.com/DOI-USGS/ISIS3/pull/5909)
7272
- Updated cmake configs to accommodate new cspice release [#5886](https://github.com/DOI-USGS/ISIS3/pull/5886)
73+
- Changed `PVL` class to read data from GDAL metadata directly [#5824](https://github.com/DOI-USGS/ISIS3/pull/5824)
7374

7475
### Fixed
7576
- Fixed Chandrayaan-2 TMC2 serial numbers by setting InstrumentId to CH2_TMC_FORE/NADIR/AFT based on the filename sensor [#5871](https://github.com/DOI-USGS/ISIS3/issues/5871)

isis/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ find_package(GSL 2.2.1 REQUIRED)
302302
find_package(HDF5 1.8.15 REQUIRED)
303303
find_package(Jama 125 REQUIRED)
304304
find_package(NN REQUIRED)
305-
find_package(OpenCV 4.12.0 REQUIRED)
305+
find_package(OpenCV 4.9.0 REQUIRED CONFIG)
306306
find_package(PCL REQUIRED)
307307
find_package(Protobuf REQUIRED CONFIG)
308308
find_package(PROJ REQUIRED CONFIG)
@@ -396,6 +396,9 @@ endforeach()
396396
# add target based linkages to ALLLIBS variable
397397
list(APPEND ALLLIBS pantor::inja sensorutilities protobuf::libprotobuf embree GDAL::GDAL Bullet::Bullet_double CSPICE::cspice)
398398

399+
list(APPEND ALLLIBS ${OpenCV_LIBS})
400+
list(APPEND ALLINCDIRS ${OpenCV_INCLUDE_DIRS})
401+
399402
# Sometimes we add the same lib more than once (especially with LIBDIRS)
400403
list(REMOVE_DUPLICATES ALLLIBDIRS)
401404
list(REMOVE_DUPLICATES ALLLIBS)

isis/src/base/apps/catlab/main.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,7 @@ void IsisMain() {
1717
QString file = ui.GetCubeName("FROM");
1818

1919
// Extract label from file
20-
Pvl label;
21-
try {
22-
label = Pvl(file);
23-
}
24-
catch (...) {
25-
Cube cube(file);
26-
label = *cube.label();
27-
}
20+
Pvl label(file);
2821

2922
// Output to file if entered
3023
if(ui.WasEntered("TO")) {

isis/src/base/apps/spiceinit/SpiceClient.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ namespace Isis {
7777

7878
raw += " <label>\n";
7979
stringstream str;
80+
// Force BandSequential format as a hack to avoid issues
81+
// opening/operating on GTiff formated data
82+
PvlObject& core = cubeLabel.findObject("IsisCube").findObject("Core");
83+
if (core.findKeyword("Format")[0] == "GTiff") {
84+
core.findKeyword("Format") = "BandSequential";
85+
}
8086
str << cubeLabel;
8187
raw += QString(QByteArray(str.str().c_str()).toHex().constData()) + "\n";
8288

isis/src/base/apps/tabledump/main.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,7 @@ void helperButtonGetTableList() {
154154

155155
UserInterface &ui = Application::GetUserInterface();
156156
QString currentFile = ui.GetCubeName("FROM");
157-
Pvl label;
158-
try {
159-
label = Pvl(FileName(currentFile).expanded());
160-
}
161-
catch (...) {
162-
Cube cube(FileName(currentFile).expanded());
163-
label = *cube.label();
164-
}
157+
const Pvl label(FileName(currentFile).expanded());
165158

166159
// Check to see if the "FILE" parameter has changed since last press
167160
if (currentFile != g_previousFile) {

isis/src/base/objs/Cube/Cube.cpp

Lines changed: 40 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,10 @@ namespace Isis {
499499
imageFile = imageFile.addExtension("cub");
500500
}
501501
else if (format() == Format::GTiff) {
502-
imageFile = imageFile.addExtension("tiff");
502+
if (imageFile.extension() != "tif" &&
503+
imageFile.extension() != "tiff") {
504+
imageFile = imageFile.addExtension("tif");
505+
}
503506
}
504507
else {
505508
QString msg = "Unknown format type [" + toString(format()) + "]";
@@ -533,14 +536,15 @@ namespace Isis {
533536
core.addGroup(ptype);
534537
}
535538
else if (labelsAttached() == LabelAttachment::ExternalLabel) {
539+
imageFile = imageFile.addExtension("ecub");
536540
if (!m_dataFileName) {
537541
if (format() == Bsq || format() == Tile) {
538-
imageFile = imageFile.addExtension("cub");
542+
imageFile = imageFile.setExtension("cub");
539543

540544
Pvl dnLabel;
541545
PvlObject isiscube("IsisCube");
542546
PvlObject dnCore(core);
543-
PvlKeyword fileFormat("Format", toString(format()));
547+
PvlKeyword fileFormat("Format", CubeAttributeOutput::toString(format()));
544548

545549
dnCore.addKeyword(fileFormat);
546550
dnCore.addGroup(dims);
@@ -552,13 +556,11 @@ namespace Isis {
552556
Cube dnCube;
553557
dnCube.fromLabel(imageFile, dnLabel, "rw");
554558
dnCube.close();
555-
556-
m_dataFileName = new FileName(imageFile);
557559
}
558560
else if (format() == Format::GTiff) {
559-
imageFile = imageFile.setExtension("tiff");
560-
m_dataFileName = new FileName(imageFile);
561+
imageFile = imageFile.setExtension("tif");
561562
}
563+
m_dataFileName = new FileName(imageFile);
562564

563565
imageFile = imageFile.setExtension("ecub");
564566
FileName labelFileName(imageFile);
@@ -808,27 +810,26 @@ namespace Isis {
808810

809811
QString msg = "Failed to open [" + cubeFileName + "]";
810812
IException exceptions(IException::Io, msg, _FILEINFO_);
811-
if (!isOpen()) {
812-
try {
813-
openCube(cubeFileName, access);
814-
}
815-
catch (IException &e) {
816-
cleanUp(false);
817-
exceptions.append(e);
818-
}
813+
814+
GDALDriverH hDriver = GDALIdentifyDriver(FileName(cubeFileName).expanded().toStdString().c_str(), nullptr);
815+
bool openWithGdal = false;
816+
if (hDriver != nullptr) {
817+
GDALDriver* poDriver = (GDALDriver*)hDriver;
818+
QString driverDescription = poDriver->GetDescription();
819+
openWithGdal = (!driverDescription.contains("ISIS"));
819820
}
820821

821-
if (!isOpen()) {
822-
try {
822+
try{
823+
if (openWithGdal) {
823824
openGdal(cubeFileName, access);
824825
}
825-
catch(IException &e) {
826-
cleanUp(false);
827-
exceptions.append(e);
826+
else {
827+
openCube(cubeFileName, access);
828828
}
829829
}
830-
831-
if (!isOpen()) {
830+
catch(IException &e) {
831+
cleanUp(false);
832+
exceptions.append(e);
832833
throw exceptions;
833834
}
834835

@@ -942,7 +943,9 @@ namespace Isis {
942943
realDataFileLabel(), true);
943944
}
944945
else if (m_format == GTiff) {
945-
m_dataFile->close();
946+
if (m_dataFile) {
947+
m_dataFile->close();
948+
}
946949
m_geodataSet = GDALDataset::FromHandle(GDALOpen(m_dataFileName->expanded().toStdString().c_str(), eAccess));
947950
if (!m_geodataSet) {
948951
QString msg = "Opening GDALDataset from [" + m_dataFileName->name() + "] failed with access [" + QString::number(eAccess) +"]";
@@ -975,145 +978,8 @@ namespace Isis {
975978
m_dataFileName = new FileName(*m_labelFileName);
976979

977980
initCoreFromGdal(m_labelFileName->expanded());
978-
GDALDataset *dataset = GDALDataset::FromHandle(GDALOpen(m_dataFileName->expanded().toStdString().c_str(), GA_ReadOnly));
979-
if (!dataset) {
980-
QString msg = "Failed opening GDALDataset from [" + m_dataFileName->name() + "]";
981-
cleanUp(false);
982-
throw IException(IException::Programmer, msg, _FILEINFO_);
983-
}
984-
985-
CPLStringList metadata = CPLStringList(dataset->GetMetadata("USGS"), false);
986-
987-
m_label = new Pvl();
988-
if (metadata[0] != nullptr) {
989-
for (int i = 0; i < metadata.size(); i++) {
990-
const char *metadataItem = CPLParseNameValue(metadata[i], nullptr);
991-
nlohmann::ordered_json metadataAsJson = nlohmann::ordered_json::parse(metadataItem);
992-
Pvl pvl;
993-
Pvl::readObject(pvl, metadataAsJson);
994-
for (int i = 0; i < pvl.objects(); i++) {
995-
m_label->addObject(pvl.object(i));
996-
}
997-
for (int i = 0; i < pvl.groups(); i++) {
998-
m_label->addGroup(pvl.group(i));
999-
}
1000-
}
1001-
}
1002-
else {
1003-
// Setup the PVL
1004-
PvlObject isiscube("IsisCube");
1005-
PvlObject core("Core");
1006-
1007-
// Create the size of the core
1008-
PvlGroup dims("Dimensions");
1009-
dims += PvlKeyword("Samples", toString(m_samples));
1010-
dims += PvlKeyword("Lines", toString(m_lines));
1011-
dims += PvlKeyword("Bands", toString(m_bands));
1012-
1013-
// Create the pixel type
1014-
PvlGroup ptype("Pixels");
1015-
ptype += PvlKeyword("Type", PixelTypeName(m_pixelType));
1016-
1017-
// And the byte ordering
1018-
ptype += PvlKeyword("ByteOrder", ByteOrderName(m_byteOrder));
1019-
ptype += PvlKeyword("Base", toString(m_base));
1020-
ptype += PvlKeyword("Multiplier", toString(m_multiplier));
1021-
1022-
core += PvlKeyword("StartByte", toString(m_labelBytes + 1));
1023-
1024-
core.addGroup(dims);
1025-
core.addGroup(ptype);
1026981

1027-
isiscube.addObject(core);
1028-
1029-
m_label->addObject(isiscube);
1030-
}
1031-
1032-
if (dataset->GetSpatialRef() && !(m_label->findObject("IsisCube").hasGroup("Mapping"))) {
1033-
char ** projStr = new char*[1];
1034-
const OGRSpatialReference &oSRS = *dataset->GetSpatialRef();
1035-
oSRS.exportToProj4(projStr);
1036-
QString qProjStr = QString::fromStdString(std::string(projStr[0]) + " +type=crs");
1037-
delete[] projStr[0];
1038-
delete[] projStr;
1039-
1040-
char ** projJsonStr = new char*[1];
1041-
oSRS.exportToPROJJSON(projJsonStr, nullptr);
1042-
nlohmann::json projJson = nlohmann::json::parse(projJsonStr[0]);
1043-
CPLFree(projJsonStr);
1044-
1045-
PvlGroup mappingGroup("Mapping");
1046-
mappingGroup.addKeyword(PvlKeyword("ProjectionName", "IProj"));
1047-
mappingGroup.addKeyword(PvlKeyword("EquatorialRadius", toString(oSRS.GetSemiMajor()), "meters"));
1048-
mappingGroup.addKeyword(PvlKeyword("PolarRadius", toString(oSRS.GetSemiMinor()), "meters"));
1049-
1050-
if (projJson.contains("base_crs")) {
1051-
projJson = projJson["base_crs"];
1052-
}
1053-
1054-
std::string direction = projJson["coordinate_system"]["axis"][1]["direction"];
1055-
if (direction == "east") {
1056-
mappingGroup.addKeyword(PvlKeyword("LongitudeDirection", "PositiveEast"));
1057-
}
1058-
else if (direction == "west") {
1059-
mappingGroup.addKeyword(PvlKeyword("LongitudeDirection", "PositiveWest"));
1060-
}
1061-
else {
1062-
QString msg = "Unknown direction [" + QString::fromStdString(direction) + "]";
1063-
throw IException(IException::Programmer, msg, _FILEINFO_);
1064-
}
1065-
1066-
if (oSRS.GetSemiMajor() == oSRS.GetSemiMinor()) {
1067-
mappingGroup.addKeyword(PvlKeyword("LatitudeType", "Planetocentric"));
1068-
}
1069-
else {
1070-
mappingGroup.addKeyword(PvlKeyword("LatitudeType", "Planetographic"));
1071-
}
1072-
1073-
mappingGroup.addKeyword(PvlKeyword("LongitudeDomain", "180"));
1074-
mappingGroup.addKeyword(PvlKeyword("ProjStr", qProjStr));
1075-
1076-
// Read the GeoTransform and get the elements we care about
1077-
double *padfTransform = new double[6];
1078-
dataset->GetGeoTransform(padfTransform);
1079-
if (abs(padfTransform[1]) != abs(padfTransform[5])) {
1080-
delete[] padfTransform;
1081-
QString msg = "Vertical and horizontal resolution do not match";
1082-
throw IException(IException::Io, msg, _FILEINFO_);
1083-
}
1084-
1085-
double dfScale;
1086-
double dfRes;
1087-
double upperLeftX;
1088-
double upperLeftY;
1089-
dfRes = padfTransform[1] * oSRS.GetLinearUnits();
1090-
upperLeftX = padfTransform[0];
1091-
upperLeftY = padfTransform[3];
1092-
if (oSRS.IsProjected()) {
1093-
const double dfDegToMeter = oSRS.GetSemiMajor() * M_PI / 180.0;
1094-
dfScale = dfDegToMeter / dfRes;
1095-
mappingGroup.addKeyword(PvlKeyword("PixelResolution", toString(dfRes), "meters/pixel"));
1096-
}
1097-
else if (oSRS.IsGeographic()) {
1098-
dfScale = 1.0 / dfRes;
1099-
mappingGroup.addKeyword(PvlKeyword("PixelResolution", toString(dfRes), "degrees/pixel"));
1100-
}
1101-
else {
1102-
QString msg = "Gdal spatial reference is not Geographic or Projected";
1103-
throw IException(IException::Io, msg, _FILEINFO_);
1104-
}
1105-
mappingGroup.addKeyword(PvlKeyword("Scale", toString(dfScale), "pixels/degree"));
1106-
mappingGroup.addKeyword(PvlKeyword("UpperLeftCornerX", toString(upperLeftX)));
1107-
mappingGroup.addKeyword(PvlKeyword("UpperLeftCornerY", toString(upperLeftY)));
1108-
delete[] padfTransform;
1109-
1110-
PvlObject &isiscube = m_label->findObject("IsisCube");
1111-
if (isiscube.hasGroup("Mapping")) {
1112-
isiscube.deleteGroup("Mapping");
1113-
}
1114-
isiscube.addGroup(mappingGroup);
1115-
}
1116-
GDALClose(dataset);
982+
m_label = new Pvl(m_dataFileName->expanded());
1117983

1118984
GDALAccess eAccess = GA_ReadOnly;
1119985
if (access == "rw") {
@@ -1374,7 +1240,9 @@ namespace Isis {
13741240
// maxbyte = position after the cube DN data and labels
13751241
streampos maxbyte = (streampos) m_labelBytes;
13761242

1377-
maxbyte += (streampos) m_ioHandler->getDataSize();
1243+
if (labelsAttached() != ExternalLabel) {
1244+
maxbyte += (streampos) m_ioHandler->getDataSize();
1245+
}
13781246

13791247
// If EOF is too early, allocate space up to where we want the blob
13801248
if (endByte < maxbyte) {
@@ -2406,6 +2274,16 @@ namespace Isis {
24062274
* @return bool True if the BLOB was found
24072275
*/
24082276
bool Cube::hasBlob(const QString &name, const QString &type) {
2277+
if (gdalDataset()) {
2278+
string key = type.toStdString() + "_" + name.toStdString();
2279+
const char *jsonblobStr = gdalDataset()->GetMetadataItem(key.c_str(), "USGS");
2280+
2281+
if (jsonblobStr) {
2282+
return true;
2283+
}
2284+
return false;
2285+
}
2286+
24092287
for(int o = 0; o < label()->objects(); o++) {
24102288
PvlObject &obj = label()->object(o);
24112289
if (obj.isNamed(type)) {
@@ -2585,10 +2463,6 @@ namespace Isis {
25852463

25862464

25872465
GDALDataset *Cube::gdalDataset() const {
2588-
if (!m_geodataSet) {
2589-
QString msg = "No GDALDataset has been constructed";
2590-
throw IException(IException::Programmer, msg, _FILEINFO_);
2591-
}
25922466
return m_geodataSet;
25932467
}
25942468

isis/src/base/objs/CubeAttribute/CubeAttribute.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ namespace Isis {
527527

528528
using CubeAttribute<CubeAttributeOutput>::toString;
529529

530+
static QString toString(Cube::Format);
530531

531532
private:
532533
bool isByteOrder(QString attribute) const;
@@ -535,8 +536,6 @@ namespace Isis {
535536
bool isPixelType(QString attribute) const;
536537
bool isRange(QString attribute) const;
537538

538-
static QString toString(Cube::Format);
539-
540539
/**
541540
* @brief Output cube range tracker
542541
*

isis/src/base/objs/CubeManager/CubeManager.truth

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,4 @@ Setting number of open cubes > 60 percent of system open file limit
5050

5151
Attempting to open a file that does not exist:
5252
**I/O ERROR** Failed to open [dne.cub].
53-
**PROGRAMMER ERROR** Gdal failed to open [dne.cub].
5453
**I/O ERROR** Unable to open [dne.cub].

isis/src/base/objs/ProcessMapMosaic/ProcessMapMosaic.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,7 @@ namespace Isis {
508508
double xmin, double xmax, double ymin, double ymax,
509509
double slat, double elat, double slon, double elon, int nbands,
510510
CubeAttributeOutput &oAtt, const QString &mosaicFile, bool latlonflag) {
511-
Cube cube(inputFile);
512-
Pvl fileLab = *cube.label();
511+
Pvl fileLab(inputFile);
513512
PvlGroup &mapping = fileLab.findGroup("Mapping", Pvl::Traverse);
514513

515514
// All mosaicking programs use only the upper left x and y to determine where to

0 commit comments

Comments
 (0)