Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PreviewPanel.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include "hugin_config.h"
28 #include "panoinc_WX.h"
29 #include "panoinc.h"
30 
31 #include <vigra/basicimageview.hxx>
32 #include "nona/Stitcher.h"
33 
34 #include "base_wx/wxImageCache.h"
35 #include "base_wx/wxutils.h"
36 #include "hugin/PreviewPanel.h"
37 #include "hugin/PreviewFrame.h"
38 #include "hugin/MainFrame.h"
39 #include "base_wx/CommandHistory.h"
40 #include "base_wx/PanoCommand.h"
41 #include "base_wx/wxcms.h"
42 #include "hugin/config_defaults.h"
43 #include "hugin/huginApp.h"
44 
45 #include <math.h>
46 
47 typedef vigra::RGBValue<unsigned char> BRGBValue;
48 
50  : pano(0), m_autoPreview(false),m_panoImgSize(1,1),
51  m_panoBitmap(0),
52  m_pano2erect(0), m_blendMode(BLEND_COPY),
53  m_state_rendering(false), m_rerender(false), m_imgsDirty(true)
54 {
55 }
56 
57 bool PreviewPanel::Create(wxWindow* parent, wxWindowID id,
58  const wxPoint& pos,
59  const wxSize& size,
60  long style,
61  const wxString& name)
62 {
63  DEBUG_TRACE(" Create called *************");
64  if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
65  return false;
66  }
67  DEBUG_TRACE("");
68  DEBUG_DEBUG("m_state_rendering = " << m_state_rendering);
69 
70 #if defined(__WXMSW__)
71  wxString cursorPath = huginApp::Get()->GetXRCPath() + "/data/cursor_cp_pick.cur";
72  m_cursor = new wxCursor(cursorPath, wxBITMAP_TYPE_CUR);
73 #else
74  m_cursor = new wxCursor(wxCURSOR_CROSS);
75 #endif
76  SetCursor(*m_cursor);
77  Bind(wxEVT_SIZE, &PreviewPanel::OnResize, this);
78  Bind(wxEVT_LEFT_DOWN, &PreviewPanel::mousePressLMBEvent, this);
79  Bind(wxEVT_RIGHT_DOWN, &PreviewPanel::mousePressRMBEvent, this);
80  Bind(wxEVT_MOTION, &PreviewPanel::OnMouse, this);
81  Bind(wxEVT_PAINT, &PreviewPanel::OnPaint, this);
82 
83  return true;
84 }
85 
86 
88 {
89  pano = panorama;
90  parentWindow = parent;
91  pano->addObserver(this);
92 }
93 
94 
96 {
97  DEBUG_TRACE("dtor");
98  delete m_cursor;
99  pano->removeObserver(this);
100  if (m_panoBitmap) {
101  delete m_panoBitmap;
102  }
103  if (m_pano2erect) {
104  delete m_pano2erect;
105  }
106  DEBUG_TRACE("dtor end");
107 }
108 
110 {
111  // avoid recursive calls.. don't know if they can happen at all,
112  // but they might lead to crashes.
113  bool dirty = false;
114 
115  const HuginBase::PanoramaOptions & newOpts = pano.getOptions();
116 
117  // check if an important options has been changed
118  if (newOpts.getHFOV() != opts.getHFOV()) {
119  DEBUG_DEBUG("HFOV changed");
120  dirty = true;
121  }
122  if (newOpts.getVFOV() != opts.getVFOV()) {
123  DEBUG_DEBUG("VFOV changed");
124  dirty = true;
125  }
126  if (newOpts.getProjection() != opts.getProjection()) {
127  DEBUG_DEBUG("projection changed");
128  dirty = true;
129  }
130 
132  DEBUG_DEBUG("projection parameters changed");
133  dirty = true;
134  }
136  {
137  DEBUG_DEBUG("output exposure value changed");
138  dirty = true;
139  };
141  {
142  DEBUG_DEBUG("output range compression changed");
143  dirty = true;
144  };
145 
146  opts = newOpts;
147  if (dirty) {
148  // have to remap all images
150  }
151 
152  if (m_autoPreview && dirty) {
153  DEBUG_DEBUG("forcing preview update");
154  ForceUpdate();
155  // resize
156  } else if(m_autoPreview && m_imgsDirty ) {
157  DEBUG_DEBUG("updating preview after image change");
158  updatePreview();
159  m_imgsDirty=false;
160  }
161 }
162 
164 {
165  DEBUG_TRACE("");
166  m_imgsDirty = true;
167 }
168 
170 {
171  m_blendMode = b;
172  updatePreview();
173 }
174 
176 {
177  updatePreview();
178 }
179 
180 void PreviewPanel::SetAutoUpdate(bool enabled)
181 {
182  m_autoPreview = enabled;
183  if (enabled) {
184  updatePreview();
185  }
186 }
187 
190 template <class OP>
192 {
193  ExposureResponseFunctor2(double exposure, const OP & operation)
194  : op(operation), e(exposure)
195  {
196  }
197  const OP & op;
198  double e;
199 
200  template <class VT>
201  typename vigra::NumericTraits<VT>::RealPromote
202  operator()(VT v) const
203  {
204  return op(v*e);
205  }
206 };
207 
209 {
210 public:
211  RangeCompression(double rangeCompression)
212  {
213  m_rangeCompression = rangeCompression;
214  m_logM1 = std::log2(m_rangeCompression + 1);
215  };
216 
217  vigra::RGBValue<float> operator()(vigra::RGBValue<float> const& v) const
218  {
219  return vigra::RGBValue<float>(std::log2(m_rangeCompression * v.red() + 1) / m_logM1,
220  std::log2(m_rangeCompression * v.green() + 1) / m_logM1,
221  std::log2(m_rangeCompression * v.blue() + 1) / m_logM1
222  );
223  }
224 private:
226  double m_logM1;
227 };
228 
230 {
231  DEBUG_TRACE("");
232 
233  // we can accidentally end up here recursively, because wxWidgets
234  // allows user input during redraw of the progress in the bottom
235  if (m_state_rendering) {
236  DEBUG_DEBUG("m_state_rendering == true, aborting rendering");
237  m_rerender = true;
238  return;
239  }
240 
241  DEBUG_DEBUG("m_state_rendering = true");
242  m_state_rendering = true;
243  m_rerender = false;
244 
245  {
246  // Even though the frame is hidden, the panel is not
247  // so check the parent instead
248  if (parentWindow) {
249  if (parentWindow->IsShown() && (! parentWindow->IsIconized())) {
250  DEBUG_INFO("Parent window shown - updating");
251  } else {
252  DEBUG_INFO("Parent window hidden - not updating");
253  m_state_rendering = false;
254  return;
255  }
256  }
257  }
258  wxBusyCursor wait;
259  double finalWidth = pano->getOptions().getWidth();
260  double finalHeight = pano->getOptions().getHeight();
261 
262  m_panoImgSize = vigra::Diff2D(GetClientSize().GetWidth(), GetClientSize().GetHeight());
263 
264  double ratioPano = finalWidth / finalHeight;
265  double ratioPanel = (double)m_panoImgSize.x / (double)m_panoImgSize.y;
266 
267  DEBUG_DEBUG("panorama ratio: " << ratioPano << " panel ratio: " << ratioPanel);
268 
269  if (ratioPano < ratioPanel) {
270  // panel is wider than pano
272  DEBUG_DEBUG("portrait: " << m_panoImgSize);
273  } else {
274  // panel is taller than pano
276  DEBUG_DEBUG("landscape: " << m_panoImgSize);
277  }
278 
280  //don't use GPU for preview
281  opts.remapUsingGPU = false;
282  opts.setWidth(m_panoImgSize.x, false);
283  opts.setHeight(m_panoImgSize.y);
284  // always use bilinear for preview.
285 
286  // reset ROI. The preview needs to draw the parts outside the ROI, too!
287  opts.setROI(vigra::Rect2D(opts.getSize()));
289 
290  // create images
291  wxImage panoImage(m_panoImgSize.x, m_panoImgSize.y);
292  try {
293  vigra::BasicImageView<vigra::RGBValue<unsigned char> > panoImg8((vigra::RGBValue<unsigned char> *)panoImage.GetData(), panoImage.GetWidth(), panoImage.GetHeight());
294  vigra::FRGBImage panoImg(m_panoImgSize);
295  vigra::BImage alpha(m_panoImgSize);
296 
297  DEBUG_DEBUG("about to stitch images, pano size: " << m_panoImgSize);
298  HuginBase::UIntSet displayedImages = pano->getActiveImages();
299  if (!displayedImages.empty()) {
301  DEBUG_DEBUG("HDR output merge");
302 
305  stitcher.stitch(opts, displayedImages,
306  destImageRange(panoImg), destImage(alpha),
307  m_remapCache,
308  hdrmerge);
309 #ifdef DEBUG_REMAP
310 {
311  vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_preview_HDR_Reduce.tif"); \
312  vigra::exportImage(vigra::srcImageRange(panoImg), exi); \
313 }
314 {
315  vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_preview_HDR_Reduce_Alpha.tif"); \
316  vigra::exportImage(vigra::srcImageRange(alpha), exi); \
317 }
318 #endif
319 
320  // find min and max
321  vigra::FindAverageAndVariance<float> mean; // init functor
322  vigra::inspectImageIf(vigra::srcImageRange(panoImg, vigra::RGBToGrayAccessor<vigra::RGBValue<float>>()), vigra::srcImage(alpha), mean);
323  double min = std::max(mean.average()-3*sqrt(mean.variance()), 1e-6f);
324  double max = mean.average() + 3 * sqrt(mean.variance());
325 
326  int mapping = wxConfigBase::Get()->Read("/ImageCache/Mapping", HUGIN_IMGCACHE_MAPPING_FLOAT);
327  vigra_ext::applyMapping(vigra::srcImageRange(panoImg), vigra::destImage(panoImg8), min, max, mapping);
328 
329  } else {
330  // LDR output
331  vigra::ImageImportInfo::ICCProfile iccProfile;
332  switch (m_blendMode) {
333  case BLEND_COPY:
334  {
337  stitcher.stitch(opts, displayedImages,
338  destImageRange(panoImg), destImage(alpha),
339  m_remapCache,
340  blender);
341  iccProfile = stitcher.iccProfile;
342  break;
343  }
344  case BLEND_DIFFERENCE:
345  {
348  stitcher.stitch(opts, displayedImages,
349  destImageRange(panoImg), destImage(alpha),
350  m_remapCache,
351  func);
352  iccProfile = stitcher.iccProfile;
353  break;
354  }
355  }
356 
357 #ifdef DEBUG_REMAP
358 {
359  vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_preview_AfterRemap.tif"); \
360  vigra::exportImage(vigra::srcImageRange(panoImg), exi); \
361 }
362 {
363  vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_preview_AfterRemapAlpha.tif"); \
364  vigra::exportImage(vigra::srcImageRange(alpha), exi); \
365 }
366 #endif
367 
368  // apply default exposure and convert to 8 bit
370 
371  // apply the exposure
372  double scale = 1.0/pow(2.0,opts.outputExposureValue);
373 
375  vigra::functor::Arg1()*vigra::functor::Param(scale));
376 
377  DEBUG_DEBUG("LDR output, with response: " << src.getResponseType());
378  if (src.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_LINEAR) {
380  vigra::functor::Arg1()*vigra::functor::Param(255));
381  } else {
382  if (opts.outputRangeCompression > 0.0)
383  {
384  RangeCompression rangeCompression(opts.outputRangeCompression);
385  vigra::omp::transformImage(srcImageRange(panoImg), destImage(panoImg), rangeCompression);
386  }
387  // create suitable lut for response
388  typedef std::vector<double> LUT;
389  LUT lut;
390  switch(src.getResponseType())
391  {
393  vigra_ext::EMoR::createEMoRLUT(src.getEMoRParams(), lut);
394  break;
396  lut.resize(256);
397  vigra_ext::createGammaLUT(1/src.getGamma(), lut);
398  break;
399  default:
400  vigra_fail("Unknown or unsupported response function type");
401  break;
402  }
403  // scale lut
404  for (size_t i=0; i < lut.size(); i++)
405  lut[i] = lut[i]*255;
406  typedef vigra::RGBValue<float> FRGB;
408 
410  lutf);
411  }
412  // apply color profiles
413  if (!iccProfile.empty() || huginApp::Get()->HasMonitorProfile())
414  {
416  };
417  }
418  }
419 
420 #ifdef DEBUG_REMAP
421 {
422  vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin05_preview_final.tif"); \
423  vigra::exportImage(vigra::srcImageRange(panoImg8), exi); \
424 }
425 #endif
426 
427 
428  } catch (std::exception & e) {
429  m_state_rendering = false;
430  DEBUG_ERROR("error during stitching: " << e.what());
431  hugin_utils::HuginMessageBox(wxString::Format(_("Could not stitch preview.\nError: %s\nOne cause could be an invalid or missing image file."), wxString(e.what(), wxConvLocal)),
432  _("Hugin"), wxOK | wxICON_INFORMATION, this);
433  }
434 
435 
436  // update the transform for pano -> erect coordinates
437  if (m_pano2erect) delete m_pano2erect;
439  src.setProjection(HuginBase::SrcPanoImage::EQUIRECTANGULAR);
440  src.setHFOV(360);
441  src.setSize(vigra::Size2D(360,180));
443  m_pano2erect->createTransform(src, opts);
444 
445  if (m_panoBitmap) {
446  delete m_panoBitmap;
447  }
448  m_panoBitmap = new wxBitmap(panoImage);
449 
450 
451  // always redraw
452  Refresh();
453 
454  m_state_rendering = false;
455  DEBUG_DEBUG("m_state_rendering = false");
456  m_rerender = false;
457 }
458 
459 
461 {
462  if (!IsShown()){
463  return;
464  }
465  DEBUG_TRACE("");
466 
467  int offsetX = 0;
468  int offsetY = 0;
469 
470  wxSize sz = GetClientSize();
471  if (sz.GetWidth() > m_panoImgSize.x) {
472  offsetX = (sz.GetWidth() - m_panoImgSize.x) / 2;
473  }
474  if (sz.GetHeight() > m_panoImgSize.y) {
475  offsetY = (sz.GetHeight() - m_panoImgSize.y) / 2;
476  }
477 
478  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
479  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
480  dc.DrawRectangle(0, 0, offsetX, sz.GetHeight());
481  dc.DrawRectangle(offsetX, 0, sz.GetWidth(), offsetY);
482  dc.DrawRectangle(offsetX, sz.GetHeight() - offsetY,
483  sz.GetWidth(), sz.GetHeight());
484  dc.DrawRectangle(sz.GetWidth() - offsetX, offsetY,
485  sz.GetWidth(), sz.GetHeight() - offsetY);
486 
487  // set a clip region to draw stuff accordingly
488  dc.DestroyClippingRegion();
489  dc.SetClippingRegion(offsetX, offsetY,
491 
492  dc.SetPen(wxPen("BLACK", 1, wxPENSTYLE_SOLID));
493  dc.SetBrush(wxBrush("BLACK", wxBRUSHSTYLE_SOLID));
494  dc.DrawRectangle(offsetX, offsetY, m_panoImgSize.x, m_panoImgSize.y);
495 
496 
497  wxCoord w = m_panoImgSize.x;
498  wxCoord h = m_panoImgSize.y;
499 
500 
501  // draw panorama image
502  if (m_panoBitmap) {
503 
504  dc.DrawBitmap(*m_panoBitmap, offsetX, offsetY);
505 
506  // draw ROI
507  vigra::Size2D panoSize = pano->getOptions().getSize();
508  vigra::Rect2D panoROI = pano->getOptions().getROI();
509  if (panoROI != vigra::Rect2D(panoSize)) {
510 
511  double scale = std::min(w/(double)panoSize.x, h/(double)panoSize.y);
512  vigra::Rect2D previewROI = vigra::Rect2D(panoROI.upperLeft()* scale, panoROI.lowerRight() * scale);
513  vigra::Rect2D screenROI = previewROI;
514  screenROI.moveBy(offsetX, offsetY);
515 
516 
517  // TODO: make areas outside ROI darker than the rest of the image
518  // overdraw areas outside the ROI with some black half transparent
519  // bitmap
520  // it seems to be quite complicated to create a half transparent black image...
521  wxImage blackImg(w,h);
522  // init alpha channel
523  if (!blackImg.HasAlpha()) {
524  blackImg.InitAlpha();
525  }
526  unsigned char * aptr = blackImg.GetAlpha();
527  unsigned char * aend = aptr + w*h;
528  for (; aptr != aend; ++aptr)
529  *aptr = 128;
530  wxBitmap blackBitmap(blackImg);
531 
532  // left
533  if (screenROI.left() > offsetX) {
534  dc.DestroyClippingRegion();
535  dc.SetClippingRegion(offsetX, offsetY,
536  previewROI.left(), h);
537  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
538  }
539  // top
540  if (screenROI.top() > offsetY ) {
541  dc.DestroyClippingRegion();
542  dc.SetClippingRegion(screenROI.left(), offsetY,
543  previewROI.width(), previewROI.top());
544  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
545  }
546  // right
547  if (screenROI.right() < offsetX + w) {
548  dc.DestroyClippingRegion();
549  dc.SetClippingRegion(screenROI.right(), offsetY,
550  w - previewROI.right(), h);
551  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
552  }
553  // bottom
554  if (screenROI.bottom() < offsetY + h ) {
555  dc.DestroyClippingRegion();
556  dc.SetClippingRegion(screenROI.left(), screenROI.bottom(),
557  screenROI.width(), h - previewROI.bottom());
558  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
559  }
560 
561 
562  // reset clipping region
563  dc.DestroyClippingRegion();
564  dc.SetClippingRegion(offsetX, offsetY,
566 
567  // draw boundaries
568  dc.SetPen(wxPen("WHITE", 1, wxPENSTYLE_SOLID));
569  dc.SetLogicalFunction(wxINVERT);
570 
571  DEBUG_DEBUG("ROI scale factor: " << scale << " screen ROI: " << screenROI);
572 
573  dc.DrawLine(screenROI.left(),screenROI.top(),
574  screenROI.right(),screenROI.top());
575  dc.DrawLine(screenROI.right(),screenROI.top(),
576  screenROI.right(),screenROI.bottom());
577  dc.DrawLine(screenROI.right(),screenROI.bottom(),
578  screenROI.left(),screenROI.bottom());
579  dc.DrawLine(screenROI.left(),screenROI.bottom(),
580  screenROI.left(),screenROI.top());
581 
582 
583  }
584  }
585 
586  dc.DestroyClippingRegion();
587  dc.SetClippingRegion(offsetX, offsetY,
589 
590  // draw center lines over display
591  dc.SetPen(wxPen("WHITE", 1, wxPENSTYLE_SOLID));
592  dc.SetLogicalFunction(wxINVERT);
593  dc.DrawLine(offsetX + w/2, offsetY,
594  offsetX + w/2, offsetY + h);
595  dc.DrawLine(offsetX, offsetY + h/2,
596  offsetX + w, offsetY+ h/2);
597 
598 }
599 
600 void PreviewPanel::OnPaint(wxPaintEvent & event)
601 {
602  wxPaintDC dc(this);
603  DrawPreview(dc);
604 }
605 
606 void PreviewPanel::OnResize(wxSizeEvent & e)
607 {
608  DEBUG_TRACE("");
609  wxSize sz = GetClientSize();
610  if (sz.GetWidth() != m_panoImgSize.x && sz.GetHeight() != m_panoImgSize.y) {
612  if (m_autoPreview) {
613  ForceUpdate();
614  }
615  }
616 }
617 
618 
619 void PreviewPanel::mousePressLMBEvent(wxMouseEvent & e)
620 {
621  DEBUG_DEBUG("mousePressLMBEvent: " << e.m_x << "x" << e.m_y);
622  double yaw, pitch;
623  mouse2erect(e.m_x, e.m_y, yaw, pitch);
624  // calculate new rotation angles.
625  Matrix3 rotY;
626  rotY.SetRotationPT(DEG_TO_RAD(-yaw), 0, 0);
627  Matrix3 rotP;
628  rotP.SetRotationPT(0, DEG_TO_RAD(pitch), 0);
629 
630  double y,p,r;
631  Matrix3 rot = rotP * rotY;
632  rot.GetRotationPT(y,p,r);
633  y = RAD_TO_DEG(y);
634  p = RAD_TO_DEG(p);
635  r = RAD_TO_DEG(r);
636  DEBUG_DEBUG("rotation angles pitch*yaw: " << y << " " << p << " " << r);
637 
639  new PanoCommand::RotatePanoCmd(*pano, y, p, r)
640  );
641  if (!m_autoPreview) {
642  ForceUpdate();
643  }
644 }
645 
646 
647 void PreviewPanel::mousePressRMBEvent(wxMouseEvent & e)
648 {
649  DEBUG_DEBUG("mousePressRMBEvent: " << e.m_x << "x" << e.m_y);
650  double yaw, pitch;
651  mouse2erect(e.m_x, e.m_y, yaw, pitch);
652  // theta, phi: spherical coordinates in mathworld notation.
653  double theta = DEG_TO_RAD(yaw);
654  double phi = DEG_TO_RAD(90+pitch);
655  // convert to cartesian coordinates.
656 #ifdef DEBUG
657  double x = cos(theta)* sin(phi);
658 #endif
659  double y = sin(theta)* sin(phi);
660  double z = cos(phi);
661  DEBUG_DEBUG("theta: " << theta << " phi: " << phi << " x y z:" << x << " " << y << " " << z);
662  double roll = RAD_TO_DEG(atan(z/y));
663 
664  DEBUG_DEBUG("roll correction: " << roll);
665 
667  new PanoCommand::RotatePanoCmd(*pano, 0, 0, roll)
668  );
669  if (!m_autoPreview) {
670  ForceUpdate();
671  }
672 }
673 
674 
675 void PreviewPanel::OnMouse(wxMouseEvent & e)
676 {
677  double yaw, pitch;
678  mouse2erect(e.m_x, e.m_y, yaw, pitch);
679 
680  parentWindow->SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0);
681  parentWindow->SetStatusText(wxString::Format("%.1f %.1f", yaw, pitch), 1);
682 }
683 
684 void PreviewPanel::mouse2erect(int xm, int ym, double &xd, double & yd)
685 {
686  if (m_pano2erect) {
687  int offsetX=0, offsetY=0;
688  wxSize sz = GetClientSize();
689  if (sz.GetWidth() > m_panoImgSize.x) {
690  offsetX = (sz.GetWidth() - m_panoImgSize.x) / 2;
691  }
692  if (sz.GetHeight() > m_panoImgSize.y) {
693  offsetY = (sz.GetHeight() - m_panoImgSize.y) / 2;
694  }
695  double x = xm - offsetX - m_panoImgSize.x/2;
696  double y = ym - offsetY - m_panoImgSize.y/2;
697  m_pano2erect->transform(xd, yd, x, y);
698  //DEBUG_DEBUG("pano: " << x << " " << y << " erect: " << xd << "° " << yd << "°");
699  }
700 }
701 
702 void PreviewPanel::DrawOutline(const std::vector<hugin_utils::FDiff2D> & points, wxDC & dc, int offX, int offY)
703 {
704  for (std::vector<hugin_utils::FDiff2D>::const_iterator pnt = points.begin();
705  pnt != points.end() ;
706  ++pnt)
707  {
708  vigra::Diff2D point = pnt->toDiff2D();
709  if (point.x < 0) point.x = 0;
710  if (point.y < 0) point.y = 0;
711  if (point.x >= m_panoImgSize.x)
712  point.x = m_panoImgSize.y-1;
713  if (point.y >= m_panoImgSize.y)
714  point.y = m_panoImgSize.y -1;
715  dc.DrawPoint(hugin_utils::roundi(offX + point.x), hugin_utils::roundi(offY + point.y));
716  }
717 }
718 
719 
721 
723  : wxXmlResourceHandler()
724 {
725  AddWindowStyles();
726 }
727 
729 {
730  XRC_MAKE_INSTANCE(cp, PreviewPanel)
731 
732  cp->Create(m_parentAsWindow,
733  GetID(),
734  GetPosition(), GetSize(),
735  GetStyle("style"),
736  GetName());
737 
738  SetupWindow( cp);
739 
740  return cp;
741 }
742 
744 {
745  return IsOfClass(node, "PreviewPanel");
746 }
747 
748 IMPLEMENT_DYNAMIC_CLASS(PreviewPanelXmlHandler, wxXmlResourceHandler)
749 
#define DEBUG_INFO(msg)
Definition: utils.h:69
PreviewFrame * parentWindow
Definition: PreviewPanel.h:118
PanoramaOptions::ProjectionFormat getProjection() const
HuginBase::PanoramaOptions opts
Definition: PreviewPanel.h:108
wxCursor * m_cursor
Definition: PreviewPanel.h:119
bool m_state_rendering
Definition: PreviewPanel.h:121
void setHeight(unsigned int h)
set panorama height
int roundi(T x)
Definition: hugin_math.h:73
PreviewPanel()
ctor.
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
blend images, by simply stacking them, without soft blending or boundary calculation ...
Definition: Stitcher.h:956
#define DEBUG_TRACE(msg)
Definition: utils.h:67
unsigned int getHeight() const
get panorama height
create a panorama using the reduce operation on all overlapping pixels.
Definition: Stitcher.h:689
bool m_autoPreview
Definition: PreviewPanel.h:98
void updatePreview()
general : Matrix3 is a class for handling 3x3 Matrix manipulation.
Definition: Matrix3.h:37
virtual ~PreviewPanel()
dtor.
include file for the hugin project
Difference reduce functor.
Definition: Stitcher.h:637
void GetRotationPT(double &Yaw, double &Pitch, double &Roll)
GetRotation in panotools style.
Definition: Matrix3.cpp:157
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
Definition: ROIImage.h:300
void applyMapping(vigra::triple< SrcIterator, SrcIterator, SrcAccessor > img, vigra::pair< DestIterator, DestAccessor > dest, T min, T max, int mapping)
Definition: utils.h:685
functor to apply a LUT to gray and color images.
Definition: lut.h:118
void SetRotationPT(double yaw, double pitch, double roll)
set rotation in panotools style, code adapted from Panotools-Script by Bruno Postle ...
Definition: Matrix3.cpp:110
void GetMonitorProfile(wxString &profileName, cmsHPROFILE &profile)
Definition: wxcms.cpp:195
bool transform(double &x_dest, double &y_dest, double x_src, double y_src) const
excecute transform
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:651
double round(double x)
Definition: hugin_math.h:50
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
notifies about changes to images
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void mouse2erect(int xm, int ym, double &xd, double &yd)
void Init(PreviewFrame *parent, HuginBase::Panorama *pano)
const vigra::Rect2D & getROI() const
Model for a panorama.
Definition: Panorama.h:152
void mousePressLMBEvent(wxMouseEvent &e)
empirical model of response
Definition: SrcPanoImage.h:100
just apply exposure and response to linear data
virtual wxObject * DoCreateResource()
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, const std::string &filename, SingleImageRemapper< ImageType, AlphaType > &remapper, FUNCTOR &reduce, const AdvancedOptions &advOptions)
Definition: Stitcher.h:704
void mousePressRMBEvent(wxMouseEvent &e)
HuginBase::Panorama * pano
the model
Definition: PreviewPanel.h:96
void CorrectImage(wxImage &image, const vigra::ImageImportInfo::ICCProfile &iccProfile, const cmsHPROFILE &monitorProfile)
apply color correction to given image using input iccProfile and monitor profile
Definition: wxcms.cpp:218
void SetAutoUpdate(bool enabled)
vigra_ext::Interpolator interpolator
float pow(float a, double b)
Definition: utils.h:181
void DrawOutline(const std::vector< hugin_utils::FDiff2D > &points, wxDC &dc, int offX, int offY)
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
vigra::ImageExportInfo::ICCProfile iccProfile
Definition: Stitcher.h:950
void OnResize(wxSizeEvent &e)
recalculate panorama to fit the panel
void SetBlendMode(BlendMode b)
bool HasMonitorProfile() const
return true if we found a suitable monitor profile and could loading it
Definition: huginApp.h:120
void OnMouse(wxMouseEvent &e)
IMPEX double h[25][1024]
Definition: emor.cpp:169
static GlobalCmdHist & getInstance()
ExposureResponseFunctor2(double exposure, const OP &operation)
SmallRemappedImageCache m_remapCache
Definition: PreviewPanel.h:114
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:324
#define DEBUG_ERROR(msg)
Definition: utils.h:76
void setROI(const vigra::Rect2D &val)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
Definition: ROIImage.h:287
The image preview frame.
Definition: PreviewFrame.h:40
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
void createGammaLUT(double gamma, VECTOR &lut)
Definition: lut.h:50
void createEMoRLUT(const std::vector< float > &params, VECTOR &lut)
Definition: emor.h:44
Contains various routines used for stitching panoramas.
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
unsigned int getWidth() const
HuginBase::PTools::Transform * m_pano2erect
Definition: PreviewPanel.h:111
include file for the hugin project
A stitcher without seaming, just copies the images over each other.
Definition: Stitcher.h:837
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
#define RAD_TO_DEG(x)
Definition: hugin_math.h:45
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
static T max(T x, T y)
Definition: svm.cpp:65
vigra::RGBValue< unsigned char > BRGBValue
Holds transformations for Image -&gt; Pano and the other way.
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
a simple gamma response curve
Definition: SrcPanoImage.h:102
void setSize(vigra::Size2D val)
Set the image size in pixels.
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:312
void transformImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc, const Functor &func)
Definition: openmp_vigra.h:330
#define DEG_TO_RAD(x)
Definition: hugin_math.h:44
#define HUGIN_IMGCACHE_MAPPING_FLOAT
virtual bool CanHandle(wxXmlNode *node)
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, vigra::triple< ImgIter, ImgIter, ImgAccessor > pano, std::pair< AlphaIter, AlphaAccessor > alpha, SingleImageRemapper< ImageType, AlphaType > &remapper, BlendFunctor &blend)
Definition: Stitcher.h:854
vigra::ImageImportInfo::ICCProfile iccProfile
Definition: Stitcher.h:831
A preview panel that renders the pictures using the panotools library.
Definition: PreviewPanel.h:40
void ForceUpdate()
vigra::RGBValue< float > operator()(vigra::RGBValue< float > const &v) const
void invalidate()
invalidates all images
const wxString & GetXRCPath()
return the current xrc path
Definition: huginApp.h:98
All variables of a source image.
Definition: SrcPanoImage.h:194
Panorama image options.
vigra::Size2D getSize() const
get size of output image
RangeCompression(double rangeCompression)
Rotate the panorama.
Definition: PanoCommand.h:448
wxBitmap * m_panoBitmap
Definition: PreviewPanel.h:102
void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
static T min(T x, T y)
Definition: svm.cpp:62
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
vigra::NumericTraits< VT >::RealPromote operator()(VT v) const
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
void DrawPreview(wxDC &dc)
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
BlendMode m_blendMode
Definition: PreviewPanel.h:116
vigra::Diff2D m_panoImgSize
Definition: PreviewPanel.h:100
void OnPaint(wxPaintEvent &event)