1 #include "dynamic_depth/imaging_model.h"
2 
3 #include <math.h>
4 
5 #include "android-base/logging.h"
6 #include "dynamic_depth/const.h"
7 #include "strings/numbers.h"
8 #include "xmpmeta/base64.h"
9 
10 namespace dynamic_depth {
11 namespace {
12 
13 using ::dynamic_depth::xmpmeta::EncodeFloatArrayBase64;
14 using ::dynamic_depth::xmpmeta::xml::Deserializer;
15 using ::dynamic_depth::xmpmeta::xml::Serializer;
16 
17 constexpr char kFocalLengthX[] = "FocalLengthX";
18 constexpr char kFocalLengthY[] = "FocalLengthY";
19 constexpr char kImageWidth[] = "ImageWidth";
20 constexpr char kImageHeight[] = "ImageHeight";
21 constexpr char kPrincipalPointX[] = "PrincipalPointX";
22 constexpr char kPrincipalPointY[] = "PrincipalPointY";
23 constexpr char kSkew[] = "Skew";
24 constexpr char kPixelAspectRatio[] = "PixelAspectRatio";
25 constexpr char kDistortion[] = "Distortion";
26 constexpr char kDistortionCount[] = "DistortionCount";
27 
28 constexpr char kNamespaceHref[] =
29     "http://ns.google.com/photos/dd/1.0/imagingmodel/";
30 
ParseFields(const Deserializer & deserializer)31 std::unique_ptr<ImagingModel> ParseFields(const Deserializer& deserializer) {
32   Point<double> focal_length(0, 0);
33   Dimension image_size(0, 0);
34   Point<double> principal_point(0.5, 0.5);
35   double skew = 0;
36   double pixel_aspect_ratio = 1.0;
37   const string& prefix = DynamicDepthConst::ImagingModel();
38 
39   if (!deserializer.ParseDouble(prefix, kFocalLengthX, &focal_length.x) ||
40       !deserializer.ParseDouble(prefix, kFocalLengthY, &focal_length.y) ||
41       !deserializer.ParseInt(prefix, kImageWidth, &image_size.width) ||
42       !deserializer.ParseInt(prefix, kImageHeight, &image_size.height)) {
43     return nullptr;
44   }
45 
46   double temp1;
47   double temp2;
48   if (deserializer.ParseDouble(prefix, kPrincipalPointX, &temp1) &&
49       deserializer.ParseDouble(prefix, kPrincipalPointY, &temp2)) {
50     principal_point.x = temp1;
51     principal_point.y = temp2;
52   }
53 
54   if (deserializer.ParseDouble(prefix, kSkew, &temp1)) {
55     skew = temp1;
56   }
57 
58   if (deserializer.ParseDouble(prefix, kPixelAspectRatio, &temp1)) {
59     pixel_aspect_ratio = temp1;
60   }
61 
62   int distortion_count = 0;
63   std::vector<float> distortion;
64   if (deserializer.ParseInt(DynamicDepthConst::ImagingModel(), kDistortionCount,
65                             &distortion_count)) {
66     if (distortion_count % 2 != 0) {
67       LOG(ERROR) << "Parsed DistortionCount = " << distortion_count
68                  << " was expected to be even";
69       return nullptr;
70     }
71 
72     deserializer.ParseFloatArrayBase64(DynamicDepthConst::ImagingModel(),
73                                        kDistortion, &distortion);
74     if (distortion.size() != distortion_count * 2) {
75       LOG(ERROR) << "Parsed DistortionCount of " << distortion_count
76                  << " but should be " << distortion.size()
77                  << " when multiplied by 2";
78       return nullptr;
79     }
80   }
81 
82   ImagingModelParams params(focal_length, image_size);
83   params.principal_point = principal_point;
84   params.distortion = distortion;
85   params.skew = skew;
86   params.pixel_aspect_ratio = pixel_aspect_ratio;
87   return ImagingModel::FromData(params);
88 }
89 
90 }  // namespace
91 
92 // Private constructor.
ImagingModel(const ImagingModelParams & params)93 ImagingModel::ImagingModel(const ImagingModelParams& params)
94     : params_(params) {}
95 
96 // Public methods.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)97 void ImagingModel::GetNamespaces(
98     std::unordered_map<string, string>* ns_name_href_map) {
99   if (ns_name_href_map == nullptr) {
100     LOG(ERROR) << "Namespace list or own namespace is null";
101     return;
102   }
103 
104   ns_name_href_map->emplace(DynamicDepthConst::ImagingModel(), kNamespaceHref);
105 }
106 
FromData(const ImagingModelParams & params)107 std::unique_ptr<ImagingModel> ImagingModel::FromData(
108     const ImagingModelParams& params) {
109   if (!params.distortion.empty() && params.distortion.size() % 2 != 0) {
110     LOG(ERROR) << "Distortion must be empty or contain pairs of values, but an "
111                << " odd number (size=" << params.distortion.size()
112                << ") was found";
113     return nullptr;
114   }
115 
116   return std::unique_ptr<ImagingModel>(new ImagingModel(params));  // NOLINT
117 }
118 
FromDeserializer(const Deserializer & parent_deserializer)119 std::unique_ptr<ImagingModel> ImagingModel::FromDeserializer(
120     const Deserializer& parent_deserializer) {
121   std::unique_ptr<Deserializer> deserializer =
122       parent_deserializer.CreateDeserializer(
123           DynamicDepthConst::Namespace(DynamicDepthConst::ImagingModel()),
124           DynamicDepthConst::ImagingModel());
125   if (deserializer == nullptr) {
126     return nullptr;
127   }
128 
129   return ParseFields(*deserializer);
130 }
131 
GetFocalLength() const132 Point<double> ImagingModel::GetFocalLength() const {
133   return params_.focal_length;
134 }
135 
GetPrincipalPoint() const136 Point<double> ImagingModel::GetPrincipalPoint() const {
137   return params_.principal_point;
138 }
139 
GetImageSize() const140 Dimension ImagingModel::GetImageSize() const { return params_.image_size; }
141 
GetSkew() const142 double ImagingModel::GetSkew() const { return params_.skew; }
143 
GetPixelAspectRatio() const144 double ImagingModel::GetPixelAspectRatio() const {
145   return params_.pixel_aspect_ratio;
146 }
147 
GetDistortion() const148 const std::vector<float>& ImagingModel::GetDistortion() const {
149   return params_.distortion;
150 }
151 
GetDistortionCount() const152 int ImagingModel::GetDistortionCount() const {
153   return static_cast<int>(floor(params_.distortion.size() / 2));
154 }
155 
Serialize(Serializer * serializer) const156 bool ImagingModel::Serialize(Serializer* serializer) const {
157   if (serializer == nullptr) {
158     LOG(ERROR) << "Serializer is null";
159     return false;
160   }
161 
162   // Short-circuiting ensures unnecessary writes will not be performed.
163   if (!serializer->WriteProperty(DynamicDepthConst::ImagingModel(),
164                                  kFocalLengthX,
165                                  std::to_string(params_.focal_length.x)) ||
166       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(),
167                                  kFocalLengthY,
168                                  std::to_string(params_.focal_length.y)) ||
169       // Image dimensions.
170       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(), kImageWidth,
171                                  std::to_string(params_.image_size.width)) ||
172       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(),
173                                  kImageHeight,
174                                  std::to_string(params_.image_size.height)) ||
175       // Principal point.
176       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(),
177                                  kPrincipalPointX,
178                                  std::to_string(params_.principal_point.x)) ||
179       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(),
180                                  kPrincipalPointY,
181                                  std::to_string(params_.principal_point.y)) ||
182       // Skew, pixel aspect ratio.
183       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(), kSkew,
184                                  std::to_string(params_.skew)) ||
185       !serializer->WriteProperty(DynamicDepthConst::ImagingModel(),
186                                  kPixelAspectRatio,
187                                  std::to_string(params_.pixel_aspect_ratio))) {
188     return false;
189   }
190 
191   // Write distortion model only if needed.
192   if (params_.distortion.empty()) {
193     return true;
194   }
195 
196   // No error-checking that there are an even number of values in
197   // params_.distortion, because this is already done in the instantiator and
198   // deserializer.
199   string base64_encoded_distortion;
200   if (!EncodeFloatArrayBase64(params_.distortion, &base64_encoded_distortion)) {
201     LOG(ERROR) << "Distortion encoding failed";
202     return false;
203   }
204 
205   int distortion_count = static_cast<int>(floor(params_.distortion.size() / 2));
206   if (!serializer->WriteProperty(
207           DynamicDepthConst::ImagingModel(), kDistortionCount,
208           ::dynamic_depth::strings::SimpleItoa(distortion_count))) {
209     return false;
210   }
211 
212   if (!serializer->WriteProperty(DynamicDepthConst::ImagingModel(), kDistortion,
213                                  base64_encoded_distortion)) {
214     return false;
215   }
216 
217   return true;
218 }
219 
220 }  // namespace dynamic_depth
221