1 #include "dynamic_depth/depth_map.h" 2 3 #include "android-base/logging.h" 4 #include "dynamic_depth/const.h" 5 #include "dynamic_depth/item.h" 6 #include "strings/numbers.h" 7 #include "xmpmeta/base64.h" 8 9 using ::dynamic_depth::Item; 10 using ::dynamic_depth::xmpmeta::EncodeFloatArrayBase64; 11 using ::dynamic_depth::xmpmeta::xml::Deserializer; 12 using ::dynamic_depth::xmpmeta::xml::Serializer; 13 14 namespace dynamic_depth { 15 namespace { 16 constexpr const char* kNamespaceHref = 17 "http://ns.google.com/photos/dd/1.0/depthmap/"; 18 19 constexpr const char* kFormat = "Format"; 20 constexpr const char* kNear = "Near"; 21 constexpr const char* kFar = "Far"; 22 constexpr const char* kUnits = "Units"; 23 constexpr const char* kDepthUri = "DepthURI"; 24 constexpr const char* kItemSemantic = "ItemSemantic"; 25 constexpr const char* kConfidenceUri = "ConfidenceURI"; 26 constexpr const char* kMeasureType = "MeasureType"; 27 constexpr const char* kSoftware = "Software"; 28 constexpr const char* kFocalTable = "FocalTable"; 29 constexpr const char* kFocalTableEntryCount = "FocalTableEntryCount"; 30 31 constexpr const char* kFormatRangeInverse = "RangeInverse"; 32 constexpr const char* kFormatRangeLinear = "RangeLinear"; 33 constexpr const char* kFormatRangeInverseLower = "rangeinverse"; 34 constexpr const char* kFormatRangeLinearLower = "rangelinear"; 35 36 constexpr const char* kUnitsMeters = "Meters"; 37 constexpr const char* kUnitsDiopters = "Diopters"; 38 constexpr const char* kUnitsNone = "None"; 39 constexpr const char* kUnitsMetersLower = "meters"; 40 constexpr const char* kUnitsDioptersLower = "diopters"; 41 42 constexpr const char* kMeasureTypeOpticalAxis = "OpticalAxis"; 43 constexpr const char* kMeasureTypeOpticRay = "OpticRay"; 44 constexpr const char* kMeasureTypeOpticRayLower = "opticray"; 45 46 constexpr const char* kItemSemanticDepth = "Depth"; 47 constexpr const char* kItemSemanticSegmentation = "Segmentation"; 48 constexpr const char* kItemSemanticSegmentationLower = "segmentation"; 49 50 string ItemSemanticToString(DepthItemSemantic item_semantic) { 51 switch (item_semantic) { 52 case DepthItemSemantic::kDepth: 53 return kItemSemanticDepth; 54 case DepthItemSemantic::kSegmentation: 55 return kItemSemanticSegmentation; 56 } 57 } 58 59 DepthItemSemantic StringToItemSemantic(const string& semantic_str) { 60 string semantic_str_lower = semantic_str; 61 std::transform(semantic_str_lower.begin(), semantic_str_lower.end(), 62 semantic_str_lower.begin(), ::tolower); 63 if (kItemSemanticSegmentationLower == semantic_str_lower) { 64 return DepthItemSemantic::kSegmentation; 65 } 66 67 return DepthItemSemantic::kDepth; 68 } 69 70 string FormatToString(DepthFormat format) { 71 switch (format) { 72 case DepthFormat::kRangeInverse: 73 return kFormatRangeInverse; 74 case DepthFormat::kRangeLinear: 75 return kFormatRangeLinear; 76 case DepthFormat::kFormatNone: 77 return ""; 78 } 79 } 80 81 // Case insensitive. 82 DepthFormat StringToFormat(const string& format_str) { 83 string format_str_lower = format_str; 84 std::transform(format_str_lower.begin(), format_str_lower.end(), 85 format_str_lower.begin(), ::tolower); 86 if (kFormatRangeInverseLower == format_str_lower) { 87 return DepthFormat::kRangeInverse; 88 } 89 90 if (kFormatRangeLinearLower == format_str_lower) { 91 return DepthFormat::kRangeLinear; 92 } 93 94 return DepthFormat::kFormatNone; 95 } 96 97 string UnitsToString(DepthUnits units) { 98 switch (units) { 99 case DepthUnits::kMeters: 100 return kUnitsMeters; 101 case DepthUnits::kDiopters: 102 return kUnitsDiopters; 103 case DepthUnits::kUnitsNone: 104 return kUnitsNone; 105 } 106 } 107 108 DepthUnits StringToUnits(const string& units_str) { 109 string units_str_lower = units_str; 110 std::transform(units_str_lower.begin(), units_str_lower.end(), 111 units_str_lower.begin(), ::tolower); 112 if (kUnitsMetersLower == units_str_lower) { 113 return DepthUnits::kMeters; 114 } 115 116 if (kUnitsDioptersLower == units_str_lower) { 117 return DepthUnits::kDiopters; 118 } 119 120 return DepthUnits::kUnitsNone; 121 } 122 123 string MeasureTypeToString(DepthMeasureType measure_type) { 124 switch (measure_type) { 125 case DepthMeasureType::kOpticRay: 126 return kMeasureTypeOpticRay; 127 case DepthMeasureType::kOpticalAxis: 128 return kMeasureTypeOpticalAxis; 129 } 130 } 131 132 DepthMeasureType StringToMeasureType(const string& measure_type_str) { 133 string measure_type_str_lower = measure_type_str; 134 std::transform(measure_type_str_lower.begin(), measure_type_str_lower.end(), 135 measure_type_str_lower.begin(), ::tolower); 136 if (kMeasureTypeOpticRayLower == measure_type_str_lower) { 137 return DepthMeasureType::kOpticRay; 138 } 139 140 return DepthMeasureType::kOpticalAxis; 141 } 142 143 } // namespace 144 145 // Private constructor. 146 DepthMap::DepthMap(const DepthMapParams& params) : params_(params) {} 147 148 // Private parser. 149 std::unique_ptr<DepthMap> DepthMap::ParseFields( 150 const Deserializer& deserializer) { 151 const string& prefix = DynamicDepthConst::DepthMap(); 152 string format_str; 153 float near; 154 float far; 155 string units_str; 156 string depth_uri; 157 string item_semantic_str; 158 159 if (!deserializer.ParseString(prefix, kItemSemantic, &item_semantic_str) || 160 !deserializer.ParseString(prefix, kFormat, &format_str) || 161 !deserializer.ParseFloat(prefix, kNear, &near) || 162 !deserializer.ParseFloat(prefix, kFar, &far) || 163 !deserializer.ParseString(prefix, kUnits, &units_str) || 164 !deserializer.ParseString(prefix, kDepthUri, &depth_uri)) { 165 return nullptr; 166 } 167 168 DepthMapParams params(StringToFormat(format_str), near, far, 169 StringToUnits(units_str), depth_uri); 170 params.item_semantic = StringToItemSemantic(item_semantic_str); 171 172 string confidence_uri; 173 if (deserializer.ParseString(prefix, kConfidenceUri, &confidence_uri)) { 174 params.confidence_uri = confidence_uri; 175 } 176 177 string measure_type_str; 178 if (deserializer.ParseString(prefix, kMeasureType, &measure_type_str)) { 179 params.measure_type = StringToMeasureType(measure_type_str); 180 } 181 182 string software; 183 if (deserializer.ParseString(prefix, kSoftware, &software)) { 184 params.software = software; 185 } 186 187 std::vector<float> focal_table; 188 int focal_table_entry_count; 189 if (deserializer.ParseFloatArrayBase64(prefix, kFocalTable, &focal_table) && 190 (!deserializer.ParseInt(prefix, kFocalTableEntryCount, 191 &focal_table_entry_count) && 192 focal_table.size() / 2 != focal_table_entry_count)) { 193 return nullptr; 194 } 195 params.focal_table = focal_table; 196 197 return std::unique_ptr<DepthMap>(new DepthMap(params)); // NOLINT 198 } 199 200 // Public methods. 201 void DepthMap::GetNamespaces( 202 std::unordered_map<string, string>* ns_name_href_map) { 203 if (ns_name_href_map == nullptr) { 204 LOG(ERROR) << "Namespace list or own namespace is null"; 205 return; 206 } 207 ns_name_href_map->emplace(DynamicDepthConst::DepthMap(), kNamespaceHref); 208 } 209 210 std::unique_ptr<DepthMap> DepthMap::FromData( 211 const DepthMapParams& params, std::vector<std::unique_ptr<Item>>* items) { 212 if (params.format == DepthFormat::kFormatNone) { 213 LOG(ERROR) 214 << "Format must be specified, cannot be of type DepthFormat::NONE"; 215 return nullptr; 216 } 217 218 if (params.depth_uri.empty() || params.depth_image_data.empty()) { 219 LOG(ERROR) << "Depth image data and URI must be provided"; 220 return nullptr; 221 } 222 223 if (!params.focal_table.empty() && params.focal_table.size() % 2 != 0) { 224 LOG(ERROR) << "Focal table entries must consist of pairs"; 225 return nullptr; 226 } 227 228 if (items == nullptr) { 229 LOG(ERROR) << "List of items is null"; 230 return nullptr; 231 } 232 233 if (params.mime.empty()) { 234 LOG(ERROR) << "Depth image mime must be provided to DepthMapParams"; 235 return nullptr; 236 } 237 238 ItemParams depth_item_params(params.mime, params.depth_image_data.size(), 239 params.depth_uri); 240 depth_item_params.payload_to_serialize = params.depth_image_data; 241 items->emplace_back(Item::FromData(depth_item_params)); 242 243 bool available_confidence_uri_and_data = true; 244 if (!params.confidence_uri.empty() && !params.confidence_data.empty()) { 245 // Assumes that the confidence mime is the same as that of the depth map. 246 ItemParams confidence_item_params( 247 params.mime, params.confidence_data.size(), params.confidence_uri); 248 confidence_item_params.payload_to_serialize = params.confidence_data; 249 items->emplace_back(Item::FromData(confidence_item_params)); 250 } else if (!params.confidence_uri.empty() && params.confidence_data.empty()) { 251 LOG(ERROR) << "No confidence data provided, the URI will be set to empty " 252 "and not serialized"; 253 available_confidence_uri_and_data = false; 254 } 255 256 auto depth_map = std::unique_ptr<DepthMap>(new DepthMap(params)); // NOLINT 257 if (!available_confidence_uri_and_data) { 258 // Ensure we don't serialize the confidence URI if no data has been 259 // provided. 260 depth_map->params_.confidence_uri = ""; 261 } 262 263 return depth_map; 264 } 265 266 std::unique_ptr<DepthMap> DepthMap::FromDeserializer( 267 const Deserializer& parent_deserializer) { 268 std::unique_ptr<Deserializer> deserializer = 269 parent_deserializer.CreateDeserializer( 270 DynamicDepthConst::Namespace(DynamicDepthConst::DepthMap()), 271 DynamicDepthConst::DepthMap()); 272 if (deserializer == nullptr) { 273 return nullptr; 274 } 275 276 return ParseFields(*deserializer); 277 } 278 279 DepthFormat DepthMap::GetFormat() const { return params_.format; } 280 float DepthMap::GetNear() const { return params_.near; } 281 float DepthMap::GetFar() const { return params_.far; } 282 DepthUnits DepthMap::GetUnits() const { return params_.units; } 283 const string DepthMap::GetDepthUri() const { return params_.depth_uri; } 284 DepthItemSemantic DepthMap::GetItemSemantic() const { 285 return params_.item_semantic; 286 } 287 const string DepthMap::GetConfidenceUri() const { 288 return params_.confidence_uri; 289 } 290 291 DepthMeasureType DepthMap::GetMeasureType() const { 292 return params_.measure_type; 293 } 294 295 const string DepthMap::GetSoftware() const { return params_.software; } 296 const std::vector<float>& DepthMap::GetFocalTable() const { 297 return params_.focal_table; 298 } 299 300 size_t DepthMap::GetFocalTableEntryCount() const { 301 return params_.focal_table.size() / 2; 302 } 303 304 bool DepthMap::Serialize(Serializer* serializer) const { 305 if (serializer == nullptr) { 306 LOG(ERROR) << "Serializer is null"; 307 return false; 308 } 309 if (params_.depth_uri.empty()) { 310 LOG(ERROR) << "Depth image URI is empty"; 311 return false; 312 } 313 314 const string& prefix = DynamicDepthConst::DepthMap(); 315 // Error checking is already done in FromData. 316 if (!serializer->WriteProperty(prefix, kItemSemantic, 317 ItemSemanticToString(params_.item_semantic)) || 318 !serializer->WriteProperty(prefix, kFormat, 319 FormatToString(params_.format)) || 320 !serializer->WriteProperty(prefix, kUnits, 321 UnitsToString(params_.units)) || 322 !serializer->WriteProperty(prefix, kNear, std::to_string(params_.near)) || 323 !serializer->WriteProperty(prefix, kFar, std::to_string(params_.far)) || 324 !serializer->WriteProperty(prefix, kDepthUri, params_.depth_uri)) { 325 return false; 326 } 327 328 serializer->WriteProperty(prefix, kMeasureType, 329 MeasureTypeToString(params_.measure_type)); 330 331 if (!params_.confidence_uri.empty()) { 332 serializer->WriteProperty(prefix, kConfidenceUri, params_.confidence_uri); 333 } 334 335 if (!params_.software.empty()) { 336 serializer->WriteProperty(prefix, kSoftware, params_.software); 337 } 338 339 if (!params_.focal_table.empty()) { 340 string base64_encoded_focal_table; 341 if (!EncodeFloatArrayBase64(params_.focal_table, 342 &base64_encoded_focal_table)) { 343 LOG(ERROR) << "Focal table encoding failed"; 344 } else { 345 int focal_table_entry_count = 346 static_cast<int>(params_.focal_table.size() / 2); 347 if (!serializer->WriteProperty( 348 prefix, kFocalTableEntryCount, 349 ::dynamic_depth::strings::SimpleItoa(focal_table_entry_count)) || 350 !serializer->WriteProperty(prefix, kFocalTable, 351 base64_encoded_focal_table)) { 352 LOG(ERROR) << "Focal table or entry count could not be serialized"; 353 } 354 } 355 } 356 357 return true; 358 } 359 360 } // namespace dynamic_depth 361