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 
ItemSemanticToString(DepthItemSemantic item_semantic)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 
StringToItemSemantic(const string & semantic_str)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 
FormatToString(DepthFormat format)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.
StringToFormat(const string & format_str)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 
UnitsToString(DepthUnits units)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 
StringToUnits(const string & units_str)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 
MeasureTypeToString(DepthMeasureType measure_type)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 
StringToMeasureType(const string & measure_type_str)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.
DepthMap(const DepthMapParams & params)146 DepthMap::DepthMap(const DepthMapParams& params) : params_(params) {}
147 
148 // Private parser.
ParseFields(const Deserializer & deserializer)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.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)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 
FromData(const DepthMapParams & params,std::vector<std::unique_ptr<Item>> * items)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 
FromDeserializer(const Deserializer & parent_deserializer)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 
GetFormat() const279 DepthFormat DepthMap::GetFormat() const { return params_.format; }
GetNear() const280 float DepthMap::GetNear() const { return params_.near; }
GetFar() const281 float DepthMap::GetFar() const { return params_.far; }
GetUnits() const282 DepthUnits DepthMap::GetUnits() const { return params_.units; }
GetDepthUri() const283 const string DepthMap::GetDepthUri() const { return params_.depth_uri; }
GetItemSemantic() const284 DepthItemSemantic DepthMap::GetItemSemantic() const {
285   return params_.item_semantic;
286 }
GetConfidenceUri() const287 const string DepthMap::GetConfidenceUri() const {
288   return params_.confidence_uri;
289 }
290 
GetMeasureType() const291 DepthMeasureType DepthMap::GetMeasureType() const {
292   return params_.measure_type;
293 }
294 
GetSoftware() const295 const string DepthMap::GetSoftware() const { return params_.software; }
GetFocalTable() const296 const std::vector<float>& DepthMap::GetFocalTable() const {
297   return params_.focal_table;
298 }
299 
GetFocalTableEntryCount() const300 size_t DepthMap::GetFocalTableEntryCount() const {
301   return params_.focal_table.size() / 2;
302 }
303 
Serialize(Serializer * serializer) const304 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