Home | History | Annotate | Download | only in dynamic_depth
      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