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