1 // -*- c-basic-offset: 4 -*-
2
3 /** @file PanoOutputDialog.cpp
4 *
5 * @brief implementation of PanoOutputDialog class
6 *
7 * @author T. Modes
8 *
9 */
10
11 /* This 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 * Lesser 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 #include "hugin/PanoOutputDialog.h"
28 #include "base_wx/wxPlatform.h"
29 #include "panoinc.h"
30
31 #include "hugin/huginApp.h"
32 #include "base_wx/platform.h"
33 #include "hugin/config_defaults.h"
34 #include "algorithms/basic/LayerStacks.h"
35 #include "algorithms/basic/CalculateOptimalScale.h"
36
BEGIN_EVENT_TABLE(PanoOutputDialog,wxDialog)37 BEGIN_EVENT_TABLE(PanoOutputDialog,wxDialog)
38 EVT_BUTTON(wxID_OK, PanoOutputDialog::OnOk)
39 EVT_CHECKBOX(XRCID("output_normal"), PanoOutputDialog::OnOutputChanged)
40 EVT_CHECKBOX(XRCID("output_fused_blended"), PanoOutputDialog::OnOutputChanged)
41 EVT_CHECKBOX(XRCID("output_blended_fused"), PanoOutputDialog::OnOutputChanged)
42 EVT_CHECKBOX(XRCID("output_hdr"), PanoOutputDialog::OnOutputChanged)
43 EVT_CHOICE(XRCID("output_ldr_format"), PanoOutputDialog::OnLDRFormatChanged)
44 EVT_CHOICE(XRCID("output_hdr_format"), PanoOutputDialog::OnHDRFormatChanged)
45 EVT_SPINCTRL(XRCID("output_width"), PanoOutputDialog::OnWidthChanged)
46 EVT_SPINCTRL(XRCID("output_height"), PanoOutputDialog::OnHeightChanged)
47 END_EVENT_TABLE()
48
49 PanoOutputDialog::PanoOutputDialog(wxWindow *parent, HuginBase::Panorama& pano, GuiLevel guiLevel) : m_pano(pano), m_aspect(0)
50 {
51 // load our children. some children might need special
52 // initialization. this will be done later.
53 wxXmlResource::Get()->LoadDialog(this, parent, wxT("pano_output_dialog"));
54
55 #ifdef __WXMSW__
56 wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
57 #else
58 wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
59 #endif
60 SetIcon(myIcon);
61 //set parameters
62 wxConfigBase * cfg = wxConfigBase::Get();
63 //position
64 int x = cfg->Read(wxT("/PanoOutputDialog/positionX"),-1l);
65 int y = cfg->Read(wxT("/PanoOutputDialog/positionY"),-1l);
66 if ( y >= 0 && x >= 0)
67 {
68 this->Move(x, y);
69 }
70 else
71 {
72 this->Move(0, 44);
73 };
74 // get number of stacks and exposure layers
75 m_guiLevel=guiLevel;
76 HuginBase::UIntSet images=getImagesinROI(m_pano, m_pano.getActiveImages());
77 m_stacks=getHDRStacks(m_pano, images, m_pano.getOptions());
78 m_exposureLayers=getExposureLayers(m_pano, images, m_pano.getOptions());
79 // set initial width
80 m_newOpt = m_pano.getOptions();
81 wxConfigBase* config = wxConfigBase::Get();
82 if (m_newOpt.fovCalcSupported(m_newOpt.getProjection()))
83 {
84 // calc optimal size of pano, only of projection is supported
85 // otherwise use current width as start point
86 long opt_width = hugin_utils::roundi(HuginBase::CalculateOptimalScale::calcOptimalScale(m_pano) * m_newOpt.getWidth());
87 double sizeFactor = HUGIN_ASS_PANO_DOWNSIZE_FACTOR;
88 config->Read(wxT("/Assistant/panoDownsizeFactor"), &sizeFactor, HUGIN_ASS_PANO_DOWNSIZE_FACTOR);
89 m_newOpt.setWidth(hugin_utils::floori(sizeFactor*opt_width), true);
90 };
91 m_initalWidth=m_newOpt.getWidth();
92 m_initalROIWidth=m_newOpt.getROI().width();
93 m_aspect=(double)m_newOpt.getROI().height()/m_newOpt.getROI().width();
94 m_edit_width=XRCCTRL(*this, "output_width", wxSpinCtrl);
95 m_edit_height=XRCCTRL(*this, "output_height", wxSpinCtrl);
96 m_edit_width->SetValue(m_newOpt.getROI().width());
97 m_edit_height->SetValue(m_newOpt.getROI().height());
98
99 //LDR output format, as in preferences set
100 int i = config->Read(wxT("/output/jpeg_quality"),HUGIN_JPEG_QUALITY);
101 XRCCTRL(*this, "output_jpeg_quality", wxSpinCtrl)->SetValue(i);
102 i=config->Read(wxT("/output/tiff_compression"), HUGIN_TIFF_COMPRESSION);
103 XRCCTRL(*this, "output_tiff_compression", wxChoice)->SetSelection(i);
104 i=config->Read(wxT("/output/ldr_format"), HUGIN_LDR_OUTPUT_FORMAT);
105 XRCCTRL(*this, "output_ldr_format", wxChoice)->SetSelection(i);
106 //HDR output format, as in project given
107 if (m_newOpt.outputImageTypeHDR == "exr")
108 {
109 XRCCTRL(*this, "output_hdr_format", wxChoice)->SetSelection(0);
110 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->SetSelection(2);
111 }
112 else
113 {
114 XRCCTRL(*this, "output_hdr_format", wxChoice)->SetSelection(1);
115 if (m_newOpt.outputImageTypeHDRCompression == "PACKBITS")
116 {
117 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->SetSelection(1);
118 }
119 else
120 {
121 if (m_newOpt.outputImageTypeHDRCompression == "LZW")
122 {
123 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->SetSelection(2);
124 }
125 else
126 {
127 if (m_newOpt.outputImageTypeHDRCompression == "DEFLATE")
128 {
129 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->SetSelection(3);
130 }
131 else
132 {
133 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->SetSelection(0);
134 };
135 };
136 };
137 };
138 EnableOutputOptions();
139 wxCommandEvent dummy;
140 OnOutputChanged(dummy);
141 OnLDRFormatChanged(dummy);
142 OnHDRFormatChanged(dummy);
143 };
144
~PanoOutputDialog()145 PanoOutputDialog::~PanoOutputDialog()
146 {
147 wxConfigBase * cfg = wxConfigBase::Get();
148 wxPoint ps = this->GetPosition();
149 cfg->Write(wxT("/PanoOutputDialog/positionX"), ps.x);
150 cfg->Write(wxT("/PanoOutputDialog/positionY"), ps.y);
151 cfg->Flush();
152 };
153
EnableOutputOptions()154 void PanoOutputDialog::EnableOutputOptions()
155 {
156 // check, if hdr images
157 wxFileName file1(wxString(m_pano.getImage(0).getFilename().c_str(), HUGIN_CONV_FILENAME));
158 wxString ext1=file1.GetExt().Lower();
159 if(ext1 == wxT(".hdr") || ext1 == wxT(".exr") || ext1==wxT("hdr") || ext1==wxT("exr"))
160 {
161 XRCCTRL(*this, "output_normal", wxCheckBox)->SetValue(true);
162 XRCCTRL(*this, "output_normal", wxCheckBox)->Enable(true);
163 XRCCTRL(*this, "output_normal_bitmap", wxStaticBitmap)->Enable(true);
164 return;
165 }
166 //hide hdr controls for simple interface
167 if(m_guiLevel==GUI_SIMPLE)
168 {
169 XRCCTRL(*this, "output_hdr", wxCheckBox)->Hide();
170 XRCCTRL(*this, "output_hdr_bitmap", wxStaticBitmap)->Hide();
171 XRCCTRL(*this, "output_hdr_format_label", wxStaticText)->Hide();
172 XRCCTRL(*this, "output_hdr_format", wxChoice)->Hide();
173 XRCCTRL(*this, "output_hdr_compression_label", wxStaticText)->Hide();
174 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->Hide();
175 Layout();
176 GetSizer()->Fit(this);
177 };
178 //single image or normal panorama, enable only normal output
179 if(m_pano.getNrOfImages()==1 || m_stacks.size() >= 0.7 * m_pano.getNrOfImages())
180 {
181 XRCCTRL(*this, "output_normal", wxCheckBox)->SetValue(true);
182 XRCCTRL(*this, "output_normal", wxCheckBox)->Enable(true);
183 XRCCTRL(*this, "output_normal_bitmap", wxStaticBitmap)->Enable(true);
184 if(m_pano.getNrOfImages()==1 || m_stacks.size()==m_pano.getNrOfImages())
185 {
186 return;
187 };
188 };
189 XRCCTRL(*this, "output_fused_blended", wxCheckBox)->Enable(true);
190 XRCCTRL(*this, "output_fused_blended_bitmap", wxStaticBitmap)->Enable(true);
191 XRCCTRL(*this, "output_blended_fused", wxCheckBox)->Enable(true);
192 XRCCTRL(*this, "output_blended_fused_bitmap", wxStaticBitmap)->Enable(true);
193 if(m_guiLevel!=GUI_SIMPLE)
194 {
195 XRCCTRL(*this, "output_hdr", wxCheckBox)->Enable(true);
196 XRCCTRL(*this, "output_hdr_bitmap", wxStaticBitmap)->Enable(true);
197 };
198 if(m_pano.getNrOfImages() % m_stacks.size() == 0)
199 {
200 XRCCTRL(*this, "output_fused_blended", wxCheckBox)->SetValue(true);
201 }
202 else
203 {
204 if(m_exposureLayers.size()==1)
205 {
206 XRCCTRL(*this, "output_normal", wxCheckBox)->SetValue(true);
207 XRCCTRL(*this, "output_normal", wxCheckBox)->Enable(true);
208 XRCCTRL(*this, "output_normal_bitmap", wxStaticBitmap)->Enable(true);
209 }
210 else
211 {
212 XRCCTRL(*this, "output_blended_fused", wxCheckBox)->SetValue(true);
213 };
214 };
215 };
216
OnOk(wxCommandEvent & e)217 void PanoOutputDialog::OnOk(wxCommandEvent & e)
218 {
219 bool output_normal=XRCCTRL(*this, "output_normal", wxCheckBox)->GetValue();
220 bool output_fused_blended=XRCCTRL(*this, "output_fused_blended", wxCheckBox)->GetValue();
221 bool output_blended_fused=XRCCTRL(*this, "output_blended_fused", wxCheckBox)->GetValue();
222 bool output_hdr=XRCCTRL(*this, "output_hdr", wxCheckBox)->GetValue();
223 bool keep_intermediate=XRCCTRL(*this, "output_keep_intermediate", wxCheckBox)->GetValue();
224 //normal output
225 m_newOpt.outputLDRBlended=output_normal;
226 m_newOpt.outputLDRLayers=output_normal && keep_intermediate;
227 //fused stacks, then blended
228 m_newOpt.outputLDRExposureBlended=output_fused_blended;
229 m_newOpt.outputLDRExposureRemapped=(output_fused_blended || output_blended_fused) && keep_intermediate;
230 m_newOpt.outputLDRStacks=output_fused_blended && keep_intermediate;
231 // blended exposure layers, then fused
232 m_newOpt.outputLDRExposureLayersFused=output_blended_fused;
233 m_newOpt.outputLDRExposureLayers=output_blended_fused && keep_intermediate;
234 // HDR output
235 m_newOpt.outputHDRBlended=output_hdr;
236 m_newOpt.outputHDRLayers=output_hdr && keep_intermediate;
237 m_newOpt.outputHDRStacks=output_hdr && keep_intermediate;
238 // read compression
239 if(output_normal || output_fused_blended || output_blended_fused)
240 {
241 if(m_newOpt.outputImageType=="jpg")
242 {
243 m_newOpt.quality=XRCCTRL(*this, "output_jpeg_quality", wxSpinCtrl)->GetValue();
244 }
245 else
246 {
247 if(m_newOpt.outputImageType=="tif")
248 {
249 switch(XRCCTRL(*this, "output_tiff_compression", wxChoice)->GetSelection())
250 {
251 case 0:
252 default:
253 m_newOpt.outputImageTypeCompression = "NONE";
254 m_newOpt.tiffCompression = "NONE";
255 break;
256 case 1:
257 m_newOpt.outputImageTypeCompression = "PACKBITS";
258 m_newOpt.tiffCompression = "PACKBITS";
259 break;
260 case 2:
261 m_newOpt.outputImageTypeCompression = "LZW";
262 m_newOpt.tiffCompression = "LZW";
263 break;
264 case 3:
265 m_newOpt.outputImageTypeCompression = "DEFLATE";
266 m_newOpt.tiffCompression = "DEFLATE";
267 break;
268 };
269 };
270 };
271 };
272 //HDR compression
273 if(output_hdr)
274 {
275 if(m_newOpt.outputImageTypeHDR=="tif")
276 {
277 switch(XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->GetSelection())
278 {
279 case 0:
280 default:
281 m_newOpt.outputImageTypeHDRCompression = "NONE";
282 break;
283 case 1:
284 m_newOpt.outputImageTypeHDRCompression = "PACKBITS";
285 break;
286 case 2:
287 m_newOpt.outputImageTypeHDRCompression = "LZW";
288 break;
289 case 3:
290 m_newOpt.outputImageTypeHDRCompression = "DEFLATE";
291 break;
292 };
293 };
294 }
295 // canvas size
296 double scale=m_edit_width->GetValue()/m_initalROIWidth;
297 m_newOpt.setWidth(hugin_utils::roundi(m_initalWidth*scale), true);
298 //some checks to prevent some rounding errors, only for cropped outputs
299 if(m_initalROIWidth < m_initalWidth)
300 {
301 if(m_newOpt.getROI().width()<m_edit_width->GetValue() || m_newOpt.getROI().height()<m_edit_height->GetValue())
302 {
303 m_newOpt.setWidth(m_newOpt.getWidth()+1, true);
304 };
305 vigra::Rect2D roi=m_newOpt.getROI();
306 if(roi.width()>m_edit_width->GetValue() || roi.height()>m_edit_height->GetValue())
307 {
308 roi.setSize(m_edit_width->GetValue(), m_edit_height->GetValue());
309 m_newOpt.setROI(roi);
310 };
311 };
312 //send Ok
313 EndModal(wxID_OK);
314 };
315
OnOutputChanged(wxCommandEvent & e)316 void PanoOutputDialog::OnOutputChanged(wxCommandEvent & e)
317 {
318 bool output_normal=XRCCTRL(*this, "output_normal", wxCheckBox)->GetValue();
319 bool output_fused_blended=XRCCTRL(*this, "output_fused_blended", wxCheckBox)->GetValue();
320 bool output_blended_fused=XRCCTRL(*this, "output_blended_fused", wxCheckBox)->GetValue();
321 bool output_hdr=XRCCTRL(*this, "output_hdr", wxCheckBox)->GetValue();
322 //enable Ok only if at least one option is enabled
323 XRCCTRL(*this, "wxID_OK", wxButton)->Enable(output_normal || output_fused_blended || output_blended_fused || output_hdr);
324 XRCCTRL(*this, "output_ldr_format_label", wxStaticText)->Enable(output_normal || output_fused_blended || output_blended_fused);
325 XRCCTRL(*this, "output_ldr_format", wxChoice)->Enable(output_normal || output_fused_blended || output_blended_fused);
326 XRCCTRL(*this, "output_ldr_compression_label", wxStaticText)->Enable(output_normal || output_fused_blended || output_blended_fused);
327 XRCCTRL(*this, "output_jpeg_quality", wxSpinCtrl)->Enable(output_normal || output_fused_blended || output_blended_fused);
328 XRCCTRL(*this, "output_tiff_compression", wxChoice)->Enable(output_normal || output_fused_blended || output_blended_fused);
329 XRCCTRL(*this, "output_hdr_format_label", wxStaticText)->Enable(output_hdr);
330 XRCCTRL(*this, "output_hdr_format", wxChoice)->Enable(output_hdr);
331 XRCCTRL(*this, "output_hdr_compression_label", wxStaticText)->Enable(output_hdr);
332 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->Enable(output_hdr);
333 GetSizer()->Layout();
334 };
335
OnLDRFormatChanged(wxCommandEvent & e)336 void PanoOutputDialog::OnLDRFormatChanged(wxCommandEvent & e)
337 {
338 int sel = XRCCTRL(*this, "output_ldr_format", wxChoice)->GetSelection();
339 switch (sel)
340 {
341 case 1:
342 m_newOpt.outputImageType ="jpg";
343 XRCCTRL(*this, "output_ldr_compression_label", wxStaticText)->Show();
344 XRCCTRL(*this, "output_ldr_compression_label", wxStaticText)->SetLabel(_("Quality:"));
345 XRCCTRL(*this, "output_jpeg_quality", wxSpinCtrl)->Show();
346 XRCCTRL(*this, "output_tiff_compression", wxChoice)->Hide();
347 break;
348 case 2:
349 m_newOpt.outputImageType ="png";
350 XRCCTRL(*this, "output_ldr_compression_label", wxStaticText)->Hide();
351 XRCCTRL(*this, "output_jpeg_quality", wxSpinCtrl)->Hide();
352 XRCCTRL(*this, "output_tiff_compression", wxChoice)->Hide();
353 break;
354 default:
355 case 0:
356 m_newOpt.outputImageType ="tif";
357 XRCCTRL(*this, "output_ldr_compression_label", wxStaticText)->Show();
358 XRCCTRL(*this, "output_ldr_compression_label", wxStaticText)->SetLabel(_("Compression:"));
359 XRCCTRL(*this, "output_jpeg_quality", wxSpinCtrl)->Hide();
360 XRCCTRL(*this, "output_tiff_compression", wxChoice)->Show();
361 break;
362 };
363 GetSizer()->Layout();
364 };
365
366
OnHDRFormatChanged(wxCommandEvent & e)367 void PanoOutputDialog::OnHDRFormatChanged(wxCommandEvent & e)
368 {
369 int sel = XRCCTRL(*this, "output_hdr_format", wxChoice)->GetSelection();
370 switch (sel)
371 {
372 case 1:
373 m_newOpt.outputImageTypeHDR="tif";
374 XRCCTRL(*this, "output_hdr_compression_label", wxStaticText)->Show();
375 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->Show();
376 break;
377 case 0:
378 default:
379 m_newOpt.outputImageTypeHDR="exr";
380 XRCCTRL(*this, "output_hdr_compression_label", wxStaticText)->Hide();
381 XRCCTRL(*this, "output_hdr_tiff_compression", wxChoice)->Hide();
382 break;
383 };
384 GetSizer()->Layout();
385 };
386
OnWidthChanged(wxSpinEvent & e)387 void PanoOutputDialog::OnWidthChanged(wxSpinEvent & e)
388 {
389 if(m_aspect>0)
390 {
391 m_edit_height->SetValue(m_edit_width->GetValue()*m_aspect);
392 };
393 };
394
OnHeightChanged(wxSpinEvent & e)395 void PanoOutputDialog::OnHeightChanged(wxSpinEvent & e)
396 {
397 if(m_aspect>0)
398 {
399 m_edit_width->SetValue(m_edit_height->GetValue()/m_aspect);
400 };
401 };
402