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