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 };