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 "hugin/PreviewPanel.h"
36 #include "hugin/PreviewFrame.h"
37 #include "hugin/MainFrame.h"
38 #include "base_wx/CommandHistory.h"
39 #include "base_wx/PanoCommand.h"
40 #include "base_wx/wxcms.h"
41 #include "hugin/config_defaults.h"
42 #include "hugin/huginApp.h"
43 
44 #include <math.h>
45 
46 typedef vigra::RGBValue<unsigned char> BRGBValue;
47 
48 BEGIN_EVENT_TABLE(PreviewPanel, wxPanel)
49  EVT_SIZE(PreviewPanel::OnResize)
50  EVT_LEFT_DOWN(PreviewPanel::mousePressLMBEvent)
51  EVT_RIGHT_DOWN(PreviewPanel::mousePressRMBEvent)
52  EVT_MOUSE_EVENTS ( PreviewPanel::OnMouse )
53  EVT_PAINT ( PreviewPanel::OnDraw )
55 
57  : pano(0), m_autoPreview(false),m_panoImgSize(1,1),
58  m_panoBitmap(0),
59  m_pano2erect(0), m_blendMode(BLEND_COPY),
60  m_state_rendering(false), m_rerender(false), m_imgsDirty(true)
61 {
62 }
63 
64 bool PreviewPanel::Create(wxWindow* parent, wxWindowID id,
65  const wxPoint& pos,
66  const wxSize& size,
67  long style,
68  const wxString& name)
69 {
70  DEBUG_TRACE(" Create called *************");
71  if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
72  return false;
73  }
74  DEBUG_TRACE("");
75  DEBUG_DEBUG("m_state_rendering = " << m_state_rendering);
76 
77 #if defined(__WXMSW__)
78  wxString cursorPath = huginApp::Get()->GetXRCPath() + wxT("/data/cursor_cp_pick.cur");
79  m_cursor = new wxCursor(cursorPath, wxBITMAP_TYPE_CUR);
80 #else
81  m_cursor = new wxCursor(wxCURSOR_CROSS);
82 #endif
83  SetCursor(*m_cursor);
84  return true;
85 }
86 
87 
89 {
90  pano = panorama;
91  parentWindow = parent;
92  pano->addObserver(this);
93 }
94 
95 
97 {
98  DEBUG_TRACE("dtor");
99  delete m_cursor;
100  pano->removeObserver(this);
101  if (m_panoBitmap) {
102  delete m_panoBitmap;
103  }
104  if (m_pano2erect) {
105  delete m_pano2erect;
106  }
107  DEBUG_TRACE("dtor end");
108 }
109 
111 {
112  // avoid recursive calls.. don't know if they can happen at all,
113  // but they might lead to crashes.
114  bool dirty = false;
115 
116  const HuginBase::PanoramaOptions & newOpts = pano.getOptions();
117 
118  // check if an important options has been changed
119  if (newOpts.getHFOV() != opts.getHFOV()) {
120  DEBUG_DEBUG("HFOV changed");
121  dirty = true;
122  }
123  if (newOpts.getVFOV() != opts.getVFOV()) {
124  DEBUG_DEBUG("VFOV changed");
125  dirty = true;
126  }
127  if (newOpts.getProjection() != opts.getProjection()) {
128  DEBUG_DEBUG("projection changed");
129  dirty = true;
130  }
131 
133  DEBUG_DEBUG("projection parameters changed");
134  dirty = true;
135  }
137  {
138  DEBUG_DEBUG("output exposure value changed");
139  dirty = true;
140  };
142  {
143  DEBUG_DEBUG("output range compression changed");
144  dirty = true;
145  };
146 
147  opts = newOpts;
148  if (dirty) {
149  // have to remap all images
151  }
152 
153  if (m_autoPreview && dirty) {
154  DEBUG_DEBUG("forcing preview update");
155  ForceUpdate();
156  // resize
157  } else if(m_autoPreview && m_imgsDirty ) {
158  DEBUG_DEBUG("updating preview after image change");
159  updatePreview();
160  m_imgsDirty=false;
161  }
162 }
163 
165 {
166  DEBUG_TRACE("");
167  m_imgsDirty = true;
168 }
169 
171 {
172  m_blendMode = b;
173  updatePreview();
174 }
175 
177 {
178  updatePreview();
179 }
180 
181 void PreviewPanel::SetAutoUpdate(bool enabled)
182 {
183  m_autoPreview = enabled;
184  if (enabled) {
185  updatePreview();
186  }
187 }
188 
191 template <class OP>
193 {
194  ExposureResponseFunctor2(double exposure, const OP & operation)
195  : op(operation), e(exposure)
196  {
197  }
198  const OP & op;
199  double e;
200 
201  template <class VT>
202  typename vigra::NumericTraits<VT>::RealPromote
203  operator()(VT v) const
204  {
205  return op(v*e);
206  }
207 };
208 
210 {
211 public:
212  RangeCompression(double rangeCompression)
213  {
214  m_rangeCompression = rangeCompression;
215  m_logM1 = std::log2(m_rangeCompression + 1);
216  };
217 
218  vigra::RGBValue<float> operator()(vigra::RGBValue<float> const& v) const
219  {
220  return vigra::RGBValue<float>(std::log2(m_rangeCompression * v.red() + 1) / m_logM1,
221  std::log2(m_rangeCompression * v.green() + 1) / m_logM1,
222  std::log2(m_rangeCompression * v.blue() + 1) / m_logM1
223  );
224  }
225 private:
227  double m_logM1;
228 };
229 
231 {
232  DEBUG_TRACE("");
233 
234  // we can accidentally end up here recursively, because wxWidgets
235  // allows user input during redraw of the progress in the bottom
236  if (m_state_rendering) {
237  DEBUG_DEBUG("m_state_rendering == true, aborting rendering");
238  m_rerender = true;
239  return;
240  }
241 
242  DEBUG_DEBUG("m_state_rendering = true");
243  m_state_rendering = true;
244  m_rerender = false;
245 
246  {
247  // Even though the frame is hidden, the panel is not
248  // so check the parent instead
249  if (parentWindow) {
250  if (parentWindow->IsShown() && (! parentWindow->IsIconized())) {
251  DEBUG_INFO("Parent window shown - updating");
252  } else {
253  DEBUG_INFO("Parent window hidden - not updating");
254  m_state_rendering = false;
255  return;
256  }
257  }
258  }
259  wxBusyCursor wait;
260  double finalWidth = pano->getOptions().getWidth();
261  double finalHeight = pano->getOptions().getHeight();
262 
263  m_panoImgSize = vigra::Diff2D(GetClientSize().GetWidth(), GetClientSize().GetHeight());
264 
265  double ratioPano = finalWidth / finalHeight;
266  double ratioPanel = (double)m_panoImgSize.x / (double)m_panoImgSize.y;
267 
268  DEBUG_DEBUG("panorama ratio: " << ratioPano << " panel ratio: " << ratioPanel);
269 
270  if (ratioPano < ratioPanel) {
271  // panel is wider than pano
273  DEBUG_DEBUG("portrait: " << m_panoImgSize);
274  } else {
275  // panel is taller than pano
277  DEBUG_DEBUG("landscape: " << m_panoImgSize);
278  }
279 
281  //don't use GPU for preview
282  opts.remapUsingGPU = false;
283  opts.setWidth(m_panoImgSize.x, false);
284  opts.setHeight(m_panoImgSize.y);
285  // always use bilinear for preview.
286 
287  // reset ROI. The preview needs to draw the parts outside the ROI, too!
288  opts.setROI(vigra::Rect2D(opts.getSize()));
290 
291  // create images
292  wxImage panoImage(m_panoImgSize.x, m_panoImgSize.y);
293  try {
294  vigra::BasicImageView<vigra::RGBValue<unsigned char> > panoImg8((vigra::RGBValue<unsigned char> *)panoImage.GetData(), panoImage.GetWidth(), panoImage.GetHeight());
295  vigra::FRGBImage panoImg(m_panoImgSize);
296  vigra::BImage alpha(m_panoImgSize);
297 
298  DEBUG_DEBUG("about to stitch images, pano size: " << m_panoImgSize);
299  HuginBase::UIntSet displayedImages = pano->getActiveImages();
300  if (!displayedImages.empty()) {
302  DEBUG_DEBUG("HDR output merge");
303 
306  stitcher.stitch(opts, displayedImages,
307  destImageRange(panoImg), destImage(alpha),
308  m_remapCache,
309  hdrmerge);
310 #ifdef DEBUG_REMAP
311 {
312  vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_preview_HDR_Reduce.tif"); \
313  vigra::exportImage(vigra::srcImageRange(panoImg), exi); \
314 }
315 {
316  vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_preview_HDR_Reduce_Alpha.tif"); \
317  vigra::exportImage(vigra::srcImageRange(alpha), exi); \
318 }
319 #endif
320 
321  // find min and max
322  vigra::FindMinMax<float> minmax; // init functor
323  vigra::inspectImageIf(vigra::srcImageRange(panoImg), vigra::srcImage(alpha),
324  minmax);
325  double min = std::max(minmax.min, 1e-6f);
326  double max = minmax.max;
327 
328  int mapping = wxConfigBase::Get()->Read(wxT("/ImageCache/Mapping"), HUGIN_IMGCACHE_MAPPING_FLOAT);
329  vigra_ext::applyMapping(vigra::srcImageRange(panoImg), vigra::destImage(panoImg8), min, max, mapping);
330 
331  } else {
332  // LDR output
333  vigra::ImageImportInfo::ICCProfile iccProfile;
334  switch (m_blendMode) {
335  case BLEND_COPY:
336  {
339  stitcher.stitch(opts, displayedImages,
340  destImageRange(panoImg), destImage(alpha),
341  m_remapCache,
342  blender);
343  iccProfile = stitcher.iccProfile;
344  break;
345  }
346  case BLEND_DIFFERENCE:
347  {
350  stitcher.stitch(opts, displayedImages,
351  destImageRange(panoImg), destImage(alpha),
352  m_remapCache,
353  func);
354  iccProfile = stitcher.iccProfile;
355  break;
356  }
357  }
358 
359 #ifdef DEBUG_REMAP
360 {
361  vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_preview_AfterRemap.tif"); \
362  vigra::exportImage(vigra::srcImageRange(panoImg), exi); \
363 }
364 {
365  vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_preview_AfterRemapAlpha.tif"); \
366  vigra::exportImage(vigra::srcImageRange(alpha), exi); \
367 }
368 #endif
369 
370  // apply default exposure and convert to 8 bit
372 
373  // apply the exposure
374  double scale = 1.0/pow(2.0,opts.outputExposureValue);
375 
377  vigra::functor::Arg1()*vigra::functor::Param(scale));
378 
379  DEBUG_DEBUG("LDR output, with response: " << src.getResponseType());
380  if (src.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_LINEAR) {
382  vigra::functor::Arg1()*vigra::functor::Param(255));
383  } else {
384  if (opts.outputRangeCompression > 0.0)
385  {
386  RangeCompression rangeCompression(opts.outputRangeCompression);
387  vigra::omp::transformImage(srcImageRange(panoImg), destImage(panoImg), rangeCompression);
388  }
389  // create suitable lut for response
390  typedef std::vector<double> LUT;
391  LUT lut;
392  switch(src.getResponseType())
393  {
395  vigra_ext::EMoR::createEMoRLUT(src.getEMoRParams(), lut);
396  break;
398  lut.resize(256);
399  vigra_ext::createGammaLUT(1/src.getGamma(), lut);
400  break;
401  default:
402  vigra_fail("Unknown or unsupported response function type");
403  break;
404  }
405  // scale lut
406  for (size_t i=0; i < lut.size(); i++)
407  lut[i] = lut[i]*255;
408  typedef vigra::RGBValue<float> FRGB;
410 
412  lutf);
413  }
414  // apply color profiles
415  if (!iccProfile.empty() || huginApp::Get()->HasMonitorProfile())
416  {
418  };
419  }
420  }
421 
422 #ifdef DEBUG_REMAP
423 {
424  vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin05_preview_final.tif"); \
425  vigra::exportImage(vigra::srcImageRange(panoImg8), exi); \
426 }
427 #endif
428 
429 
430  } catch (std::exception & e) {
431  m_state_rendering = false;
432  DEBUG_ERROR("error during stitching: " << e.what());
433  wxMessageBox(wxString::Format(_("Could not stitch preview.\nError: %s\nOne cause could be an invalid or missing image file."), wxString(e.what(), wxConvLocal)),
434 #ifdef __WXMSW__
435  wxT("Hugin"),
436 #else
437  wxT(""),
438 #endif
439  wxOK | wxICON_INFORMATION);
440  }
441 
442 
443  // update the transform for pano -> erect coordinates
444  if (m_pano2erect) delete m_pano2erect;
446  src.setProjection(HuginBase::SrcPanoImage::EQUIRECTANGULAR);
447  src.setHFOV(360);
448  src.setSize(vigra::Size2D(360,180));
450  m_pano2erect->createTransform(src, opts);
451 
452  if (m_panoBitmap) {
453  delete m_panoBitmap;
454  }
455  m_panoBitmap = new wxBitmap(panoImage);
456 
457 
458  // always redraw
459  wxClientDC dc(this);
460  DrawPreview(dc);
461 
462  m_state_rendering = false;
463  DEBUG_DEBUG("m_state_rendering = false");
464  m_rerender = false;
465 }
466 
467 
469 {
470  if (!IsShown()){
471  return;
472  }
473  DEBUG_TRACE("");
474 
475  int offsetX = 0;
476  int offsetY = 0;
477 
478  wxSize sz = GetClientSize();
479  if (sz.GetWidth() > m_panoImgSize.x) {
480  offsetX = (sz.GetWidth() - m_panoImgSize.x) / 2;
481  }
482  if (sz.GetHeight() > m_panoImgSize.y) {
483  offsetY = (sz.GetHeight() - m_panoImgSize.y) / 2;
484  }
485 
486  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
487  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
488  dc.DrawRectangle(0, 0, offsetX, sz.GetHeight());
489  dc.DrawRectangle(offsetX, 0, sz.GetWidth(), offsetY);
490  dc.DrawRectangle(offsetX, sz.GetHeight() - offsetY,
491  sz.GetWidth(), sz.GetHeight());
492  dc.DrawRectangle(sz.GetWidth() - offsetX, offsetY,
493  sz.GetWidth(), sz.GetHeight() - offsetY);
494 
495  // set a clip region to draw stuff accordingly
496  dc.DestroyClippingRegion();
497  dc.SetClippingRegion(offsetX, offsetY,
499 
500  dc.SetPen(wxPen(wxT("BLACK"), 1, wxPENSTYLE_SOLID));
501  dc.SetBrush(wxBrush(wxT("BLACK"), wxBRUSHSTYLE_SOLID));
502  dc.DrawRectangle(offsetX, offsetY, m_panoImgSize.x, m_panoImgSize.y);
503 
504 
505  wxCoord w = m_panoImgSize.x;
506  wxCoord h = m_panoImgSize.y;
507 
508 
509  // draw panorama image
510  if (m_panoBitmap) {
511 
512  dc.DrawBitmap(*m_panoBitmap, offsetX, offsetY);
513 
514  // draw ROI
515  vigra::Size2D panoSize = pano->getOptions().getSize();
516  vigra::Rect2D panoROI = pano->getOptions().getROI();
517  if (panoROI != vigra::Rect2D(panoSize)) {
518 
519  double scale = std::min(w/(double)panoSize.x, h/(double)panoSize.y);
520  vigra::Rect2D previewROI = vigra::Rect2D(panoROI.upperLeft()* scale, panoROI.lowerRight() * scale);
521  vigra::Rect2D screenROI = previewROI;
522  screenROI.moveBy(offsetX, offsetY);
523 
524 
525  // TODO: make areas outside ROI darker than the rest of the image
526  // overdraw areas outside the ROI with some black half transparent
527  // bitmap
528  // it seems to be quite complicated to create a half transparent black image...
529  wxImage blackImg(w,h);
530  // init alpha channel
531  if (!blackImg.HasAlpha()) {
532  blackImg.InitAlpha();
533  }
534  unsigned char * aptr = blackImg.GetAlpha();
535  unsigned char * aend = aptr + w*h;
536  for (; aptr != aend; ++aptr)
537  *aptr = 128;
538  wxBitmap blackBitmap(blackImg);
539 
540  // left
541  if (screenROI.left() > offsetX) {
542  dc.DestroyClippingRegion();
543  dc.SetClippingRegion(offsetX, offsetY,
544  previewROI.left(), h);
545  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
546  }
547  // top
548  if (screenROI.top() > offsetY ) {
549  dc.DestroyClippingRegion();
550  dc.SetClippingRegion(screenROI.left(), offsetY,
551  previewROI.width(), previewROI.top());
552  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
553  }
554  // right
555  if (screenROI.right() < offsetX + w) {
556  dc.DestroyClippingRegion();
557  dc.SetClippingRegion(screenROI.right(), offsetY,
558  w - previewROI.right(), h);
559  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
560  }
561  // bottom
562  if (screenROI.bottom() < offsetY + h ) {
563  dc.DestroyClippingRegion();
564  dc.SetClippingRegion(screenROI.left(), screenROI.bottom(),
565  screenROI.width(), h - previewROI.bottom());
566  dc.DrawBitmap(blackBitmap, offsetX, offsetY);
567  }
568 
569 
570  // reset clipping region
571  dc.DestroyClippingRegion();
572  dc.SetClippingRegion(offsetX, offsetY,
574 
575  // draw boundaries
576  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
577  dc.SetLogicalFunction(wxINVERT);
578 
579  DEBUG_DEBUG("ROI scale factor: " << scale << " screen ROI: " << screenROI);
580 
581  dc.DrawLine(screenROI.left(),screenROI.top(),
582  screenROI.right(),screenROI.top());
583  dc.DrawLine(screenROI.right(),screenROI.top(),
584  screenROI.right(),screenROI.bottom());
585  dc.DrawLine(screenROI.right(),screenROI.bottom(),
586  screenROI.left(),screenROI.bottom());
587  dc.DrawLine(screenROI.left(),screenROI.bottom(),
588  screenROI.left(),screenROI.top());
589 
590 
591  }
592  }
593 
594  dc.DestroyClippingRegion();
595  dc.SetClippingRegion(offsetX, offsetY,
597 
598  // draw center lines over display
599  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
600  dc.SetLogicalFunction(wxINVERT);
601  dc.DrawLine(offsetX + w/2, offsetY,
602  offsetX + w/2, offsetY + h);
603  dc.DrawLine(offsetX, offsetY + h/2,
604  offsetX + w, offsetY+ h/2);
605 
606 }
607 
608 void PreviewPanel::OnDraw(wxPaintEvent & event)
609 {
610  wxPaintDC dc(this);
611  DrawPreview(dc);
612 }
613 
614 void PreviewPanel::OnResize(wxSizeEvent & e)
615 {
616  DEBUG_TRACE("");
617  wxSize sz = GetClientSize();
618  if (sz.GetWidth() != m_panoImgSize.x && sz.GetHeight() != m_panoImgSize.y) {
620  if (m_autoPreview) {
621  ForceUpdate();
622  }
623  }
624 }
625 
626 
627 void PreviewPanel::mousePressLMBEvent(wxMouseEvent & e)
628 {
629  DEBUG_DEBUG("mousePressLMBEvent: " << e.m_x << "x" << e.m_y);
630  double yaw, pitch;
631  mouse2erect(e.m_x, e.m_y, yaw, pitch);
632  // calculate new rotation angles.
633  Matrix3 rotY;
634  rotY.SetRotationPT(DEG_TO_RAD(-yaw), 0, 0);
635  Matrix3 rotP;
636  rotP.SetRotationPT(0, DEG_TO_RAD(pitch), 0);
637 
638  double y,p,r;
639  Matrix3 rot = rotP * rotY;
640  rot.GetRotationPT(y,p,r);
641  y = RAD_TO_DEG(y);
642  p = RAD_TO_DEG(p);
643  r = RAD_TO_DEG(r);
644  DEBUG_DEBUG("rotation angles pitch*yaw: " << y << " " << p << " " << r);
645 
647  new PanoCommand::RotatePanoCmd(*pano, y, p, r)
648  );
649  if (!m_autoPreview) {
650  ForceUpdate();
651  }
652 }
653 
654 
655 void PreviewPanel::mousePressRMBEvent(wxMouseEvent & e)
656 {
657  DEBUG_DEBUG("mousePressRMBEvent: " << e.m_x << "x" << e.m_y);
658  double yaw, pitch;
659  mouse2erect(e.m_x, e.m_y, yaw, pitch);
660  // theta, phi: spherical coordinates in mathworld notation.
661  double theta = DEG_TO_RAD(yaw);
662  double phi = DEG_TO_RAD(90+pitch);
663  // convert to cartesian coordinates.
664 #ifdef DEBUG
665  double x = cos(theta)* sin(phi);
666 #endif
667  double y = sin(theta)* sin(phi);
668  double z = cos(phi);
669  DEBUG_DEBUG("theta: " << theta << " phi: " << phi << " x y z:" << x << " " << y << " " << z);
670  double roll = RAD_TO_DEG(atan(z/y));
671 
672  DEBUG_DEBUG("roll correction: " << roll);
673 
675  new PanoCommand::RotatePanoCmd(*pano, 0, 0, roll)
676  );
677  if (!m_autoPreview) {
678  ForceUpdate();
679  }
680 }
681 
682 
683 void PreviewPanel::OnMouse(wxMouseEvent & e)
684 {
685  double yaw, pitch;
686  mouse2erect(e.m_x, e.m_y, yaw, pitch);
687 
688  parentWindow->SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0);
689  parentWindow->SetStatusText(wxString::Format(wxT("%.1f %.1f"), yaw, pitch), 1);
690 }
691 
692 void PreviewPanel::mouse2erect(int xm, int ym, double &xd, double & yd)
693 {
694  if (m_pano2erect) {
695  int offsetX=0, offsetY=0;
696  wxSize sz = GetClientSize();
697  if (sz.GetWidth() > m_panoImgSize.x) {
698  offsetX = (sz.GetWidth() - m_panoImgSize.x) / 2;
699  }
700  if (sz.GetHeight() > m_panoImgSize.y) {
701  offsetY = (sz.GetHeight() - m_panoImgSize.y) / 2;
702  }
703  double x = xm - offsetX - m_panoImgSize.x/2;
704  double y = ym - offsetY - m_panoImgSize.y/2;
705  m_pano2erect->transform(xd, yd, x, y);
706  //DEBUG_DEBUG("pano: " << x << " " << y << " erect: " << xd << "° " << yd << "°");
707  }
708 }
709 
710 void PreviewPanel::DrawOutline(const std::vector<hugin_utils::FDiff2D> & points, wxDC & dc, int offX, int offY)
711 {
712  for (std::vector<hugin_utils::FDiff2D>::const_iterator pnt = points.begin();
713  pnt != points.end() ;
714  ++pnt)
715  {
716  vigra::Diff2D point = pnt->toDiff2D();
717  if (point.x < 0) point.x = 0;
718  if (point.y < 0) point.y = 0;
719  if (point.x >= m_panoImgSize.x)
720  point.x = m_panoImgSize.y-1;
721  if (point.y >= m_panoImgSize.y)
722  point.y = m_panoImgSize.y -1;
723  dc.DrawPoint(hugin_utils::roundi(offX + point.x), hugin_utils::roundi(offY + point.y));
724  }
725 }
726 
727 
729 
731  : wxXmlResourceHandler()
732 {
733  AddWindowStyles();
734 }
735 
737 {
738  XRC_MAKE_INSTANCE(cp, PreviewPanel)
739 
740  cp->Create(m_parentAsWindow,
741  GetID(),
742  GetPosition(), GetSize(),
743  GetStyle(wxT("style")),
744  GetName());
745 
746  SetupWindow( cp);
747 
748  return cp;
749 }
750 
752 {
753  return IsOfClass(node, wxT("PreviewPanel"));
754 }
755 
756 IMPLEMENT_DYNAMIC_CLASS(PreviewPanelXmlHandler, wxXmlResourceHandler)
757 
#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 Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxT("panel"))
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
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.
END_EVENT_TABLE()
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:649
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:156
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
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
void OnDraw(wxPaintEvent &event)
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:134
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
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