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