1 // -*- c-basic-offset: 4 -*-
2
3 /** @file HFOVDialog.cpp
4 *
5 * @brief implementation of HFOVDialog Class
6 *
7 * @author Pablo d'Angelo <pablo.dangelo@web.de>
8 *
9 * $Id$
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this software. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 */
26
27
28 #include "hugin_config.h"
29 #include "panoinc_WX.h"
30 #include "panoinc.h"
31
32 #include "wxPlatform.h"
33 #include "platform.h"
34 #include "LensTools.h"
35 #include "HFOVDialog.h"
36
BEGIN_EVENT_TABLE(HFOVDialog,wxDialog)37 BEGIN_EVENT_TABLE(HFOVDialog, wxDialog)
38 EVT_CHOICE (XRCID("lensdlg_type_choice"),HFOVDialog::OnTypeChanged)
39 EVT_TEXT ( XRCID("lensdlg_cropfactor_text"), HFOVDialog::OnCropFactorChanged )
40 EVT_TEXT ( XRCID("lensdlg_hfov_text"), HFOVDialog::OnHFOVChanged )
41 EVT_TEXT ( XRCID("lensdlg_focallength_text"), HFOVDialog::OnFocalLengthChanged )
42 EVT_BUTTON( XRCID("lensdlg_load_lens_button"), HFOVDialog::OnLoadLensParameters )
43 EVT_BUTTON ( wxID_OK, HFOVDialog::OnOk)
44 END_EVENT_TABLE()
45
46 HFOVDialog::HFOVDialog(wxWindow * parent, HuginBase::SrcPanoImage & srcImg)
47 : m_srcImg(srcImg)
48 {
49 m_HFOV = srcImg.getHFOV();
50 m_focalLength = srcImg.getExifFocalLength();
51 m_cropFactor = srcImg.getCropFactor();
52 wxXmlResource::Get()->LoadDialog(this, parent, wxT("dlg_focallength"));
53
54 m_cropText = XRCCTRL(*this, "lensdlg_cropfactor_text", wxTextCtrl);
55 DEBUG_ASSERT(m_cropText);
56
57 m_hfovText = XRCCTRL(*this, "lensdlg_hfov_text", wxTextCtrl);
58 DEBUG_ASSERT(m_hfovText);
59
60 m_focalLengthText = XRCCTRL(*this, "lensdlg_focallength_text", wxTextCtrl);
61 DEBUG_ASSERT(m_focalLengthText);
62
63 m_projChoice = XRCCTRL(*this, "lensdlg_type_choice", wxChoice);
64 DEBUG_ASSERT(m_projChoice);
65 FillLensProjectionList(m_projChoice);
66
67 m_okButton = XRCCTRL(*this, "wxID_OK", wxButton);
68 DEBUG_ASSERT(m_okButton);
69
70 // fill fields
71 wxString fn(srcImg.getFilename().c_str(), HUGIN_CONV_FILENAME);
72 wxString message;
73 message.Printf(_("No or only partial information about field of view was found in image file\n%s\n\nPlease enter the horizontal field of view (HFOV) or the focal length and crop factor."), fn.c_str());
74 XRCCTRL(*this, "lensdlg_message", wxStaticText)->SetLabel(message);
75 SelectListValue(m_projChoice, m_srcImg.getProjection());
76
77 if (m_cropFactor > 0 && m_focalLength > 0) {
78 // everything is well known.. compute HFOV
79 m_HFOV = HuginBase::SrcPanoImage::calcHFOV(m_srcImg.getProjection(), m_focalLength,
80 m_cropFactor, m_srcImg.getSize());
81
82 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
83 m_hfovText->SetValue(m_HFOVStr);
84 m_focalLengthStr = hugin_utils::doubleTowxString(m_focalLength,2);
85 m_focalLengthText->SetValue(m_focalLengthStr);
86 m_cropFactorStr = hugin_utils::doubleTowxString(m_cropFactor,2);
87 m_cropText->SetValue(m_cropFactorStr);
88 } else if (m_cropFactor > 0 && m_focalLength <= 0) {
89 // focal length unknown
90 m_cropFactorStr = hugin_utils::doubleTowxString(m_cropFactor,2);
91 m_cropText->SetValue(m_cropFactorStr);
92 m_okButton->Disable();
93 } else if (m_cropFactor <= 0 && m_focalLength > 0) {
94 // crop factor unknown
95 m_focalLengthStr = hugin_utils::doubleTowxString(m_focalLength,2);
96 m_focalLengthText->SetValue(m_focalLengthStr);
97 m_okButton->Disable();
98 } else {
99 // everything unknown
100 // assume a crop factor of one
101 m_cropFactor = 1;
102 m_cropFactorStr = hugin_utils::doubleTowxString(m_cropFactor,2);
103 m_cropText->SetValue(m_cropFactorStr);
104 m_okButton->Disable();
105 }
106 // set a proper size for this dialog
107 this->GetSizer()->SetSizeHints(this);
108 }
109
OnTypeChanged(wxCommandEvent & e)110 void HFOVDialog::OnTypeChanged(wxCommandEvent & e)
111 {
112 HuginBase::SrcPanoImage::Projection new_proj = (HuginBase::SrcPanoImage::Projection)(GetSelectedValue(m_projChoice));
113 DEBUG_DEBUG("new type: " << new_proj);
114 m_srcImg.setProjection(new_proj);
115 if (m_cropFactor > 0 && m_focalLength > 0) {
116 m_HFOV = HuginBase::SrcPanoImage::calcHFOV(m_srcImg.getProjection(), m_focalLength,
117 m_cropFactor, m_srcImg.getSize());
118 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
119 m_hfovText->SetValue(m_HFOVStr);
120 }
121 }
122
OnHFOVChanged(wxCommandEvent & e)123 void HFOVDialog::OnHFOVChanged(wxCommandEvent & e)
124 {
125 wxString text = m_hfovText->GetValue();
126 DEBUG_DEBUG("state: " << m_HFOVStr.mb_str(wxConvLocal) << ", change:" << text.mb_str(wxConvLocal));
127 DEBUG_DEBUG("cmd str: " << e.GetString().mb_str(wxConvLocal));
128 if (text.empty()) {
129 // ignore all empty hfov changes
130 return;
131 }
132 // ignore changes caused by ourself
133 if (m_hfovText->GetValue() == m_HFOVStr) {
134 DEBUG_DEBUG("ignoring programatic HFOV change");
135 return;
136 }
137
138 // accept change
139 m_HFOVStr = text;
140
141 if (text.empty()) {
142 m_HFOV = 0;
143 m_okButton->Disable();
144 return;
145 }
146
147 if (!hugin_utils::str2double(text, m_HFOV)) {
148 m_okButton->Disable();
149 return;
150 }
151
152 DEBUG_DEBUG(m_HFOV);
153
154 if (m_HFOV <= 0) {
155 wxMessageBox(_("The horizontal field of view must be positive."));
156 m_HFOV = 50;
157 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
158 m_hfovText->SetValue(m_HFOVStr);
159 return;
160 }
161
162 if (m_srcImg.getProjection() == HuginBase::SrcPanoImage::RECTILINEAR && m_HFOV > 179) {
163 DEBUG_DEBUG("HFOV " << m_HFOV << " too big, resetting to 179");
164 m_HFOV=179;
165 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
166 m_hfovText->SetValue(m_HFOVStr);
167 }
168
169 if (m_cropFactor > 0) {
170 // set focal length only if crop factor is known
171 m_focalLength = HuginBase::SrcPanoImage::calcFocalLength(m_srcImg.getProjection(), m_HFOV, m_cropFactor, m_srcImg.getSize());
172 m_focalLengthStr = hugin_utils::doubleTowxString(m_focalLength,2);
173 m_focalLengthText->SetValue(m_focalLengthStr);
174 }
175 m_okButton->Enable();
176 }
177
OnFocalLengthChanged(wxCommandEvent & e)178 void HFOVDialog::OnFocalLengthChanged(wxCommandEvent & e)
179 {
180 wxString text = m_focalLengthText->GetValue();
181 DEBUG_DEBUG(m_focalLengthStr.mb_str(wxConvLocal) << " => " << text.mb_str(wxConvLocal));
182 // ignore changes caused by ourself
183 if (m_focalLengthText->GetValue() == m_focalLengthStr) {
184 DEBUG_DEBUG("ignore focal length change");
185 return;
186 }
187 // accept change
188 m_focalLengthStr = text;
189
190 if (text.empty()) {
191 m_focalLength = 0;
192 return;
193 }
194 if (!hugin_utils::str2double(text, m_focalLength)) {
195 return;
196 }
197 DEBUG_DEBUG(m_focalLength);
198
199 // ignore leading zeros..
200 if (m_focalLength == 0) {
201 return;
202 }
203 if (m_focalLength <= 0) {
204 m_focalLength=1;
205 m_focalLengthStr = hugin_utils::doubleTowxString(m_focalLength,2);
206 m_focalLengthText->SetValue(m_focalLengthStr);
207 wxMessageBox(_("The focal length must be positive."));
208 }
209
210 if (m_cropFactor > 0) {
211 // calculate HFOV.
212 m_HFOV = HuginBase::SrcPanoImage::calcHFOV(m_srcImg.getProjection(), m_focalLength,
213 m_cropFactor, m_srcImg.getSize());
214 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
215 m_hfovText->SetValue(m_HFOVStr);
216 m_okButton->Enable();
217 }
218 }
219
OnCropFactorChanged(wxCommandEvent & e)220 void HFOVDialog::OnCropFactorChanged(wxCommandEvent & e)
221 {
222 // ignore changesd cause by ourself
223 wxString text = m_cropText->GetValue();
224 DEBUG_DEBUG(m_cropFactorStr.mb_str(wxConvLocal) << " => " << text.mb_str(wxConvLocal));
225 if (text == m_cropFactorStr) {
226 DEBUG_DEBUG("ignore crop change");
227 return;
228 }
229 // accept change
230 m_cropFactorStr = text;
231
232 if (text.empty()) {
233 m_cropFactor = 0;
234 return;
235 }
236 if (!hugin_utils::str2double(text, m_cropFactor)) {
237 return;
238 }
239
240 // ignore leading zeros..
241 if (m_cropFactor == 0) {
242 m_cropFactorStr = text;
243 return;
244 }
245
246 if (m_cropFactor <= 0) {
247 wxMessageBox(_("The crop factor must be positive."));
248 m_cropFactor=1;
249 m_cropFactorStr = hugin_utils::doubleTowxString(m_cropFactor,2);
250 m_cropText->SetValue(m_cropFactorStr);
251 return;
252 }
253
254 if (m_focalLength > 0) {
255 m_HFOV = HuginBase::SrcPanoImage::calcHFOV(m_srcImg.getProjection(), m_focalLength,
256 m_cropFactor, m_srcImg.getSize());
257 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
258 m_hfovText->SetValue(m_HFOVStr);
259 m_okButton->Enable();
260 }
261 }
262
OnLoadLensParameters(wxCommandEvent & e)263 void HFOVDialog::OnLoadLensParameters(wxCommandEvent & e)
264 {
265 HuginBase::Lens lens;
266 lens.setImageSize(m_srcImg.getSize());
267
268 bool cropped=false;
269 bool autoCenterCrop=false;
270 vigra::Rect2D cropRect;
271
272 if (LoadLensParametersChoose(this, lens, cropped, autoCenterCrop, cropRect)) {
273 m_HFOV = lens.getHFOV();
274 m_cropFactor = lens.getCropFactor();
275
276 m_srcImg.setCropFactor(lens.getCropFactor());
277 m_srcImg.setHFOV(const_map_get(lens.variables,"v").getValue());
278 m_srcImg.setProjection((HuginBase::SrcPanoImage::Projection) lens.getProjection());
279
280 m_focalLength = HuginBase::SrcPanoImage::calcFocalLength(m_srcImg.getProjection(), m_HFOV, m_cropFactor, m_srcImg.getSize());
281
282 // geometrical distortion correction
283 std::vector<double> radialDist(4);
284 radialDist[0] = const_map_get(lens.variables,"a").getValue();
285 radialDist[1] = const_map_get(lens.variables,"b").getValue();
286 radialDist[2] = const_map_get(lens.variables,"c").getValue();
287 radialDist[3] = 1 - radialDist[0] - radialDist[1] - radialDist[2];
288 m_srcImg.setRadialDistortion(radialDist);
289 hugin_utils::FDiff2D t;
290 t.x = const_map_get(lens.variables,"d").getValue();
291 t.y = const_map_get(lens.variables,"e").getValue();
292 m_srcImg.setRadialDistortionCenterShift(t);
293 t.x = const_map_get(lens.variables,"g").getValue();
294 t.y = const_map_get(lens.variables,"t").getValue();
295 m_srcImg.setShear(t);
296
297 // vignetting
298 std::vector<double> vigCorrCoeff(4);
299 vigCorrCoeff[0] = const_map_get(lens.variables,"Va").getValue();
300 vigCorrCoeff[1] = const_map_get(lens.variables,"Vb").getValue();
301 vigCorrCoeff[2] = const_map_get(lens.variables,"Vc").getValue();
302 vigCorrCoeff[3] = const_map_get(lens.variables,"Vd").getValue();
303 m_srcImg.setRadialVigCorrCoeff(vigCorrCoeff);
304 t.x = const_map_get(lens.variables,"Vx").getValue();
305 t.y = const_map_get(lens.variables,"Vy").getValue();
306 m_srcImg.setRadialVigCorrCenterShift(t);
307
308 std::vector<float> resp(5);
309 resp[0] = const_map_get(lens.variables,"Ra").getValue();
310 resp[1] = const_map_get(lens.variables,"Rb").getValue();
311 resp[2] = const_map_get(lens.variables,"Rc").getValue();
312 resp[3] = const_map_get(lens.variables,"Rd").getValue();
313 resp[4] = const_map_get(lens.variables,"Re").getValue();
314 m_srcImg.setEMoRParams(resp);
315
316 if (!cropped)
317 {
318 m_srcImg.setCropMode(HuginBase::SrcPanoImage::NO_CROP);
319 }
320 else
321 {
322 if (m_srcImg.isCircularCrop())
323 {
324 m_srcImg.setCropMode(HuginBase::SrcPanoImage::CROP_CIRCLE);
325 }
326 else
327 {
328 m_srcImg.setCropMode(HuginBase::SrcPanoImage::CROP_RECTANGLE);
329 };
330 m_srcImg.setCropRect(cropRect);
331 };
332
333 // display in GUI
334 m_focalLengthStr = hugin_utils::doubleTowxString(m_focalLength,2);
335 m_focalLengthText->SetValue(m_focalLengthStr);
336 m_cropFactorStr = hugin_utils::doubleTowxString(m_cropFactor,2);
337 m_cropText->SetValue(m_cropFactorStr);
338 m_HFOVStr = hugin_utils::doubleTowxString(m_HFOV,2);
339 m_hfovText->SetValue(m_HFOVStr);
340 SelectListValue(m_projChoice, m_srcImg.getProjection());
341
342 // update lens type
343 m_okButton->Enable();
344 }
345 }
346
347
GetSrcImage()348 HuginBase::SrcPanoImage HFOVDialog::GetSrcImage()
349 {
350 m_srcImg.setCropFactor(m_cropFactor);
351 m_srcImg.setHFOV(m_HFOV);
352 return m_srcImg;
353 }
354
GetCropFactor()355 double HFOVDialog::GetCropFactor()
356 {
357 return m_cropFactor;
358 }
359
GetFocalLength()360 double HFOVDialog::GetFocalLength()
361 {
362 return m_focalLength;
363 }
364
OnOk(wxCommandEvent & e)365 void HFOVDialog::OnOk(wxCommandEvent & e)
366 {
367 if (m_srcImg.getProjection() == HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC && m_HFOV>190)
368 {
369 if(wxMessageBox(
370 wxString::Format(_("You have given a field of view of %.2f degrees.\n But the orthographic projection is limited to a field of view of 180 degress.\nDo you want still use that high value?"), m_HFOV),
371 #ifdef __WXMSW__
372 _("Hugin"),
373 #else
374 wxT(""),
375 #endif
376 wxICON_EXCLAMATION | wxYES_NO)==wxNO)
377 {
378 return;
379 };
380 };
381 EndModal(wxID_OK);
382 };