[Bf-blender-cvs] [7dd57300038] temp-cryptomatte-manifest-parser: Cryptomatte manifest reader.
Jeroen Bakker
noreply at git.blender.org
Fri Feb 26 10:04:28 CET 2021
Commit: 7dd57300038794255e2cac76b38ff552a9163c4d
Author: Jeroen Bakker
Date: Fri Feb 26 10:03:14 2021 +0100
Branches: temp-cryptomatte-manifest-parser
https://developer.blender.org/rB7dd57300038794255e2cac76b38ff552a9163c4d
Cryptomatte manifest reader.
With the cryptomatte manifest reader it is possible to construct a
cryptomatte layer from a manifest.
===================================================================
M source/blender/blenkernel/BKE_cryptomatte.hh
M source/blender/blenkernel/intern/cryptomatte.cc
M source/blender/blenkernel/intern/cryptomatte_test.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh
index 00969c0b52c..5849139f2cd 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.hh
+++ b/source/blender/blenkernel/BKE_cryptomatte.hh
@@ -64,10 +64,7 @@ struct CryptomatteLayer {
MEM_CXX_CLASS_ALLOC_FUNCS("cryptomatte:CryptomatteLayer")
#endif
- CryptomatteLayer();
- /** Create a cryptomatte layer from the given manifest. */
- CryptomatteLayer(blender::StringRefNull manifest);
-
+ static std::unique_ptr<CryptomatteLayer> read_from_manifest(blender::StringRefNull manifest);
static std::string encode_hash(uint32_t cryptomatte_hash);
void add_hash(blender::StringRef name, uint32_t cryptomatte_hash);
void add_encoded_hash(blender::StringRef name, blender::StringRefNull cryptomatte_encoded_hash);
diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc
index 492138b8783..fa5bc157bc1 100644
--- a/source/blender/blenkernel/intern/cryptomatte.cc
+++ b/source/blender/blenkernel/intern/cryptomatte.cc
@@ -315,12 +315,12 @@ StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name)
return render_pass_name.substr(0, last_token);
}
-struct CryptomatteManifestParser {
- int skip_whitespaces_len_(blender::StringRef manifest)
+struct CryptomatteManifestReader {
+ static constexpr int skip_whitespaces_len_(blender::StringRef ref)
{
int skip_len = 0;
- while (!manifest.is_empty()) {
- char front = manifest[skip_len];
+ while (skip_len < ref.size()) {
+ char front = ref[skip_len];
if (!std::isspace<char>(front, std::locale::classic())) {
break;
}
@@ -329,24 +329,56 @@ struct CryptomatteManifestParser {
return skip_len;
}
- int quoted_string_len_(blender::StringRef ref)
+ static constexpr blender::StringRef skip_whitespaces_(blender::StringRef ref)
+ {
+ return ref.drop_prefix(skip_whitespaces_len_(ref));
+ }
+
+ static constexpr int quoted_string_len_(blender::StringRef ref)
{
int len = 1;
+ bool skip_next = false;
while (len < ref.size()) {
char current_char = ref[len];
- if (current_char == '\"') {
- len += 1;
- break;
+ if (skip_next) {
+ skip_next = false;
+ }
+ else {
+ if (current_char == '\\') {
+ skip_next = true;
+ }
+ if (current_char == '\"') {
+ len += 1;
+ break;
+ }
}
len += 1;
}
return len;
}
- bool parse(CryptomatteLayer &layer, blender::StringRefNull manifest)
+ static std::string unquote_(const blender::StringRef ref)
+ {
+ std::ostringstream stream;
+ for (char c : ref) {
+ if (c != '\\') {
+ stream << c;
+ }
+ }
+ return stream.str();
+ }
+
+ static uint32_t decode_hash_(const blender::StringRef ref)
+ {
+ uint32_t result;
+ std::istringstream(ref) >> std::hex >> result;
+ return result;
+ }
+
+ static bool parse(CryptomatteLayer &layer, blender::StringRefNull manifest)
{
StringRef ref = manifest;
- ref = ref.drop_prefix(skip_whitespaces_len_(ref));
+ ref = skip_whitespaces_(ref);
if (ref.is_empty() || ref.front() != '{') {
return false;
}
@@ -357,32 +389,36 @@ struct CryptomatteManifestParser {
if (front == '\"') {
const int quoted_name_len = quoted_string_len_(ref);
const int name_len = quoted_name_len - 2;
- blender::StringRef name = ref.substr(1, name_len);
+ std::string name = unquote_(ref.substr(1, name_len));
ref = ref.drop_prefix(quoted_name_len);
- ref = ref.drop_prefix(skip_whitespaces_len_(ref));
+ ref = skip_whitespaces_(ref);
char colon = ref.front();
if (colon != ':') {
return false;
}
- ref = ref.drop_prefix(skip_whitespaces_len_(ref));
+ ref = ref.drop_prefix(1);
+ ref = skip_whitespaces_(ref);
+
+ if (ref.front() != '\"') {
+ return false;
+ }
const int quoted_hash_len = quoted_string_len_(ref);
const int hash_len = quoted_hash_len - 2;
- blender::StringRef hash = ref.substr(1, hash_len);
+ uint32_t hash = decode_hash_(ref.substr(1, hash_len));
ref = ref.drop_prefix(quoted_hash_len);
- layer.add_encoded_hash(name, blender::StringRefNull(hash));
+ layer.add_hash(name, hash);
}
- if (front == ',') {
+ else if (front == ',') {
ref = ref.drop_prefix(1);
}
- if (front == '}') {
+ else if (front == '}') {
ref = ref.drop_prefix(1);
- ref = ref.drop_prefix(skip_whitespaces_len_(ref));
-
+ ref = skip_whitespaces_(ref);
break;
}
- ref = ref.drop_prefix(skip_whitespaces_len_(ref));
+ ref = skip_whitespaces_(ref);
}
if (!ref.is_empty()) {
@@ -393,14 +429,12 @@ struct CryptomatteManifestParser {
}
};
-CryptomatteLayer::CryptomatteLayer()
-{
-}
-
-CryptomatteLayer::CryptomatteLayer(blender::StringRefNull manifest)
+std::unique_ptr<CryptomatteLayer> CryptomatteLayer::read_from_manifest(
+ blender::StringRefNull manifest)
{
- CryptomatteManifestParser parser;
- parser.parse(*this, manifest);
+ std::unique_ptr<CryptomatteLayer> layer = std::make_unique<CryptomatteLayer>();
+ CryptomatteManifestReader::parse(*layer.get(), manifest);
+ return layer;
}
std::string CryptomatteLayer::encode_hash(uint32_t cryptomatte_hash)
diff --git a/source/blender/blenkernel/intern/cryptomatte_test.cc b/source/blender/blenkernel/intern/cryptomatte_test.cc
index fe80d919d23..010c809eed5 100644
--- a/source/blender/blenkernel/intern/cryptomatte_test.cc
+++ b/source/blender/blenkernel/intern/cryptomatte_test.cc
@@ -60,9 +60,25 @@ TEST(cryptomatte, cryptomatte_layer_quoted)
ASSERT_EQ("{\"\\\"Object\\\"\":\"0000007b\"}", layer.manifest());
}
+static void test_cryptomatte_manifest(std::string expected, std::string manifest)
+{
+ EXPECT_EQ(expected, blender::CryptomatteLayer::read_from_manifest(manifest)->manifest());
+}
+
TEST(cryptomatte, cryptomatte_layer_from_manifest)
{
- ASSERT_EQ("{}", blender::CryptomatteLayer("{}").manifest());
+ test_cryptomatte_manifest("{}", "{}");
+ test_cryptomatte_manifest("{\"Object\":\"12345678\"}", "{\"Object\": \"12345678\"}");
+ test_cryptomatte_manifest("{\"Object\":\"12345678\",\"Object2\":\"87654321\"}",
+ "{\"Object\":\"12345678\",\"Object2\":\"87654321\"}");
+ test_cryptomatte_manifest(
+ "{\"Object\":\"12345678\",\"Object2\":\"87654321\"}",
+ " { \"Object\" : \"12345678\" , \"Object2\" : \"87654321\" } ");
+ test_cryptomatte_manifest("{\"Object\\\"01\\\"\":\"12345678\"}",
+ "{\"Object\\\"01\\\"\": \"12345678\"}");
+ test_cryptomatte_manifest(
+ "{\"Object\\\"01\\\"\":\"12345678\",\"Object\":\"12345678\",\"Object2\":\"87654321\"}",
+ "{\"Object\\\"01\\\"\":\"12345678\",\"Object\":\"12345678\", \"Object2\":\"87654321\"}");
}
} // namespace blender::bke::tests
More information about the Bf-blender-cvs
mailing list