#include "dynamic_depth/depth_map.h"
|
|
#include "android-base/logging.h"
|
#include "dynamic_depth/const.h"
|
#include "dynamic_depth/item.h"
|
#include "strings/numbers.h"
|
#include "xmpmeta/base64.h"
|
|
using ::dynamic_depth::Item;
|
using ::dynamic_depth::xmpmeta::EncodeFloatArrayBase64;
|
using ::dynamic_depth::xmpmeta::xml::Deserializer;
|
using ::dynamic_depth::xmpmeta::xml::Serializer;
|
|
namespace dynamic_depth {
|
namespace {
|
constexpr const char* kNamespaceHref =
|
"http://ns.google.com/photos/dd/1.0/depthmap/";
|
|
constexpr const char* kFormat = "Format";
|
constexpr const char* kNear = "Near";
|
constexpr const char* kFar = "Far";
|
constexpr const char* kUnits = "Units";
|
constexpr const char* kDepthUri = "DepthURI";
|
constexpr const char* kItemSemantic = "ItemSemantic";
|
constexpr const char* kConfidenceUri = "ConfidenceURI";
|
constexpr const char* kMeasureType = "MeasureType";
|
constexpr const char* kSoftware = "Software";
|
constexpr const char* kFocalTable = "FocalTable";
|
constexpr const char* kFocalTableEntryCount = "FocalTableEntryCount";
|
|
constexpr const char* kFormatRangeInverse = "RangeInverse";
|
constexpr const char* kFormatRangeLinear = "RangeLinear";
|
constexpr const char* kFormatRangeInverseLower = "rangeinverse";
|
constexpr const char* kFormatRangeLinearLower = "rangelinear";
|
|
constexpr const char* kUnitsMeters = "Meters";
|
constexpr const char* kUnitsDiopters = "Diopters";
|
constexpr const char* kUnitsNone = "None";
|
constexpr const char* kUnitsMetersLower = "meters";
|
constexpr const char* kUnitsDioptersLower = "diopters";
|
|
constexpr const char* kMeasureTypeOpticalAxis = "OpticalAxis";
|
constexpr const char* kMeasureTypeOpticRay = "OpticRay";
|
constexpr const char* kMeasureTypeOpticRayLower = "opticray";
|
|
constexpr const char* kItemSemanticDepth = "Depth";
|
constexpr const char* kItemSemanticSegmentation = "Segmentation";
|
constexpr const char* kItemSemanticSegmentationLower = "segmentation";
|
|
string ItemSemanticToString(DepthItemSemantic item_semantic) {
|
switch (item_semantic) {
|
case DepthItemSemantic::kDepth:
|
return kItemSemanticDepth;
|
case DepthItemSemantic::kSegmentation:
|
return kItemSemanticSegmentation;
|
}
|
}
|
|
DepthItemSemantic StringToItemSemantic(const string& semantic_str) {
|
string semantic_str_lower = semantic_str;
|
std::transform(semantic_str_lower.begin(), semantic_str_lower.end(),
|
semantic_str_lower.begin(), ::tolower);
|
if (kItemSemanticSegmentationLower == semantic_str_lower) {
|
return DepthItemSemantic::kSegmentation;
|
}
|
|
return DepthItemSemantic::kDepth;
|
}
|
|
string FormatToString(DepthFormat format) {
|
switch (format) {
|
case DepthFormat::kRangeInverse:
|
return kFormatRangeInverse;
|
case DepthFormat::kRangeLinear:
|
return kFormatRangeLinear;
|
case DepthFormat::kFormatNone:
|
return "";
|
}
|
}
|
|
// Case insensitive.
|
DepthFormat StringToFormat(const string& format_str) {
|
string format_str_lower = format_str;
|
std::transform(format_str_lower.begin(), format_str_lower.end(),
|
format_str_lower.begin(), ::tolower);
|
if (kFormatRangeInverseLower == format_str_lower) {
|
return DepthFormat::kRangeInverse;
|
}
|
|
if (kFormatRangeLinearLower == format_str_lower) {
|
return DepthFormat::kRangeLinear;
|
}
|
|
return DepthFormat::kFormatNone;
|
}
|
|
string UnitsToString(DepthUnits units) {
|
switch (units) {
|
case DepthUnits::kMeters:
|
return kUnitsMeters;
|
case DepthUnits::kDiopters:
|
return kUnitsDiopters;
|
case DepthUnits::kUnitsNone:
|
return kUnitsNone;
|
}
|
}
|
|
DepthUnits StringToUnits(const string& units_str) {
|
string units_str_lower = units_str;
|
std::transform(units_str_lower.begin(), units_str_lower.end(),
|
units_str_lower.begin(), ::tolower);
|
if (kUnitsMetersLower == units_str_lower) {
|
return DepthUnits::kMeters;
|
}
|
|
if (kUnitsDioptersLower == units_str_lower) {
|
return DepthUnits::kDiopters;
|
}
|
|
return DepthUnits::kUnitsNone;
|
}
|
|
string MeasureTypeToString(DepthMeasureType measure_type) {
|
switch (measure_type) {
|
case DepthMeasureType::kOpticRay:
|
return kMeasureTypeOpticRay;
|
case DepthMeasureType::kOpticalAxis:
|
return kMeasureTypeOpticalAxis;
|
}
|
}
|
|
DepthMeasureType StringToMeasureType(const string& measure_type_str) {
|
string measure_type_str_lower = measure_type_str;
|
std::transform(measure_type_str_lower.begin(), measure_type_str_lower.end(),
|
measure_type_str_lower.begin(), ::tolower);
|
if (kMeasureTypeOpticRayLower == measure_type_str_lower) {
|
return DepthMeasureType::kOpticRay;
|
}
|
|
return DepthMeasureType::kOpticalAxis;
|
}
|
|
} // namespace
|
|
// Private constructor.
|
DepthMap::DepthMap(const DepthMapParams& params) : params_(params) {}
|
|
// Private parser.
|
std::unique_ptr<DepthMap> DepthMap::ParseFields(
|
const Deserializer& deserializer) {
|
const string& prefix = DynamicDepthConst::DepthMap();
|
string format_str;
|
float near;
|
float far;
|
string units_str;
|
string depth_uri;
|
string item_semantic_str;
|
|
if (!deserializer.ParseString(prefix, kItemSemantic, &item_semantic_str) ||
|
!deserializer.ParseString(prefix, kFormat, &format_str) ||
|
!deserializer.ParseFloat(prefix, kNear, &near) ||
|
!deserializer.ParseFloat(prefix, kFar, &far) ||
|
!deserializer.ParseString(prefix, kUnits, &units_str) ||
|
!deserializer.ParseString(prefix, kDepthUri, &depth_uri)) {
|
return nullptr;
|
}
|
|
DepthMapParams params(StringToFormat(format_str), near, far,
|
StringToUnits(units_str), depth_uri);
|
params.item_semantic = StringToItemSemantic(item_semantic_str);
|
|
string confidence_uri;
|
if (deserializer.ParseString(prefix, kConfidenceUri, &confidence_uri)) {
|
params.confidence_uri = confidence_uri;
|
}
|
|
string measure_type_str;
|
if (deserializer.ParseString(prefix, kMeasureType, &measure_type_str)) {
|
params.measure_type = StringToMeasureType(measure_type_str);
|
}
|
|
string software;
|
if (deserializer.ParseString(prefix, kSoftware, &software)) {
|
params.software = software;
|
}
|
|
std::vector<float> focal_table;
|
int focal_table_entry_count;
|
if (deserializer.ParseFloatArrayBase64(prefix, kFocalTable, &focal_table) &&
|
(!deserializer.ParseInt(prefix, kFocalTableEntryCount,
|
&focal_table_entry_count) &&
|
focal_table.size() / 2 != focal_table_entry_count)) {
|
return nullptr;
|
}
|
params.focal_table = focal_table;
|
|
return std::unique_ptr<DepthMap>(new DepthMap(params)); // NOLINT
|
}
|
|
// Public methods.
|
void DepthMap::GetNamespaces(
|
std::unordered_map<string, string>* ns_name_href_map) {
|
if (ns_name_href_map == nullptr) {
|
LOG(ERROR) << "Namespace list or own namespace is null";
|
return;
|
}
|
ns_name_href_map->emplace(DynamicDepthConst::DepthMap(), kNamespaceHref);
|
}
|
|
std::unique_ptr<DepthMap> DepthMap::FromData(
|
const DepthMapParams& params, std::vector<std::unique_ptr<Item>>* items) {
|
if (params.format == DepthFormat::kFormatNone) {
|
LOG(ERROR)
|
<< "Format must be specified, cannot be of type DepthFormat::NONE";
|
return nullptr;
|
}
|
|
if (params.depth_uri.empty() || params.depth_image_data.empty()) {
|
LOG(ERROR) << "Depth image data and URI must be provided";
|
return nullptr;
|
}
|
|
if (!params.focal_table.empty() && params.focal_table.size() % 2 != 0) {
|
LOG(ERROR) << "Focal table entries must consist of pairs";
|
return nullptr;
|
}
|
|
if (items == nullptr) {
|
LOG(ERROR) << "List of items is null";
|
return nullptr;
|
}
|
|
if (params.mime.empty()) {
|
LOG(ERROR) << "Depth image mime must be provided to DepthMapParams";
|
return nullptr;
|
}
|
|
ItemParams depth_item_params(params.mime, params.depth_image_data.size(),
|
params.depth_uri);
|
depth_item_params.payload_to_serialize = params.depth_image_data;
|
items->emplace_back(Item::FromData(depth_item_params));
|
|
bool available_confidence_uri_and_data = true;
|
if (!params.confidence_uri.empty() && !params.confidence_data.empty()) {
|
// Assumes that the confidence mime is the same as that of the depth map.
|
ItemParams confidence_item_params(
|
params.mime, params.confidence_data.size(), params.confidence_uri);
|
confidence_item_params.payload_to_serialize = params.confidence_data;
|
items->emplace_back(Item::FromData(confidence_item_params));
|
} else if (!params.confidence_uri.empty() && params.confidence_data.empty()) {
|
LOG(ERROR) << "No confidence data provided, the URI will be set to empty "
|
"and not serialized";
|
available_confidence_uri_and_data = false;
|
}
|
|
auto depth_map = std::unique_ptr<DepthMap>(new DepthMap(params)); // NOLINT
|
if (!available_confidence_uri_and_data) {
|
// Ensure we don't serialize the confidence URI if no data has been
|
// provided.
|
depth_map->params_.confidence_uri = "";
|
}
|
|
return depth_map;
|
}
|
|
std::unique_ptr<DepthMap> DepthMap::FromDeserializer(
|
const Deserializer& parent_deserializer) {
|
std::unique_ptr<Deserializer> deserializer =
|
parent_deserializer.CreateDeserializer(
|
DynamicDepthConst::Namespace(DynamicDepthConst::DepthMap()),
|
DynamicDepthConst::DepthMap());
|
if (deserializer == nullptr) {
|
return nullptr;
|
}
|
|
return ParseFields(*deserializer);
|
}
|
|
DepthFormat DepthMap::GetFormat() const { return params_.format; }
|
float DepthMap::GetNear() const { return params_.near; }
|
float DepthMap::GetFar() const { return params_.far; }
|
DepthUnits DepthMap::GetUnits() const { return params_.units; }
|
const string DepthMap::GetDepthUri() const { return params_.depth_uri; }
|
DepthItemSemantic DepthMap::GetItemSemantic() const {
|
return params_.item_semantic;
|
}
|
const string DepthMap::GetConfidenceUri() const {
|
return params_.confidence_uri;
|
}
|
|
DepthMeasureType DepthMap::GetMeasureType() const {
|
return params_.measure_type;
|
}
|
|
const string DepthMap::GetSoftware() const { return params_.software; }
|
const std::vector<float>& DepthMap::GetFocalTable() const {
|
return params_.focal_table;
|
}
|
|
size_t DepthMap::GetFocalTableEntryCount() const {
|
return params_.focal_table.size() / 2;
|
}
|
|
bool DepthMap::Serialize(Serializer* serializer) const {
|
if (serializer == nullptr) {
|
LOG(ERROR) << "Serializer is null";
|
return false;
|
}
|
if (params_.depth_uri.empty()) {
|
LOG(ERROR) << "Depth image URI is empty";
|
return false;
|
}
|
|
const string& prefix = DynamicDepthConst::DepthMap();
|
// Error checking is already done in FromData.
|
if (!serializer->WriteProperty(prefix, kItemSemantic,
|
ItemSemanticToString(params_.item_semantic)) ||
|
!serializer->WriteProperty(prefix, kFormat,
|
FormatToString(params_.format)) ||
|
!serializer->WriteProperty(prefix, kUnits,
|
UnitsToString(params_.units)) ||
|
!serializer->WriteProperty(prefix, kNear, std::to_string(params_.near)) ||
|
!serializer->WriteProperty(prefix, kFar, std::to_string(params_.far)) ||
|
!serializer->WriteProperty(prefix, kDepthUri, params_.depth_uri)) {
|
return false;
|
}
|
|
serializer->WriteProperty(prefix, kMeasureType,
|
MeasureTypeToString(params_.measure_type));
|
|
if (!params_.confidence_uri.empty()) {
|
serializer->WriteProperty(prefix, kConfidenceUri, params_.confidence_uri);
|
}
|
|
if (!params_.software.empty()) {
|
serializer->WriteProperty(prefix, kSoftware, params_.software);
|
}
|
|
if (!params_.focal_table.empty()) {
|
string base64_encoded_focal_table;
|
if (!EncodeFloatArrayBase64(params_.focal_table,
|
&base64_encoded_focal_table)) {
|
LOG(ERROR) << "Focal table encoding failed";
|
} else {
|
int focal_table_entry_count =
|
static_cast<int>(params_.focal_table.size() / 2);
|
if (!serializer->WriteProperty(
|
prefix, kFocalTableEntryCount,
|
::dynamic_depth::strings::SimpleItoa(focal_table_entry_count)) ||
|
!serializer->WriteProperty(prefix, kFocalTable,
|
base64_encoded_focal_table)) {
|
LOG(ERROR) << "Focal table or entry count could not be serialized";
|
}
|
}
|
}
|
|
return true;
|
}
|
|
} // namespace dynamic_depth
|