Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.h2
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.hh17
-rw-r--r--source/blender/blenkernel/intern/cryptomatte.cc87
-rw-r--r--source/blender/blenkernel/intern/cryptomatte_test.cc100
4 files changed, 203 insertions, 3 deletions
diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h
index 8428b5287c1..96e853e7ff8 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.h
+++ b/source/blender/blenkernel/BKE_cryptomatte.h
@@ -38,6 +38,8 @@ struct Object;
struct RenderResult;
struct CryptomatteSession *BKE_cryptomatte_init(void);
+struct CryptomatteSession *BKE_cryptomatte_init_from_render_result(
+ const struct RenderResult *render_result);
void BKE_cryptomatte_free(struct CryptomatteSession *session);
void BKE_cryptomatte_add_layer(struct CryptomatteSession *session, const char *layer_name);
diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh
index 16f4da18e1e..f10b4c1f7c4 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.hh
+++ b/source/blender/blenkernel/BKE_cryptomatte.hh
@@ -86,4 +86,21 @@ struct CryptomatteLayer {
std::optional<std::string> operator[](float encoded_hash) const;
};
+struct CryptomatteStampDataCallbackData {
+ struct CryptomatteSession *session;
+ blender::Map<std::string, std::string> hash_to_layer_name;
+
+ /**
+ * Extract the hash from a stamp data key.
+ *
+ * Cryptomatte keys are formatted as "cryptomatte/{layer_hash}/{attribute}".
+ */
+ static blender::StringRef extract_layer_hash(blender::StringRefNull key);
+
+ /* C type callback function (StampCallback). */
+ static void extract_layer_names(void *_data, const char *propname, char *propvalue, int len);
+ /* C type callback function (StampCallback). */
+ static void extract_layer_manifest(void *_data, const char *propname, char *propvalue, int len);
+};
+
} // namespace blender::bke::cryptomatte
diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc
index 3ecbbe56a22..a20c53ed270 100644
--- a/source/blender/blenkernel/intern/cryptomatte.cc
+++ b/source/blender/blenkernel/intern/cryptomatte.cc
@@ -37,6 +37,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "RE_pipeline.h"
+
#include "MEM_guardedalloc.h"
#include <cctype>
@@ -51,6 +53,7 @@ struct CryptomatteSession {
CryptomatteSession();
CryptomatteSession(const Main *bmain);
+ CryptomatteSession(StampData *metadata);
blender::bke::cryptomatte::CryptomatteLayer &add_layer(std::string layer_name);
std::optional<std::string> operator[](float encoded_hash) const;
@@ -80,6 +83,22 @@ CryptomatteSession::CryptomatteSession(const Main *bmain)
}
}
+CryptomatteSession::CryptomatteSession(StampData *stamp_data)
+{
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData callback_data;
+ callback_data.session = this;
+ BKE_stamp_info_callback(
+ &callback_data,
+ stamp_data,
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_names,
+ false);
+ BKE_stamp_info_callback(
+ &callback_data,
+ stamp_data,
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_manifest,
+ false);
+}
+
blender::bke::cryptomatte::CryptomatteLayer &CryptomatteSession::add_layer(std::string layer_name)
{
return layers.lookup_or_add_default(layer_name);
@@ -102,6 +121,13 @@ CryptomatteSession *BKE_cryptomatte_init(void)
return session;
}
+struct CryptomatteSession *BKE_cryptomatte_init_from_render_result(
+ const struct RenderResult *render_result)
+{
+ CryptomatteSession *session = new CryptomatteSession(render_result->stamp_data);
+ return session;
+}
+
void BKE_cryptomatte_add_layer(struct CryptomatteSession *session, const char *layer_name)
{
session->add_layer(layer_name);
@@ -502,4 +528,65 @@ std::string CryptomatteLayer::manifest() const
return blender::bke::cryptomatte::manifest::to_manifest(this);
}
+blender::StringRef CryptomatteStampDataCallbackData::extract_layer_hash(blender::StringRefNull key)
+{
+ BLI_assert(key.startswith("cryptomatte/"));
+
+ size_t start_index = key.find_first_of('/');
+ size_t end_index = key.find_last_of('/');
+ if (start_index == blender::StringRef::not_found) {
+ return "";
+ }
+ if (end_index == blender::StringRef::not_found) {
+ return "";
+ }
+ if (end_index <= start_index) {
+ return "";
+ }
+ return key.substr(start_index + 1, end_index - start_index - 1);
+}
+
+void CryptomatteStampDataCallbackData::extract_layer_names(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ CryptomatteStampDataCallbackData *data = static_cast<CryptomatteStampDataCallbackData *>(_data);
+
+ blender::StringRefNull key(propname);
+ if (!key.startswith("cryptomatte/")) {
+ return;
+ }
+ if (!key.endswith("/name")) {
+ return;
+ }
+ blender::StringRef layer_hash = extract_layer_hash(key);
+ data->hash_to_layer_name.add(layer_hash, propvalue);
+}
+
+/* C type callback function (StampCallback). */
+void CryptomatteStampDataCallbackData::extract_layer_manifest(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ CryptomatteStampDataCallbackData *data = static_cast<CryptomatteStampDataCallbackData *>(_data);
+
+ blender::StringRefNull key(propname);
+ if (!key.startswith("cryptomatte/")) {
+ return;
+ }
+ if (!key.endswith("/manifest")) {
+ return;
+ }
+ blender::StringRef layer_hash = extract_layer_hash(key);
+ if (!data->hash_to_layer_name.contains(layer_hash)) {
+ return;
+ }
+
+ blender::StringRef layer_name = data->hash_to_layer_name.lookup(layer_hash);
+ blender::bke::cryptomatte::CryptomatteLayer &layer = data->session->add_layer(layer_name);
+ blender::bke::cryptomatte::manifest::from_manifest(layer, propvalue);
+}
+
} // namespace blender::bke::cryptomatte
diff --git a/source/blender/blenkernel/intern/cryptomatte_test.cc b/source/blender/blenkernel/intern/cryptomatte_test.cc
index 4a25f5f7d87..d9be252d654 100644
--- a/source/blender/blenkernel/intern/cryptomatte_test.cc
+++ b/source/blender/blenkernel/intern/cryptomatte_test.cc
@@ -17,7 +17,13 @@
*/
#include "testing/testing.h"
+#include "BKE_cryptomatte.h"
#include "BKE_cryptomatte.hh"
+#include "BKE_image.h"
+
+#include "RE_pipeline.h"
+
+#include "MEM_guardedalloc.h"
namespace blender::bke::cryptomatte::tests {
@@ -41,7 +47,7 @@ TEST(cryptomatte, extract_layer_name)
ASSERT_EQ("", BKE_cryptomatte_extract_layer_name(""));
}
-TEST(cryptomatte, cryptomatte_layer)
+TEST(cryptomatte, layer)
{
blender::bke::cryptomatte::CryptomatteLayer layer;
ASSERT_EQ("{}", layer.manifest());
@@ -53,7 +59,7 @@ TEST(cryptomatte, cryptomatte_layer)
ASSERT_EQ("{\"Object\":\"0000007b\",\"Object2\":\"0758946e\"}", layer.manifest());
}
-TEST(cryptomatte, cryptomatte_layer_quoted)
+TEST(cryptomatte, layer_quoted)
{
blender::bke::cryptomatte::CryptomatteLayer layer;
layer.add_hash("\"Object\"", 123);
@@ -66,7 +72,7 @@ static void test_cryptomatte_manifest(std::string expected, std::string manifest
blender::bke::cryptomatte::CryptomatteLayer::read_from_manifest(manifest)->manifest());
}
-TEST(cryptomatte, cryptomatte_layer_from_manifest)
+TEST(cryptomatte, layer_from_manifest)
{
test_cryptomatte_manifest("{}", "{}");
test_cryptomatte_manifest("{\"Object\":\"12345678\"}", "{\"Object\": \"12345678\"}");
@@ -82,4 +88,92 @@ TEST(cryptomatte, cryptomatte_layer_from_manifest)
"{\"Object\\\"01\\\"\":\"12345678\",\"Object\":\"12345678\", \"Object2\":\"87654321\"}");
}
+TEST(cryptomatte, extract_layer_hash_from_metadata_key)
+{
+ EXPECT_EQ("eb4c67b",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/eb4c67b/conversion"));
+ EXPECT_EQ("qwerty",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/qwerty/name"));
+ /* Check if undefined behaviors are handled. */
+ EXPECT_EQ("",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/name"));
+ EXPECT_EQ("",
+ blender::bke::cryptomatte::CryptomatteStampDataCallbackData::extract_layer_hash(
+ "cryptomatte/"));
+}
+
+static void validate_cryptomatte_session_from_stamp_data(void *UNUSED(data),
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ blender::StringRefNull prop_name(propname);
+ if (!prop_name.startswith("cryptomatte/")) {
+ return;
+ }
+
+ if (prop_name == "cryptomatte/87f095e/name") {
+ EXPECT_STREQ("viewlayername.layer1", propvalue);
+ }
+ else if (prop_name == "cryptomatte/87f095e/hash") {
+ EXPECT_STREQ("MurmurHash3_32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/87f095e/conversion") {
+ EXPECT_STREQ("uint32_to_float32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/87f095e/manifest") {
+ EXPECT_STREQ("{\"Object\":\"12345678\"}", propvalue);
+ }
+
+ else if (prop_name == "cryptomatte/c42daa7/name") {
+ EXPECT_STREQ("viewlayername.layer2", propvalue);
+ }
+ else if (prop_name == "cryptomatte/c42daa7/hash") {
+ EXPECT_STREQ("MurmurHash3_32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/c42daa7/conversion") {
+ EXPECT_STREQ("uint32_to_float32", propvalue);
+ }
+ else if (prop_name == "cryptomatte/c42daa7/manifest") {
+ EXPECT_STREQ("{\"Object2\":\"87654321\"}", propvalue);
+ }
+
+ else {
+ EXPECT_EQ("Unhandled", std::string(propname) + ": " + propvalue);
+ }
+}
+
+TEST(cryptomatte, session_from_stamp_data)
+{
+ /* Create CryptomatteSession from stamp data. */
+ RenderResult *render_result = static_cast<RenderResult *>(
+ MEM_callocN(sizeof(RenderResult), __func__));
+ BKE_render_result_stamp_data(render_result, "cryptomatte/qwerty/name", "layer1");
+ BKE_render_result_stamp_data(
+ render_result, "cryptomatte/qwerty/manifest", "{\"Object\":\"12345678\"}");
+ BKE_render_result_stamp_data(render_result, "cryptomatte/uiop/name", "layer2");
+ BKE_render_result_stamp_data(
+ render_result, "cryptomatte/uiop/manifest", "{\"Object2\":\"87654321\"}");
+ CryptomatteSession *session = BKE_cryptomatte_init_from_render_result(render_result);
+ EXPECT_NE(session, nullptr);
+ RE_FreeRenderResult(render_result);
+
+ /* Create StampData from CryptomatteSession. */
+ ViewLayer view_layer;
+ BLI_strncpy(view_layer.name, "viewlayername", sizeof(view_layer.name));
+ RenderResult *render_result2 = static_cast<RenderResult *>(
+ MEM_callocN(sizeof(RenderResult), __func__));
+ BKE_cryptomatte_store_metadata(session, render_result2, &view_layer);
+
+ /* Validate StampData. */
+ BKE_stamp_info_callback(
+ nullptr, render_result2->stamp_data, validate_cryptomatte_session_from_stamp_data, false);
+
+ RE_FreeRenderResult(render_result2);
+ BKE_cryptomatte_free(session);
+}
+
} // namespace blender::bke::cryptomatte::tests