diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d0bb390..59e9ab38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ cmake_minimum_required(VERSION 3.27) # This is the current version of this C++ project -project(c2pa-c VERSION 0.23.14) +project(c2pa-c VERSION 0.23.15) # Set the version of the c2pa_rs library used set(C2PA_VERSION "0.86.1") diff --git a/include/c2pa.hpp b/include/c2pa.hpp index 53755447..a79576de 100644 --- a/include/c2pa.hpp +++ b/include/c2pa.hpp @@ -935,6 +935,14 @@ namespace c2pa /// @throws C2paException for errors encountered by the C2PA library. std::string detailed_json() const; + /// @brief Get the manifest store as a pretty-printed crJSON string. + /// @details crJSON is a standardized JSON format for C2PA manifest data. + /// This call is infallible at yields valid empty JSON ("{}") if + /// there are no Content Credentials. + /// @return The manifest store as a crJSON string. + /// @throws C2paException if the underlying C call returns null. + std::string crjson() const; + /// @brief Get a resource from the reader and write it to a file. /// @param uri The URI of the resource. /// @param path The file path to write the resource to. diff --git a/src/c2pa_reader.cpp b/src/c2pa_reader.cpp index b47210d5..909e61e7 100644 --- a/src/c2pa_reader.cpp +++ b/src/c2pa_reader.cpp @@ -167,6 +167,11 @@ namespace c2pa return detail::c_string_to_string(c2pa_reader_detailed_json(c2pa_reader)); } + std::string Reader::crjson() const + { + return detail::c_string_to_string(c2pa_reader_crjson(c2pa_reader)); + } + [[nodiscard]] std::optional Reader::remote_url() const { auto url = c2pa_reader_remote_url(c2pa_reader); if (url == nullptr) { return std::nullopt; } diff --git a/tests/reader.test.cpp b/tests/reader.test.cpp index 8c56bce8..68827ee4 100644 --- a/tests/reader.test.cpp +++ b/tests/reader.test.cpp @@ -694,3 +694,27 @@ TEST_F(ReaderTest, ReadArchive) EXPECT_TRUE(active_manifest.contains("ingredients")); EXPECT_EQ(active_manifest["ingredients"].size(), 2); } + +TEST_F(ReaderTest, ReadCrJson) +{ + fs::path current_dir = fs::path(__FILE__).parent_path(); + fs::path test_file = current_dir / "../tests/fixtures/cloud.jpg"; + + auto reader = c2pa::Reader(test_file); + auto crjson = reader.crjson(); + EXPECT_FALSE(crjson.empty()); +} + +TEST_F(ReaderTest, ReadCrJsonSpecialChars) +{ + auto current_dir = fs::path(__FILE__).parent_path(); + #ifdef _WIN32 + auto test_file = current_dir.parent_path() / "tests" / "fixtures" / L"CÖÄ_.jpg"; + #else + auto test_file = current_dir.parent_path() / "tests" / "fixtures" / "CÖÄ_.jpg"; + #endif + + auto reader = c2pa::Reader(test_file); + auto crjson = reader.crjson(); + EXPECT_FALSE(crjson.empty()); +}