blob: b8a912bda370952a4727461d0e6c7fbef92afc23 [file] [log] [blame]
#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