1 #include "dynamic_depth/image.h"
2 
3 #include "android-base/logging.h"
4 #include "dynamic_depth/const.h"
5 #include "dynamic_depth/item.h"
6 
7 using ::dynamic_depth::Item;
8 using ::dynamic_depth::xmpmeta::xml::Deserializer;
9 using ::dynamic_depth::xmpmeta::xml::Serializer;
10 
11 namespace dynamic_depth {
12 namespace {
13 
14 constexpr char kItemUri[] = "ItemURI";
15 constexpr char kItemSemantic[] = "ItemSemantic";
16 
17 constexpr char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/image/";
18 constexpr char kPrimaryImagePlaceholderItemUri[] = "primary_image";
19 
20 constexpr char kItemSemanticPrimary[] = "Primary";
21 constexpr char kItemSemanticOriginal[] = "Original";
22 constexpr char kItemSemanticPrimaryLower[] = "primary";
23 
ItemSemanticToString(ImageItemSemantic item_semantic)24 string ItemSemanticToString(ImageItemSemantic item_semantic) {
25   switch (item_semantic) {
26     case ImageItemSemantic::kPrimary:
27       return kItemSemanticPrimary;
28     case ImageItemSemantic::kOriginal:
29       return kItemSemanticOriginal;
30   }
31 }
32 
StringToItemSemantic(const string & item_semantic_str)33 ImageItemSemantic StringToItemSemantic(const string& item_semantic_str) {
34   string item_semantic_str_lower = item_semantic_str;
35   std::transform(item_semantic_str_lower.begin(), item_semantic_str_lower.end(),
36                  item_semantic_str_lower.begin(), ::tolower);
37   if (kItemSemanticPrimaryLower == item_semantic_str_lower) {
38     return ImageItemSemantic::kPrimary;
39   }
40 
41   // Don't fail, default to Original.
42   return ImageItemSemantic::kOriginal;
43 }
44 
45 }  // namespace
46 
47 // Private constructor.
Image()48 Image::Image() {}
49 
50 // Public methods.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)51 void Image::GetNamespaces(
52     std::unordered_map<string, string>* ns_name_href_map) {
53   if (ns_name_href_map == nullptr) {
54     LOG(ERROR) << "Namespace list or own namespace is null";
55     return;
56   }
57   ns_name_href_map->emplace(DynamicDepthConst::Image(), kNamespaceHref);
58 }
59 
FromData(const string & data,const string & mime,const string & item_uri,std::vector<std::unique_ptr<Item>> * items)60 std::unique_ptr<Image> Image::FromData(
61     const string& data, const string& mime, const string& item_uri,
62     std::vector<std::unique_ptr<Item>>* items) {
63   if (data.empty() || mime.empty()) {
64     LOG(ERROR) << "No image data or mimetype given";
65     return nullptr;
66   }
67 
68   if (item_uri.empty()) {
69     LOG(ERROR) << "Item URI must be provided";
70     return nullptr;
71   }
72 
73   if (items == nullptr) {
74     LOG(ERROR) << "List of items is null";
75     return nullptr;
76   }
77 
78   ItemParams item_params(mime, data.size(), item_uri);
79   item_params.payload_to_serialize = data;
80   items->emplace_back(Item::FromData(item_params));
81 
82   std::unique_ptr<Image> image(std::unique_ptr<Image>(new Image()));  // NOLINT
83   image->item_uri_ = item_uri;
84   image->item_semantic_ = ImageItemSemantic::kOriginal;
85   return image;
86 }
87 
FromDataForPrimaryImage(const string & mime,std::vector<std::unique_ptr<Item>> * items)88 std::unique_ptr<Image> Image::FromDataForPrimaryImage(
89     const string& mime, std::vector<std::unique_ptr<Item>>* items) {
90   if (mime.empty()) {
91     LOG(ERROR) << "No mimetype given";
92     return nullptr;
93   }
94 
95   if (items == nullptr) {
96     LOG(ERROR) << "List of items is null";
97     return nullptr;
98   }
99 
100   ItemParams item_params(mime, 0, kPrimaryImagePlaceholderItemUri);
101   items->emplace_back(Item::FromData(item_params));
102 
103   std::unique_ptr<Image> image(std::unique_ptr<Image>(new Image()));  // NOLINT
104   image->item_uri_ = kPrimaryImagePlaceholderItemUri;
105   image->item_semantic_ = ImageItemSemantic::kPrimary;
106   return image;
107 }
108 
FromData(const uint8_t * data,size_t data_size,const string & mime,const string & item_uri,std::vector<std::unique_ptr<Item>> * items)109 std::unique_ptr<Image> Image::FromData(
110     const uint8_t* data, size_t data_size, const string& mime,
111     const string& item_uri, std::vector<std::unique_ptr<Item>>* items) {
112   if ((data == nullptr || data_size == 0) || mime.empty()) {
113     LOG(ERROR) << "No image data or mimetype given";
114     return nullptr;
115   }
116 
117   if (item_uri.empty()) {
118     LOG(ERROR) << "Item URI must be provided";
119     return nullptr;
120   }
121 
122   if (items == nullptr) {
123     LOG(ERROR) << "List of items is null";
124     return nullptr;
125   }
126 
127   ItemParams item_params(mime, data_size, item_uri);
128   item_params.payload_to_serialize =
129       std::string(reinterpret_cast<const char*>(data), data_size);
130   items->emplace_back(Item::FromData(item_params));
131 
132   std::unique_ptr<Image> image(std::unique_ptr<Image>(new Image()));  // NOLINT
133   image->item_uri_ = item_uri;
134   image->item_semantic_ = ImageItemSemantic::kOriginal;
135   return image;
136 }
137 
GetItemUri() const138 const string& Image::GetItemUri() const { return item_uri_; }
GetItemSemantic() const139 ImageItemSemantic Image::GetItemSemantic() const { return item_semantic_; }
140 
FromDeserializer(const Deserializer & parent_deserializer)141 std::unique_ptr<Image> Image::FromDeserializer(
142     const Deserializer& parent_deserializer) {
143   std::unique_ptr<Deserializer> deserializer =
144       parent_deserializer.CreateDeserializer(
145           DynamicDepthConst::Namespace(DynamicDepthConst::Image()),
146           DynamicDepthConst::Image());
147   if (deserializer == nullptr) {
148     return nullptr;
149   }
150 
151   std::unique_ptr<Image> image(new Image());
152   if (!image->ParseImageFields(*deserializer)) {
153     return nullptr;
154   }
155   return image;
156 }
157 
Serialize(Serializer * serializer) const158 bool Image::Serialize(Serializer* serializer) const {
159   if (serializer == nullptr) {
160     LOG(ERROR) << "Serializer is null";
161     return false;
162   }
163 
164   if (item_uri_.empty()) {
165     LOG(ERROR) << "Item URI is empty";
166     return false;
167   }
168 
169   return serializer->WriteProperty(DynamicDepthConst::Image(), kItemSemantic,
170                                    ItemSemanticToString(item_semantic_)) &&
171          serializer->WriteProperty(DynamicDepthConst::Image(), kItemUri,
172                                    item_uri_);
173 }
174 
175 // Private methods.
ParseImageFields(const Deserializer & deserializer)176 bool Image::ParseImageFields(const Deserializer& deserializer) {
177   string item_uri;
178   string item_semantic_str;
179   if (!deserializer.ParseString(DynamicDepthConst::Image(), kItemSemantic,
180                                 &item_semantic_str) ||
181       !deserializer.ParseString(DynamicDepthConst::Image(), kItemUri,
182                                 &item_uri)) {
183     return false;
184   }
185 
186   item_uri_ = item_uri;
187   item_semantic_ = StringToItemSemantic(item_semantic_str);
188   return true;
189 }
190 
191 }  // namespace dynamic_depth
192