diff --git a/Data/Baseline/OTB/Files/ioTvcoreImageMetadataTest.txt b/Data/Baseline/OTB/Files/ioTvcoreImageMetadataTest.txt new file mode 100644 index 0000000000000000000000000000000000000000..19f2ba1c0ba63171ba659f37b3d48ebc589fc24b --- /dev/null +++ b/Data/Baseline/OTB/Files/ioTvcoreImageMetadataTest.txt @@ -0,0 +1,52 @@ +mytime : 2009-08-10T10:30:08.142149Z +mytime : 2009-08-10T10:30:08.142149Z +First try size: 512 +Second try size: 264 +Third try size: 264 +md2: {{"Extra.Comment": "Test Extrakeys", +"ProductionDate": "2009-08-10T10:30:08.142149Z", +"ProjectionWKT": "UTM projRef", +"SensorID": "PHR", +}Bands[{"": "B3", +"PhysicalBias": "1", +"PhysicalGain": "2", +},{"": "B2", +"PhysicalBias": "2", +"PhysicalGain": "3", +},{"": "B1", +"PhysicalBias": "3", +"PhysicalGain": "4", +},] +} +md3: {{"Extra.Comment": "Test Extrakeys", +"ProductionDate": "2009-08-10T10:30:08.142149Z", +"ProjectionWKT": "UTM projRef", +"SensorID": "PHR", +}Bands[{"": "B3", +"PhysicalBias": "1", +"PhysicalGain": "2", +},{"": "B2", +"PhysicalBias": "2", +"PhysicalGain": "3", +},] +} +md3_append: {{"Extra.Comment": "Test Extrakeys", +"ProductType": "Official", +"ProjectionEPSG": "4326", +"ProjectionWKT": "UTM projRef", +"ProjectionProj": "+proj=longlat +datum=WGS84 +no_defs ", +"RPC": "{"LineOffset": "0", "SampleOffset": "0", "LatOffset": "0", "LonOffset": "0", "HeightOffset": "0", "LineScale": "0", "SampleScale": "0", "LatScale": "0", "LonScale": "0", "HeightScale": "0", "LineNum": [ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", ], "LineDen": [ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", ], "SampleNum": [ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", ], "SampleDen": [ "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", ], }", +"ProductionDate": "2009-08-10T10:30:08.142149Z", +"GCP": "{"Projection": "", [{"GCP_Id": "", "GCP_Info": "", "GCP_Row": "0", "GCP_Col": "0", "GCP_X": "0", "GCP_Y": "0", "GCP_Z": "0", }, ]}", +"SensorID": "PHR", +}Bands[{"": "B3", +"PhysicalBias": "1", +"PhysicalGain": "2", +},{"": "B2", +"PhysicalBias": "2", +"PhysicalGain": "3", +},{"": "B4", +"PhysicalBias": "3", +"PhysicalGain": "4", +},] +} diff --git a/Modules/Core/Metadata/include/otbGeometryMetadata.h b/Modules/Core/Metadata/include/otbGeometryMetadata.h index dbcc6febdd0f8c455401c5e8826ffb65683537fb..6a55cb9b78e6edfa19a1cc7e0074721507e8f25b 100644 --- a/Modules/Core/Metadata/include/otbGeometryMetadata.h +++ b/Modules/Core/Metadata/include/otbGeometryMetadata.h @@ -26,6 +26,7 @@ #include <string> #include <vector> +#include <sstream> namespace otb { @@ -66,6 +67,7 @@ public: ~OTB_GCP(); void Print(std::ostream& os) const; + std::string ToJSON(bool multiline=false) const; }; namespace Projection @@ -76,6 +78,9 @@ struct OTBMetadata_EXPORT GCPParam std::string GCPProjection; std::vector<OTB_GCP> GCPs; + + // JSON export + std::string ToJSON(bool multiline=false) const; }; /** \struct RPCParam @@ -140,6 +145,18 @@ struct OTBMetadata_EXPORT RPCParam 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + // JSON export + std::string ToJSON(bool multiline=false) const; + inline static std::string doubleArrayToString(const double* array) + { + std::ostringstream oss; + oss << "["; + for (int loop = 0 ; loop < 20 ; loop++) + oss << " \"" << array[loop] << "\", "; + oss << "]"; + return oss.str(); + }; + }; // TODO : add SARParam to define a SAR sensor geometry diff --git a/Modules/Core/Metadata/src/otbGeometryMetadata.cxx b/Modules/Core/Metadata/src/otbGeometryMetadata.cxx index 08d8c80de0d4a319f8241c7a54d62a2098b9ffd5..4c8b19016da9cf324e2880e85761a6828750abdf 100644 --- a/Modules/Core/Metadata/src/otbGeometryMetadata.cxx +++ b/Modules/Core/Metadata/src/otbGeometryMetadata.cxx @@ -41,4 +41,74 @@ void OTB_GCP::Print(std::ostream& os) const os << " GCP (X, Y, Z) = (" << this->m_GCPX << "," << this->m_GCPY << "," << this->m_GCPZ << ")" << std::endl; } +std::string OTB_GCP::ToJSON(bool multiline) const +{ + std::ostringstream oss; + std::string sep; + if (multiline) + { + sep = "\n"; + } + oss << "{" + << "\"GCP_Id\": \"" << this->m_Id << "\", " << sep + << "\"GCP_Info\": \"" << this->m_Info << "\", " << sep + << "\"GCP_Row\": \"" << this->m_GCPRow << "\", " << sep + << "\"GCP_Col\": \"" << this->m_GCPCol << "\", " << sep + << "\"GCP_X\": \"" << this->m_GCPX << "\", " << sep + << "\"GCP_Y\": \"" << this->m_GCPY << "\", " << sep + << "\"GCP_Z\": \"" << this->m_GCPZ << "\", " << sep + << "}"; + return oss.str(); +} + +namespace Projection +{ +std::string GCPParam::ToJSON(bool multiline) const +{ + std::ostringstream oss; + std::string sep; + if (multiline) + { + sep = "\n"; + } + oss << "{" + << "\"Projection\": \"" << GCPProjection << "\", " << sep + << "["; + for (const auto& gcp : GCPs) + oss << gcp.ToJSON() << ", "; + oss << "]}"; + return oss.str(); +} + +std::string RPCParam::ToJSON(bool multiline) const +{ + std::ostringstream oss; + std::string sep; + if (multiline) + { + sep = "\n"; + } + oss << "{" + << "\"LineOffset\": \"" << LineOffset << "\", " << sep + << "\"SampleOffset\": \"" << SampleOffset << "\", " << sep + << "\"LatOffset\": \"" << LatOffset << "\", " << sep + << "\"LonOffset\": \"" << LonOffset << "\", " << sep + << "\"HeightOffset\": \"" << HeightOffset << "\", " << sep + + << "\"LineScale\": \"" << LineScale << "\", " << sep + << "\"SampleScale\": \"" << SampleScale << "\", " << sep + << "\"LatScale\": \"" << LatScale << "\", " << sep + << "\"LonScale\": \"" << LonScale << "\", " << sep + << "\"HeightScale\": \"" << HeightScale << "\", " << sep + + << "\"LineNum\": " << doubleArrayToString(LineNum) << ", " << sep + << "\"LineDen\": " << doubleArrayToString(LineDen) << ", " << sep + << "\"SampleNum\": " << doubleArrayToString(SampleNum) << ", " << sep + << "\"SampleDen\": " << doubleArrayToString(SampleDen) << ", " << sep + + << "}"; + return oss.str(); +} + +} // end namespace Projection } // end namespace otb diff --git a/Modules/Core/Metadata/src/otbImageMetadata.cxx b/Modules/Core/Metadata/src/otbImageMetadata.cxx index 981ab5d9f14e52c20b8cf90217af8563a2e40106..ce03ef626fa24482f274ee5dcca2a99de570c189 100644 --- a/Modules/Core/Metadata/src/otbImageMetadata.cxx +++ b/Modules/Core/Metadata/src/otbImageMetadata.cxx @@ -210,35 +210,65 @@ bool ImageMetadataBase::Has(const std::string& key) const void ImageMetadataBase::ToKeywordlist(Keywordlist& kwl) const { kwl.clear(); - // TODO : Geometry - // The key MDGeom::SensorGeometry should be exported as "<typeinfo>" where - // typeinfo is boost::any::type().name() - for (const auto& kv : StringKeys) + std::string cast_string; + + // Converting the GeomKeys + for (const auto& kv : GeometryKeys) + { + + if (kv.first == MDGeom::RPC) { - kwl.emplace(MetaData::MDStrNames[kv.first], kv.second); + Projection::RPCParam rpcStruct = boost::any_cast<Projection::RPCParam>(kv.second); + cast_string = rpcStruct.ToJSON(); } - for (const auto& kv : NumericKeys) + else if (kv.first == MDGeom::ProjectionEPSG) { + cast_string = std::to_string(boost::any_cast<int>(kv.second)); + } + else if (kv.first == MDGeom::GCP) + { + Projection::GCPParam gcpStruct = boost::any_cast<Projection::GCPParam>(kv.second); + cast_string = gcpStruct.ToJSON(); + } + // TODO : MDGeom::SensorGeometry (should be exported as "<typeinfo>" where typeinfo is boost::any::type().name() + // TODO : MDGeom::SAR + // TODO : MDGeom::Adjustment + else + { + cast_string = boost::any_cast<std::string>(kv.second); + } + kwl.emplace(MetaData::MDGeomNames[kv.first], cast_string); + + } + // Converting the StringKeys + for (const auto& kv : StringKeys) + { + kwl.emplace(MetaData::MDStrNames[kv.first], kv.second); + } + // Converting the NumericKeys + for (const auto& kv : NumericKeys) + { std::ostringstream oss; oss << kv.second; kwl.emplace(MetaData::MDNumNames[kv.first], oss.str()); - } + } + // Converting the LUT1DKeys // TODO : LUT1D - + // Convereting the LUT2DKeys // TODO : LUT2D - + // Converting the TimeKeys for (const auto& kv : TimeKeys) - { + { std::ostringstream oss; oss << kv.second; kwl.emplace(MetaData::MDTimeNames[kv.first], oss.str()); - } - + } + // Converting the ExtraKeys std::string prefix("Extra."); for (const auto& kv : ExtraKeys) - { + { kwl.emplace(prefix + kv.first, kv.second); - } + } } std::string ImageMetadataBase::ToJSON(bool multiline) const @@ -286,8 +316,7 @@ ImageMetadata ImageMetadata::slice(int start, int end) // Copy the bands auto first = this->Bands.cbegin() + start; auto last = this->Bands.cbegin() + end + 1; - ImageMetadataBandsType vect(first, last); - imd.Bands = vect; + imd.Bands = ImageMetadataBandsType(first, last); return imd; } diff --git a/Modules/Core/Metadata/test/otbImageMetadataTest.cxx b/Modules/Core/Metadata/test/otbImageMetadataTest.cxx index e48064fee871b8932f5c5333c6dc8f821581c5b9..fa085e8d405d287ad177a1aba745b37454ecbd1f 100644 --- a/Modules/Core/Metadata/test/otbImageMetadataTest.cxx +++ b/Modules/Core/Metadata/test/otbImageMetadataTest.cxx @@ -38,8 +38,7 @@ int otbImageMetadataTest(int argc, char* argv[]) using namespace otb; const char* outFileName = argv[1]; - std::ofstream outfile; - outfile.open(outFileName); + std::ofstream outfile(outFileName); MetaData::Time mytime; int year, month; @@ -69,8 +68,7 @@ int otbImageMetadataTest(int argc, char* argv[]) outfile << "mytime : "<< mytime << "\n"; - MDNum someKey; - someKey = static_cast<MDNum>(3); + MDNum someKey = static_cast<MDNum>(3); if (someKey == MDNum::PhysicalGain) { outfile << "Found physical gain\n"; @@ -182,19 +180,24 @@ int otbImageMetadataTest(int argc, char* argv[]) bmd.Add(MDNum::PhysicalBias, 3.0); md.Bands.push_back(bmd); - ImageMetadata md2; - md2 = md; + ImageMetadata md2 = md; md.Add(MDGeom::ProjectionWKT, std::string("Lambert projRef")); outfile << "md2: "<< md2 << "\n"; - ImageMetadata md3; - md3 = md2.slice(0, 1); + ImageMetadata md3 = md2.slice(0, 1); outfile << "md3: "<< md3 << "\n"; ImageMetadata md4; md4.Add(MDStr::SensorID, "PHR"); md4.Add(MDStr::ProductType, "Official"); md4.Add(std::string("Comment"), std::string("Test append")); + md4.Add(MDGeom::ProjectionEPSG, 4326); + md4.Add(MDGeom::ProjectionProj, std::string("+proj=longlat +datum=WGS84 +no_defs ")); + Projection::RPCParam rpcStruct; + md4.Add(MDGeom::RPC, rpcStruct); + Projection::GCPParam gcpStruct; + gcpStruct.GCPs.push_back(OTB_GCP()); + md4.Add(MDGeom::GCP, gcpStruct); bmd.Add(MDStr::BandName, "B4"); md4.Bands.push_back(bmd); md3.append(md4);