Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CPImageCtrl.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 // standard wx include
28 #include "hugin_config.h"
29 #include "panoinc_WX.h"
30 
31 // standard hugin include
32 #include "panoinc.h"
33 #include "base_wx/platform.h"
34 
35 #include <vigra/inspectimage.hxx>
36 #include <vigra/transformimage.hxx>
37 #include <vigra/basicimageview.hxx>
38 #include <functional> // std::bind
39 
40 #include "hugin/config_defaults.h"
41 #include "hugin/CPImageCtrl.h"
42 #include "base_wx/wxImageCache.h"
43 #include "hugin/CPEditorPanel.h"
44 #include "hugin/MainFrame.h"
45 #include "hugin/huginApp.h"
46 #include "base_wx/wxcms.h"
47 
49 
50 // definition of the control point event
51 
53 wxDEFINE_EVENT(EVT_CPEVENT, CPEvent);
54 
55 CPEvent::CPEvent( )
56 {
57  SetEventType( EVT_CPEVENT );
58  SetEventObject( (wxWindow *) NULL );
59  mode = NONE;
60 }
61 
62 CPEvent::CPEvent(wxWindow * win, CPEventMode evt_mode)
63 {
64  SetEventType(EVT_CPEVENT);
65  SetEventObject(win);
66  mode = evt_mode;
67 }
68 
70 {
71  SetEventType( EVT_CPEVENT );
72  SetEventObject( win );
74  point = p;
75 }
76 
77 CPEvent::CPEvent(wxWindow *win, unsigned int cpNr)
78 {
79  SetEventType( EVT_CPEVENT );
80  SetEventObject( win );
82  pointNr = cpNr;
83 }
84 
85 CPEvent::CPEvent(wxWindow* win, unsigned int cpNr, const hugin_utils::FDiff2D & p)
86 {
87  SetEventType( EVT_CPEVENT );
88  SetEventObject( win );
90  pointNr = cpNr;
91  point = p;
92 }
93 
94 CPEvent::CPEvent(wxWindow* win, const hugin_utils::FDiff2D & p1, const hugin_utils::FDiff2D & p2)
95 {
96  SetEventType(EVT_CPEVENT);
97  SetEventObject(win);
100  abs(hugin_utils::roundi(p2.x-p1.x)),abs(hugin_utils::roundi(p2.y-p1.y)));
101 };
102 
103 CPEvent::CPEvent(wxWindow* win, CPEventMode evt_mode, const hugin_utils::FDiff2D & p)
104 {
105  SetEventType(EVT_CPEVENT);
106  SetEventObject(win);
107  mode = evt_mode;
108  point = p;
109 }
110 
111 CPEvent::CPEvent(wxWindow* win, CPEventMode evt_mode, const HuginBase::ControlPoint cp)
112 {
113  SetEventType(EVT_CPEVENT);
114  SetEventObject(win);
115  mode=evt_mode;
116  m_cp=cp;
117 };
118 
119 CPEvent::CPEvent(wxWindow* win, CPEventMode evt_mode, size_t cpNr, const HuginBase::ControlPoint cp)
120 {
121  SetEventType(EVT_CPEVENT);
122  SetEventObject(win);
123  mode=evt_mode;
124  pointNr=cpNr;
125  m_cp=cp;
126 };
127 
128 wxEvent * CPEvent::Clone() const
129 {
130  return new CPEvent(*this);
131 }
132 
134 {
135  m_cp=cp;
136  m_control=control;
137  m_mirrored=mirrored;
139 };
140 
141 void DisplayedControlPoint::SetColour(wxColour pointColour, wxColour textColour)
142 {
143  m_pointColour=pointColour;
144  m_textColour=textColour;
145 };
146 
147 void DisplayedControlPoint::SetLabel(wxString newLabel)
148 {
149  m_label=newLabel;
150 };
151 
153 {
154  m_control=control;
155 };
156 
157 void DrawCross(wxDC& dc, wxPoint p, int l)
158 {
159  dc.DrawLine(p + wxPoint(-l, 0),
160  p + wxPoint(-1, 0));
161  dc.DrawLine(p + wxPoint(2, 0),
162  p + wxPoint(l+1, 0));
163  dc.DrawLine(p + wxPoint(0, -l),
164  p + wxPoint(0, -1));
165  dc.DrawLine(p + wxPoint(0, 2),
166  p + wxPoint(0, l+1));
167 };
168 
169 void DisplayedControlPoint::Draw(wxDC& dc, const wxRect& visibleRect, bool selected, bool newPoint)
170 {
171  if(m_control==NULL)
172  {
173  return;
174  };
175  // select color
176  wxColour bgColor = m_pointColour;
177  wxColour textColor = m_textColour;
178  bool drawMag = false;
179  if (selected)
180  {
181  bgColor = wxTheColourDatabase->Find(wxT("RED"));
182  textColor = wxTheColourDatabase->Find(wxT("WHITE"));
184  }
185  if (newPoint)
186  {
187  bgColor = wxTheColourDatabase->Find(wxT("YELLOW"));
188  textColor = wxTheColourDatabase->Find(wxT("BLACK"));
189  drawMag = true;
190  }
191 
192  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
193  dc.SetBrush(wxBrush(wxT("BLACK"),wxBRUSHSTYLE_TRANSPARENT));
194 
196  hugin_utils::FDiff2D point = m_control->applyRot(pointInput);
197  wxPoint p = m_control->roundP(m_control->scale(point));
198  hugin_utils::FDiff2D pointInput2;
199  wxPoint p2;
200  if(IsDrawingLine())
201  {
203  hugin_utils::FDiff2D point2 = m_control->applyRot(pointInput2);
204  p2 = m_control->roundP(m_control->scale(point2));
205  // check that line is in visible range
206  const wxRect lineRect(p, p2);
207  if (!visibleRect.Intersects(lineRect))
208  {
209  // reset label position, so it is not considered when checking
210  m_labelPos = wxRect();
211  m_labelPos2 = wxRect();
212  return;
213  };
214  }
215  else
216  {
217  // check that point is inside the visible rect
218  if (!visibleRect.Contains(p))
219  {
220  // reset label position, so it is not considered when checking
221  m_labelPos = wxRect();
222  m_labelPos2 = wxRect();
223  return;
224  };
225  }
226  int l = 6;
227  // draw cursor line, choose white or black
228  vigra::Rect2D box;
229  if(IsDrawingLine())
230  {
231  box.setUpperLeft(vigra::Point2D(hugin_utils::roundi(std::min(m_cp.x1, m_cp.x2)) - l, hugin_utils::roundi(std::min(m_cp.y1, m_cp.y2)) - l));
232  box.setSize(hugin_utils::roundi(std::abs(m_cp.x1 - m_cp.x2) + 2.0*l), hugin_utils::roundi(std::abs(m_cp.y1 - m_cp.y2) + 2.0*l));
233  }
234  else
235  {
236  box.setUpperLeft(vigra::Point2D(hugin_utils::roundi(pointInput.x - l), hugin_utils::roundi(pointInput.y - l)));
237  box.setSize(2*l, 2*l);
238  };
239  // only use part inside.
240  box &= vigra::Rect2D(m_control->GetImg()->size());
241  if(box.width()<=0 || box.height()<=0)
242  {
243  return;
244  };
245  // calculate mean "luminance value"
246  vigra::FindAverage<vigra::UInt8> average; // init functor
247  vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> > lumac;
248  vigra::inspectImage(m_control->GetImg()->upperLeft()+ box.upperLeft(),
249  m_control->GetImg()->upperLeft()+ box.lowerRight(),
250  lumac, average);
251  if (average() < 150)
252  {
253  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
254  }
255  else
256  {
257  dc.SetPen(wxPen(wxT("BLACK"), 1, wxPENSTYLE_SOLID));
258  }
259 
260  if(IsDrawingLine())
261  {
262  DrawLine(dc);
263  DrawCross(dc, p, l);
264  DrawCross(dc, p2, l);
265  }
266  else
267  {
269  {
270  DrawLineSegment(dc);
271  };
272  DrawCross(dc, p, l);
273  };
274  // calculate distance to the image boundaries,
275  // decide where to put the label and magnifier
276  if (IsDrawingLine())
277  {
278  m_labelPos2 = DrawTextMag(dc, p2, pointInput2, drawMag, textColor, bgColor);
279  };
280  // draw first point second so that is on top
281  m_labelPos=DrawTextMag(dc, p, pointInput, drawMag, textColor, bgColor);
282 }
283 
284 wxRect DisplayedControlPoint::DrawTextMag(wxDC& dc, wxPoint p, hugin_utils::FDiff2D pointInput, bool drawMag, wxColour textColour, wxColour bgColour)
285 {
286  wxRect labelPos;
287  int l = 6;
288  wxSize clientSize = m_control->GetClientSize();
289  int vx0, vy0;
290  m_control->GetViewStart(&vx0, &vy0);
291  wxFont font(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT);
292  dc.SetFont(font);
293  wxPoint pClient(p.x - vx0, p.y - vy0);
294  // space in upper left, upper right, lower left, lower right
295  int maxDistUR = std::min(clientSize.x - pClient.x, pClient.y);
296  int maxDistLL = std::min(pClient.x, clientSize.y - pClient.y);
297  int maxDistLR = std::min(clientSize.x - pClient.x, clientSize.y - pClient.y);
298 
299  // text and magnifier offset
300  int toff = l-1;
301  // default to lower right
302  wxPoint tul = p + wxPoint(toff,toff);
303 
304  // calculate text position and extend
305  // width of border around text label
306  int tB = 2;
307  wxCoord tw, th;
308  dc.GetTextExtent(m_label, &tw, &th);
309 
310  if (drawMag && m_control->getScale() < 2)
311  {
312  const wxBitmap& magBitmap = m_control->GetMagBitmap(pointInput);
313  // TODO: select position depending on visible part of canvas
314  wxPoint ulMag = tul;
315  // choose placement of the magnifier
316  int w = toff + magBitmap.GetWidth()+3;
317  int db = 5;
318  if ( maxDistLR > w + db )
319  {
320  ulMag = p + wxPoint(toff,toff);
321  }
322  else
323  {
324  if (maxDistLL > w + db)
325  {
326  ulMag = p + wxPoint(-w, toff);
327  }
328  else
329  {
330  if (maxDistUR > w + db)
331  {
332  ulMag = p + wxPoint(toff, -w);
333  }
334  else
335  {
336  ulMag = p + wxPoint(-w, -w);
337  }
338  }
339  };
340 
341  dc.DrawBitmap(magBitmap, ulMag);
342  dc.SetPen(wxPen(wxT("BLACK"), 1, wxPENSTYLE_SOLID));
343  dc.SetBrush(wxBrush(wxT("WHITE"),wxBRUSHSTYLE_TRANSPARENT));
344 
345  // draw Bevel
346  int bw = magBitmap.GetWidth();
347  int bh = magBitmap.GetHeight();
348  dc.DrawLine(ulMag.x-1, ulMag.y+bh,
349  ulMag.x+bw+1, ulMag.y+bh);
350  dc.DrawLine(ulMag.x+bw, ulMag.y+bh,
351  ulMag.x+bw, ulMag.y-2);
352  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
353  dc.DrawLine(ulMag.x-1, ulMag.y-1,
354  ulMag.x+bw+1, ulMag.y-1);
355  dc.DrawLine(ulMag.x-1, ulMag.y+bh,
356  ulMag.x-1, ulMag.y-2);
357  }
358  // choose placement of text.
359  int db = 5;
360  int w = toff+tw+2*tB;
361  if ( maxDistLR > w + db && (!drawMag) )
362  {
363  tul = p + wxPoint(toff,toff);
364  }
365  else
366  {
367  if (maxDistLL > w + db)
368  {
369  tul = p + wxPoint(-w, toff);
370  }
371  else
372  {
373  if (maxDistUR > w + db)
374  {
375  tul = p + wxPoint(toff, -(toff) - (th+2*tB));
376  }
377  else
378  {
379  tul = p + wxPoint(-w, -(toff) - (th+2*tB));
380  };
381  };
382  };
383 
384  // draw background
385  dc.SetPen(wxPen(textColour, 1, wxPENSTYLE_SOLID));
386  dc.SetBrush(wxBrush(bgColour, wxBRUSHSTYLE_SOLID));
387  dc.DrawRectangle(tul.x, tul.y, tw+2*tB+1, th+2*tB);
388  labelPos.SetLeft(tul.x);
389  labelPos.SetTop(tul.y);
390  labelPos.SetWidth(tw+2*tB+1);
391  labelPos.SetHeight(th+2*tB);
392  // draw number
393  dc.SetTextForeground(textColour);
394  dc.DrawText(m_label, tul + wxPoint(tB,tB));
395  return labelPos;
396 };
397 
399 {
400  if(m_control==NULL)
401  {
402  return;
403  };
404  hugin_utils::FDiff2D p1, p2, dp;
405  // transform end points to pano space
407  {
408  return;
409  };
411  {
412  return;
413  };
414  dp=p2-p1;
415  int len = hugin_utils::roundi(sqrt((m_cp.x1 - m_cp.x2)*(m_cp.x1 - m_cp.x2) + (m_cp.y1 - m_cp.y2)*(m_cp.y1 - m_cp.y2))) + 1;
416  if(len<5)
417  {
418  //very short line, draw straight line
421  }
422  else
423  {
424  //longer line, draw correct line, taking output projection into account
425  wxPoint* points=new wxPoint[len+1];
426  for(size_t i=0; i<len+1; i++)
427  {
428  hugin_utils::FDiff2D p = p1 + dp*((double)i / len);
429  // transform line coordinates back to image space
431  {
432  delete []points;
433  //fall through, draw direct line, not exact, but better than no line
436  return;
437  };
438  // check that all points are inside of image, accept a little border around the whole image
439  if (p2.x<-100 || p2.x>m_control->GetRealImageSize().GetWidth() + 100 ||
440  p2.y<-100 || p2.y>m_control->GetRealImageSize().GetHeight() + 100)
441  {
442  // this can happen, if the line cp span the 360 deg border
443  // in this case don't draw anything
444  delete[]points;
445  return;
446  }
447  points[i]=m_control->roundP(m_control->scale(m_control->applyRot(p2)));
448  };
449  dc.SetClippingRegion(wxPoint(0, 0), m_control->GetBitmapSize());
450  dc.DrawLines(len+1, points);
451  dc.DestroyClippingRegion();
452  delete []points;
453  };
454 };
455 
457 {
458  if(m_control==NULL)
459  {
460  return;
461  };
462  // calculate line equation
464  hugin_utils::FDiff2D p2_image = m_mirrored ? hugin_utils::FDiff2D(m_cp.x1, m_cp.y1) : hugin_utils::FDiff2D(m_cp.x2, m_cp.y2);
465  hugin_utils::FDiff2D p1, p2, dp;
466  if(!m_control->getFirstInvTrans()->transformImgCoord(p1, p1_image))
467  {
468  return;
469  };
470  if(!m_control->getSecondInvTrans()->transformImgCoord(p2, p2_image))
471  {
472  return;
473  };
474  dp=p2-p1;
475  // now find the parameter to draw an appropriate long line segment
476  double f=1.0;
477  int image_width=m_control->GetRealImageSize().GetWidth();
478  int image_height=m_control->GetRealImageSize().GetHeight();
479  int image_dimension=std::min(image_width, image_height);
480  int line_length=-1;
481  while(f>1e-4)
482  {
483  p2=p1+dp*f;
484  if(m_control->getFirstTrans()->transformImgCoord(p2_image, p2))
485  {
486  double length=sqrt(p1_image.squareDistance(p2_image));
487  if(length > 0.05f * image_dimension && length < 0.75f * image_dimension)
488  {
489  line_length=hugin_utils::roundi(length);
490  break;
491  };
492  };
493  f*=0.9;
494  };
495  // found no suitable length, don't draw line
496  if(line_length<1)
497  {
498  return;
499  };
500  // now calc line positions
501  wxPoint* points=new wxPoint[2*line_length+1];
502  for(size_t i=0; i<2*line_length+1; i++)
503  {
504  hugin_utils::FDiff2D p = p1 + dp*f*(((double)i - line_length) / (2.0f*line_length));
506  {
507  delete []points;
508  return;
509  };
510  points[i]=m_control->roundP(m_control->scale(m_control->applyRot(p2)));
511  };
512  //and finally draw line segment
513  dc.SetClippingRegion(wxPoint(0,0), m_control->GetBitmapSize());
514  dc.DrawLines(2*line_length+1, points);
515  dc.DestroyClippingRegion();
516  delete []points;
517 };
518 
520 {
521  return m_line && m_control->IsShowingLines();
522 }
523 
524 const bool DisplayedControlPoint::isOccupiedLabel(const wxPoint mousePos) const
525 {
526  if(IsDrawingLine())
527  {
528  return m_labelPos.Contains(mousePos) || m_labelPos2.Contains(mousePos);
529  }
530  else
531  {
532  return m_labelPos.Contains(mousePos);
533  };
534 };
535 
537 {
538  double d=m_control->invScale(3.0);
539  if(IsDrawingLine())
540  {
541  return (p.x < m_cp.x1 + d && p.x > m_cp.x1 - d && p.y < m_cp.y1 + d && p.y > m_cp.y1 - d) ||
542  (p.x < m_cp.x2 + d && p.x > m_cp.x2 - d && p.y < m_cp.y2 + d && p.y > m_cp.y2 - d);
543  }
544  else
545  {
546  if(m_mirrored)
547  {
548  return (p.x < m_cp.x2 + d && p.x > m_cp.x2 - d && p.y < m_cp.y2 + d && p.y > m_cp.y2 - d);
549  }
550  else
551  {
552  return (p.x < m_cp.x1 + d && p.x > m_cp.x1 - d && p.y < m_cp.y1 + d && p.y > m_cp.y1 - d);
553  };
554  };
555 };
556 
557 void DisplayedControlPoint::CheckSelection(const wxPoint mousePos, const hugin_utils::FDiff2D& p)
558 {
559  if(!IsDrawingLine())
560  {
561  return;
562  };
563  double d=m_control->invScale(3.0);
564  m_mirrored=m_labelPos2.Contains(mousePos) ||
565  (p.x < m_cp.x2 + d && p.x > m_cp.x2 - d && p.y < m_cp.y2 + d && p.y > m_cp.y2 - d);
566 };
567 
569 {
570  if(m_mirrored)
571  {
572  m_cp.x2=x;
573  }
574  else
575  {
576  m_cp.x1=x;
577  };
578 };
579 
581 {
582  if(m_mirrored)
583  {
584  m_cp.y2=y;
585  }
586  else
587  {
588  m_cp.y1=y;
589  };
590 };
591 
593 {
594  if(m_mirrored)
595  {
596  m_cp.x2=newPoint.x;
597  m_cp.y2=newPoint.y;
598  }
599  else
600  {
601  m_cp.x1=newPoint.x;
602  m_cp.y1=newPoint.y;
603  };
604 };
605 
607 {
608  if(m_mirrored)
609  {
610  m_cp.x2+=shift.x;
611  m_cp.y2+=shift.y;
612  }
613  else
614  {
615  m_cp.x1+=shift.x;
616  m_cp.y1+=shift.y;
617  };
618 };
619 
621 {
622  //start a new line control point
623  m_line=true;
624  m_mirrored=true;
625  m_label=_("new");
626  m_cp.image1Nr=UINT_MAX;
627  m_cp.x1=newPoint.x;
628  m_cp.y1=newPoint.y;
630  m_cp.x2=m_cp.x1;
631  m_cp.y2=m_cp.y1;
633 };
634 
636 {
638 };
639 
641 {
642  return m_cp==other.GetControlPoint() && m_mirrored == other.IsMirrored() && m_label == other.GetLabel();
643 };
644 
645 // our image control
646 
647 bool CPImageCtrl::Create(wxWindow * parent, wxWindowID id,
648  const wxPoint& pos,
649  const wxSize& size,
650  long style,
651  const wxString& name)
652 {
653  wxScrolledWindow::Create(parent, id, pos, size, style, name);
654  selectedPointNr = 0;
656  scaleFactor = 1;
657  fitToWindow = false;
658  m_showSearchArea = false;
659  m_searchRectWidth = 0;
660  m_showTemplateArea = false;
662  m_editPanel = 0;
664  m_sameImage = false;
666 
667  wxString filename;
668 
669 #if defined(__WXMSW__)
670  wxString cursorPath = huginApp::Get()->GetXRCPath() + wxT("/data/cursor_cp_pick.cur");
671  m_CPSelectCursor = new wxCursor(cursorPath, wxBITMAP_TYPE_CUR);
672 #else
673  m_CPSelectCursor = new wxCursor(wxCURSOR_CROSS);
674 #endif
675  SetCursor(*m_CPSelectCursor);
676 
677  // TODO: define custom, light background colors.
678  pointColors.push_back(wxTheColourDatabase->Find(wxT("BLUE")));
679  textColours.push_back(wxTheColourDatabase->Find(wxT("WHITE")));
680 
681  pointColors.push_back(wxTheColourDatabase->Find(wxT("GREEN")));
682  textColours.push_back(wxTheColourDatabase->Find(wxT("WHITE")));
683 
684  pointColors.push_back(wxTheColourDatabase->Find(wxT("CYAN")));
685  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
686  pointColors.push_back(wxTheColourDatabase->Find(wxT("GOLD")));
687  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
688 
689  pointColors.push_back(wxTheColourDatabase->Find(wxT("NAVY")));
690  textColours.push_back(wxTheColourDatabase->Find(wxT("WHITE")));
691 
692  pointColors.push_back(wxTheColourDatabase->Find(wxT("DARK TURQUOISE")));
693  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
694 
695  pointColors.push_back(wxTheColourDatabase->Find(wxT("SALMON")));
696  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
697 
698  pointColors.push_back(wxTheColourDatabase->Find(wxT("MAROON")));
699  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
700 
701  pointColors.push_back(wxTheColourDatabase->Find(wxT("KHAKI")));
702  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
703 
704  m_searchRectWidth = 120;
705  m_mouseInWindow = false;
706  m_forceMagnifier = false;
707  m_timer.SetOwner(this);
708  // bind event handler
709  Bind(wxEVT_SIZE, &CPImageCtrl::OnSize, this);
710  Bind(wxEVT_CHAR, &CPImageCtrl::OnKey, this);
711  Bind(wxEVT_KEY_DOWN, &CPImageCtrl::OnKeyDown, this);
712  Bind(wxEVT_LEAVE_WINDOW, &CPImageCtrl::OnMouseLeave, this);
713  Bind(wxEVT_ENTER_WINDOW, &CPImageCtrl::OnMouseEnter, this);
714  Bind(wxEVT_MOTION, &CPImageCtrl::mouseMoveEvent, this);
715  Bind(wxEVT_LEFT_DOWN, &CPImageCtrl::mousePressLMBEvent, this);
716  Bind(wxEVT_LEFT_UP, &CPImageCtrl::mouseReleaseLMBEvent, this);
717  Bind(wxEVT_RIGHT_DOWN, &CPImageCtrl::mousePressRMBEvent, this);
718  Bind(wxEVT_RIGHT_UP, &CPImageCtrl::mouseReleaseRMBEvent, this);
719  Bind(wxEVT_MIDDLE_DOWN, &CPImageCtrl::mousePressMMBEvent, this);
720  Bind(wxEVT_MIDDLE_UP, &CPImageCtrl::mouseReleaseMMBEvent, this);
721  Bind(wxEVT_TIMER, &CPImageCtrl::OnTimer, this);
722 
723  return true;
724 }
725 
727 {
728  m_editPanel = parent;
729  m_sameImage = false;
731 }
732 
734 {
735  DEBUG_TRACE("dtor");
736  this->SetCursor(wxNullCursor);
737  delete m_CPSelectCursor;
738  DEBUG_TRACE("dtor end");
739 }
740 
741 void CPImageCtrl::OnDraw(wxDC & dc)
742 {
743  wxSize vSize = GetClientSize();
744  // draw image (FIXME, redraw only visible regions.)
745  if (editState != NO_IMAGE && m_img.get()) {
746  //clear the blank rectangle to the left of the image
747  if (bitmap.GetWidth() < vSize.GetWidth()) {
748  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
749  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
750  dc.DrawRectangle(bitmap.GetWidth(), 0,
751  vSize.GetWidth() - bitmap.GetWidth(),vSize.GetHeight());
752  }
753  //clear the blank rectangle below the image
754  if (bitmap.GetHeight() < vSize.GetHeight()) {
755  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
756  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
757  dc.DrawRectangle(0, bitmap.GetHeight(),
758  vSize.GetWidth(), vSize.GetHeight() - bitmap.GetHeight());
759  }
760  dc.DrawBitmap(bitmap,0,0);
761  } else {
762  // clear the rectangle and exit
763  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
764  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
765  dc.Clear();
766  return;
767  }
768 
769  // draw known points.
770  wxRect visibleRect(GetViewStart(), vSize);
771  visibleRect.Inflate(20);
772  for(size_t i=0; i<m_points.size(); i++)
773  {
775  {
776  m_points[i].Draw(dc, visibleRect, false);
777  };
778  }
779 
780  switch(editState) {
781  case NEW_POINT_SELECTED:
782  // Boundary check
783  if ((newPoint.x < 0) || (newPoint.y < 0)) {
784  // Tried to create a point outside of the canvas. Ignore it.
785  break;
786  }
787  {
788  DisplayedControlPoint dsp(HuginBase::ControlPoint(0, newPoint.x, newPoint.y, 0, 0, 0), this, false);
789  dsp.SetLabel(_("new"));
790  dsp.Draw(dc, visibleRect, false, true);
791  }
792  if (m_showTemplateArea) {
793  dc.SetLogicalFunction(wxINVERT);
794  dc.SetPen(wxPen(wxT("RED"), 1, wxPENSTYLE_SOLID));
795  dc.SetBrush(wxBrush(wxT("WHITE"), wxBRUSHSTYLE_TRANSPARENT));
796  wxPoint upperLeft = applyRot(roundP(newPoint));
797  upperLeft = scale(upperLeft);
798 
799  int width = scale(m_templateRectWidth);
800 
801  dc.DrawRectangle(upperLeft.x-width, upperLeft.y-width, 2*width, 2*width);
802  dc.SetLogicalFunction(wxCOPY);
803  }
804 
805  break;
806  case NEW_LINE_CREATING:
807  m_selectedPoint.Draw(dc, visibleRect, false, true);
808  break;
810  m_points[selectedPointNr].Draw(dc, visibleRect, true);
811  break;
813  case NO_SELECTION:
814  case NO_IMAGE:
815  break;
816  }
817 
818  if (m_showSearchArea && m_mousePos.x != -1){
819  dc.SetLogicalFunction(wxINVERT);
820  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
821  dc.SetBrush(wxBrush(wxT("WHITE"), wxBRUSHSTYLE_TRANSPARENT));
822 
824  upperLeft = scale(upperLeft);
825  int width = scale(m_searchRectWidth);
826  DEBUG_DEBUG("drawing rect " << upperLeft << " with width " << 2*width << " orig: " << m_searchRectWidth*2 << " scale factor: " << getScaleFactor());
827 
828  dc.DrawRectangle(hugin_utils::roundi(upperLeft.x - width), hugin_utils::roundi(upperLeft.y - width), 2 * width, 2 * width);
829  dc.SetLogicalFunction(wxCOPY);
830  }
831 }
832 
834 {
835  if (m_magImgCenter == point)
836  {
837  // if point has not moved use cached image
838  return m_magImg;
839  };
840  // point has changed, we need to recalculate the magnified image
841  typedef vigra::RGBValue<vigra::UInt8> VT;
842  DEBUG_TRACE("")
843 
844  // draw magnified image
845  // width (and height) of magnifier region (output), should be odd
846  int magWidth = wxConfigBase::Get()->Read(wxT("/CPEditorPanel/MagnifierWidth"),61l);
847  int hw = magWidth/2;
848  magWidth = hw*2+1;
849 
850  wxImage img(magWidth, magWidth);
851  vigra::BasicImageView<VT> magImg((VT*)img.GetData(), magWidth,magWidth);
852  vigra::BImage maskImg(magWidth, magWidth);
854 
855  // middle pixel
856  double mx, my;
857  m_magInvTrans->transformImgCoord(mx, my, point.x, point.y);
858 
859  // apply the transform, for the small window the multithreading has too much overhead, so use only single threaded version
862  vigra::destImageRange(magImg),
863  vigra::destImage(maskImg),
864  *m_magTrans,
865  ptf,
866  vigra::Diff2D(hugin_utils::roundi(mx - hw),
867  hugin_utils::roundi(my - hw)),
869  false,
870  &progDisp,
871  true);
872 
873  // TODO: contrast enhancement
874  vigra::FindMinMax<vigra::UInt8> minmax;
875  vigra::inspectImage(vigra::srcImageRange(magImg), minmax);
876 
877  // transform to range 0...255
879  vigra::linearRangeMapping(
880  VT(minmax.min), VT(minmax.max), // src range
881  VT(0, 0, 0), VT(255, 255, 255)) // dest range
882  );
883 // vigra::transformImage(srcImageRange(magImg), destImage(magImg),
884 // vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
885 
886  // draw cursor
887  for(int x=0; x < magWidth; x++) {
888  VT p =magImg(x,hw+1);
889  vigra::UInt8 v = 0.3/255*p.red() + 0.6/255*p.green() + 0.1/255*p.blue() < 0.5 ? 255 : 0;
890  p[0] = v;
891  p[1] = v;
892  p[2] = v;
893  magImg(x,hw+1) = p;
894  p = magImg(hw+1, x);
895  v = 0.3/255*p.red() + 0.6/255*p.green() + 0.1/255*p.blue() < 0.5 ? 255 : 0;
896  p[0] = v;
897  p[1] = v;
898  p[2] = v;
899  magImg(hw+1, x) = p;
900  }
901 
902  // rotate image according to current display
903  switch (m_imgRotation) {
904  case ROT90:
905  img = img.Rotate90(true);
906  break;
907  case ROT180:
908  img = img.Rotate180();
909  break;
910  case ROT270:
911  img = img.Rotate90(false);
912  break;
913  default:
914  break;
915  };
916 
917  m_magImg = wxBitmap(img);
918  m_magImgCenter = point;
919  return m_magImg;
920 }
921 
923 {
924  return wxSize(imageSize.GetWidth(),imageSize.GetHeight());
925 }
926 
927 
928 void CPImageCtrl::setImage(const std::string & file, ImageRotation imgRot)
929 {
930  DEBUG_TRACE("setting Image " << file);
931  imageFilename = file;
932  m_sameImage=false;
934  wxString fn(imageFilename.c_str(),HUGIN_CONV_FILENAME);
935  if (wxFileName::FileExists(fn)) {
936  m_imgRotation = imgRot;
937  m_img = ImageCache::getInstance().getImageIfAvailable(imageFilename);
939  if (m_img.get()) {
940  rescaleImage();
941  } else {
942  // load the image in the background.
943  m_imgRequest = ImageCache::getInstance().requestAsyncImage(imageFilename);
944  m_imgRequest->ready.push_back(
945  std::bind(&CPImageCtrl::OnImageLoaded, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)
946  );
947  // With m_img.get() 0, everything will act as normal except drawing.
948  }
949  } else {
951  bitmap = wxBitmap();
952  // delete the image (release shared_ptr)
953  // create an empty image.
954  m_img = ImageCache::EntryPtr(new ImageCache::Entry);
955  }
956 }
957 
959 {
960  m_firstTrans=firstTrans;
961  m_firstInvTrans=firstInvTrans;
962  m_secondInvTrans=secondInvTrans;
963 };
964 
966 {
967  m_magTrans = magTrans;
968  m_magInvTrans = magInvTrans;
969 }
970 
971 void CPImageCtrl::setSameImage(bool sameImage)
972 {
973  m_sameImage=sameImage;
974 };
975 
976 void CPImageCtrl::OnImageLoaded(ImageCache::EntryPtr entry, std::string filename, bool load_small)
977 {
978  // check we are still displaying this image
979  if (imageFilename == filename)
980  {
981  m_img = entry;
982  rescaleImage();
983  }
984 }
985 
987 {
988  if (editState == NO_IMAGE || !m_img.get()) {
989  return;
990  }
991  wxImage img = imageCacheEntry2wxImage(m_img);
992  if (img.GetWidth() == 0) {
993  return;
994  }
995  imageSize = wxSize(img.GetWidth(), img.GetHeight());
997  if (fitToWindow) {
999  }
1000  DEBUG_DEBUG("src image size "
1001  << imageSize.GetHeight() << "x" << imageSize.GetWidth());
1002  if (getScaleFactor() == 1.0) {
1003  //the icc correction would work on the original cached image file
1004  //therefore we need to create a copy to work on it
1005  img = img.Copy();
1006  }
1007  else
1008  {
1009  // rescale image
1010  imageSize.SetWidth(scale(imageSize.GetWidth()));
1011  imageSize.SetHeight(scale(imageSize.GetHeight()));
1012  DEBUG_DEBUG("rescaling to " << imageSize.GetWidth() << "x"
1013  << imageSize.GetHeight());
1014  wxImageResizeQuality resizeQuality = wxIMAGE_QUALITY_NORMAL;
1015  if (std::max(img.GetWidth(), img.GetHeight()) > (ULONG_MAX >> 16))
1016  {
1017  // wxIMAGE_QUALITY_NORMAL resizes the image with ResampleNearest
1018  // this algorithm works only if image dimensions are smaller then
1019  // ULONG_MAX >> 16 (actual size of unsigned long differ from system
1020  // to system)
1021  resizeQuality = wxIMAGE_QUALITY_BOX_AVERAGE;
1022  };
1023  img = img.Scale(imageSize.GetWidth(), imageSize.GetHeight(), resizeQuality);
1024  };
1025  // need to rotate full image. warning. this can be very memory intensive
1026  if (m_imgRotation != ROT0)
1027  {
1028  switch (m_imgRotation)
1029  {
1030  case ROT90:
1031  img = img.Rotate90(true);
1032  break;
1033  case ROT180:
1034  img = img.Rotate180();
1035  break;
1036  case ROT270:
1037  img = img.Rotate90(false);
1038  break;
1039  default:
1040  break;
1041  };
1042  };
1043  // do color correction only if input image has icc profile or if we found a monitor profile
1044  if (!m_img->iccProfile->empty() || huginApp::Get()->HasMonitorProfile())
1045  {
1047  };
1048  bitmap = wxBitmap(img);
1049 
1050  if (m_imgRotation == ROT90 || m_imgRotation == ROT270) {
1051  SetVirtualSize(imageSize.GetHeight(), imageSize.GetWidth());
1052  } else {
1053  SetVirtualSize(imageSize.GetWidth(), imageSize.GetHeight());
1054  }
1055  SetScrollRate(1,1);
1056  Refresh(FALSE);
1057 }
1058 
1059 void CPImageCtrl::setCtrlPoint(const HuginBase::ControlPoint& cp, const bool mirrored)
1060 {
1061  DisplayedControlPoint dcp(cp, this, mirrored);
1062  dcp.SetColour(pointColors[m_points.size() % pointColors.size()], textColours[m_points.size() % textColours.size()]);
1063  dcp.SetLabel(wxString::Format(wxT("%lu"), (unsigned long int)m_points.size()));
1064  m_points.push_back(dcp);
1065 }
1066 
1068 {
1069  m_points.clear();
1071  {
1073  };
1074  selectedPointNr = UINT_MAX;
1075 };
1076 
1078 {
1079  DEBUG_TRACE("clearNewPoint");
1080  if (editState != NO_IMAGE) {
1082  }
1083 }
1084 
1085 
1086 void CPImageCtrl::selectPoint(unsigned int nr, bool scrollTo)
1087 {
1088  DEBUG_TRACE("nr: " << nr);
1089  if (nr < m_points.size()) {
1090  selectedPointNr = nr;
1092  if (scrollTo)
1093  {
1094  // scroll to center only when requested
1095  showPosition(m_points[nr].GetPos());
1096  };
1097  update();
1098  } else {
1099  DEBUG_DEBUG("trying to select invalid point nr: " << nr << ". Nr of points: " << m_points.size());
1100  }
1101 }
1102 
1104 {
1105  DEBUG_TRACE("deselecting points");
1108  }
1109  // update view
1110  update();
1111 }
1112 
1114 {
1115  DEBUG_DEBUG("x: " << point.x << " y: " << point.y);
1116  // transform and scale the co-ordinate to the screen.
1117  point = applyRot(point);
1118  point = scale(point);
1119  int x = hugin_utils::roundi(point.x);
1120  int y = hugin_utils::roundi(point.y);
1121 
1122  wxSize sz = GetClientSize();
1123  int scrollx = x - sz.GetWidth()/2;
1124  int scrolly = y - sz.GetHeight()/2;
1125  Scroll(scrollx, scrolly);
1126  if (warpPointer) {
1127  int sx,sy;
1128  GetViewStart(&sx, &sy);
1129  DEBUG_DEBUG("relative coordinages: " << x-sx << "," << y-sy);
1130  WarpPointer(x-sx,y-sy);
1131  }
1132 }
1133 
1134 CPImageCtrl::EditorState CPImageCtrl::isOccupied(wxPoint mousePos, const hugin_utils::FDiff2D &p, unsigned int & pointNr) const
1135 {
1136  // check if mouse is hovering over a label
1137  if(!m_points.empty())
1138  {
1139  for(int i=m_points.size()-1; i>=0; i--)
1140  {
1141  if(m_points[i].isOccupiedLabel(mousePos))
1142  {
1143  pointNr = i;
1144  return KNOWN_POINT_SELECTED;
1145  }
1146  };
1147  // check if mouse is over a known point
1148  for(std::vector<DisplayedControlPoint>::const_iterator it=m_points.begin(); it!=m_points.end(); ++it)
1149  {
1150  if(it->isOccupiedPos(p))
1151  {
1152  pointNr = it - m_points.begin();
1153  return KNOWN_POINT_SELECTED;
1154  }
1155  };
1156  };
1157 
1158  return NEW_POINT_SELECTED;
1159 }
1160 
1162 {
1163  wxClientDC dc(this);
1164  PrepareDC(dc);
1165  wxDCOverlay overlaydc(m_overlay, &dc);
1166  overlaydc.Clear();
1167  dc.SetPen(wxPen(*wxWHITE, 2, wxPENSTYLE_LONG_DASH));
1168  dc.SetBrush(*wxTRANSPARENT_BRUSH);
1169  wxPoint p1=roundP(scale(applyRot(pos1)));
1170  wxPoint p2=roundP(scale(applyRot(pos2)));
1171  dc.DrawRectangle(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
1172 };
1173 
1174 void CPImageCtrl::mouseMoveEvent(wxMouseEvent& mouse)
1175 {
1176  if (!m_img.get()) return; // ignore events if no image loaded.
1177  wxPoint unScrolledMousePos;
1178  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1179  &unScrolledMousePos.x, & unScrolledMousePos.y);
1180  hugin_utils::FDiff2D mpos(unScrolledMousePos.x, unScrolledMousePos.y);
1181  bool doUpdate = false;
1182  mpos = applyRotInv(invScale(mpos));
1183  // if mouseclick is out of image, ignore
1184  if ((mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) && editState!=SELECT_DELETE_REGION)
1185  {
1186  return;
1187  }
1188 
1189 // DEBUG_DEBUG(" pos:" << mpos.x << ", " << mpos.y);
1190  // only if the shift key is not pressed.
1191  if (mouse.LeftIsDown() && ! mouse.ShiftDown()) {
1192  switch(editState) {
1193  case NO_SELECTION:
1194  DEBUG_DEBUG("mouse down movement without selection, in NO_SELECTION state!");
1195  break;
1196  case KNOWN_POINT_SELECTED:
1197  if (mpos.x >= 0 && mpos.x <= m_realSize.GetWidth()){
1198  m_points[selectedPointNr].UpdateControlPointX(mpos.x);
1199  } else if (mpos.x < 0) {
1200  m_points[selectedPointNr].UpdateControlPointX(0);
1201  } else if (mpos.x > m_realSize.GetWidth()) {
1202  m_points[selectedPointNr].UpdateControlPointX(m_realSize.GetWidth());
1203  }
1204 
1205  if (mpos.y >= 0 && mpos.y <= m_realSize.GetHeight()){
1206  m_points[selectedPointNr].UpdateControlPointY(mpos.y);
1207  } else if (mpos.y < 0) {
1208  m_points[selectedPointNr].UpdateControlPointY(0);
1209  } else if (mpos.y > m_realSize.GetHeight()) {
1210  m_points[selectedPointNr].UpdateControlPointY(m_realSize.GetHeight());
1211  }
1212  // emit a notify event here.
1213  //
1214  //emit(pointMoved(selectedPointNr, points[selectedPointNr]));
1215  // do more intelligent updating here?
1216  doUpdate = true;
1217  break;
1218  // not possible.
1219  case NEW_POINT_SELECTED:
1220  DEBUG_DEBUG("WARNING: mouse move in new point state")
1221  newPoint = mpos;
1222  doUpdate = true;
1223  break;
1224  case NEW_LINE_CREATING:
1226  doUpdate = true;
1227  break;
1228  case SELECT_DELETE_REGION:
1229  case NO_IMAGE:
1230  break;
1231  }
1232  }
1233 
1234  if ((mouse.MiddleIsDown() || mouse.ShiftDown() || mouse.m_controlDown ) && editState!=SELECT_DELETE_REGION) {
1235  // scrolling with the mouse
1236  if (m_mouseScrollPos !=mouse.GetPosition()) {
1237  wxPoint delta = mouse.GetPosition() - m_mouseScrollPos;
1238  if (mouse.MiddleIsDown())
1239  {
1240  // invert scroll direction for middle mouse click (touchpad like scrolling)
1241  delta = -delta;
1242  };
1243  // scrolling is done later
1244  if (mouse.ShiftDown()) {
1245  // emit scroll event, so that other window can be scrolled
1246  // as well.
1247  CPEvent e(this, CPEvent::SCROLLED, hugin_utils::FDiff2D(delta.x, delta.y));
1248  emit(e);
1249  } else {
1250  // scroll only our window
1251  ScrollDelta(delta);
1252  }
1253  m_mouseScrollPos = mouse.GetPosition();
1254  }
1255  }
1256 
1257  if(mouse.RightIsDown() && editState==SELECT_DELETE_REGION)
1258  {
1259  //update selection rectangle
1261  }
1262 // DEBUG_DEBUG("ImageDisplay: mouse move, state: " << editState);
1263 
1264  // draw a rectangle
1265  if (m_showSearchArea) {
1266  doUpdate = true;
1267  }
1268 
1269  unsigned int selPointNr;
1270  if (isOccupied(unScrolledMousePos, mpos, selPointNr) == KNOWN_POINT_SELECTED ) {
1271  SetCursor(wxCursor(wxCURSOR_ARROW));
1272  } else {
1273  SetCursor(*m_CPSelectCursor);
1274  }
1275 
1276  m_mousePos = mpos;
1277  // repaint
1278  if (doUpdate) {
1279  update();
1280  }
1281 }
1282 
1283 
1284 void CPImageCtrl::mousePressLMBEvent(wxMouseEvent& mouse)
1285 {
1286  DEBUG_DEBUG("LEFT MOUSE DOWN");
1287  if (!m_img.get()) return; // ignore events if no image loaded.
1288  //ignore left mouse button if selecting region with right mouse button
1290  return;
1291  wxPoint unScrolledMousePos;
1292  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1293  &unScrolledMousePos.x, & unScrolledMousePos.y);
1294  hugin_utils::FDiff2D mpos(unScrolledMousePos.x, unScrolledMousePos.y);
1295  mpos = applyRotInv(invScale(mpos));
1296  DEBUG_DEBUG("mousePressEvent, pos:" << mpos.x
1297  << ", " << mpos.y);
1298  // if mouseclick is out of image, ignore
1299  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) {
1300  return;
1301  }
1302  unsigned int selPointNr = 0;
1303  EditorState clickState = isOccupied(unScrolledMousePos, mpos, selPointNr);
1304  if (mouse.LeftDown() && editState != NO_IMAGE
1305  && mpos.x < m_realSize.x && mpos.y < m_realSize.y)
1306  {
1307  // we can always select a new point
1308  if (clickState == KNOWN_POINT_SELECTED) {
1309  DEBUG_DEBUG("click on point: " << selPointNr);
1310  selectedPointNr = selPointNr;
1311  m_points[selectedPointNr].CheckSelection(unScrolledMousePos, mpos);
1313  editState = clickState;
1314  // notify parent and therefore other CPImageCtrl to select the clicked point
1315  CPEvent e( this, selectedPointNr);
1316  // stop timer so that magnifier is always displayed when moving cp and not hidden by timer
1317  m_timer.Stop();
1318  m_forceMagnifier = true;
1319  emit(e);
1320  } else if (clickState == NEW_POINT_SELECTED) {
1321  DEBUG_DEBUG("click on new space, select new point");
1322  if(m_sameImage && mouse.AltDown())
1323  {
1327  }
1328  else
1329  {
1331  };
1332  newPoint = mpos;
1333  } else {
1334  DEBUG_ERROR("invalid state " << clickState << " on mouse down");
1335  }
1336 // DEBUG_DEBUG("ImageDisplay: mouse down, state change: " << oldstate
1337 // << " -> " << editState);
1338  }
1339  m_mousePos = mpos;
1340 }
1341 
1342 void CPImageCtrl::OnTimer(wxTimerEvent & e)
1343 {
1344  if (!m_img.get()) return; // ignore events if no image loaded.
1345  m_forceMagnifier = false;
1346  update();
1347 }
1348 
1349 void CPImageCtrl::OnScrollWin(wxScrollWinEvent& e)
1350 {
1351  // repaint image, so that labels and magnifier are updated
1352  update();
1353  e.Skip();
1354 }
1355 
1356 void CPImageCtrl::mouseReleaseLMBEvent(wxMouseEvent& mouse)
1357 {
1358  DEBUG_DEBUG("LEFT MOUSE UP");
1359  if (!m_img.get()) return; // ignore events if no image loaded.
1360  //ignore left mouse button if selecting region with right mouse button
1362  return;
1363 
1364  m_timer.Start(2000, true);
1365 
1366  wxPoint mpos_;
1367  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1368  &mpos_.x, & mpos_.y);
1369  hugin_utils::FDiff2D mpos(mpos_.x, mpos_.y);
1370  mpos = applyRotInv(invScale(mpos));
1371  DEBUG_DEBUG("mouseReleaseEvent, pos:" << mpos.x
1372  << ", " << mpos.y);
1373  // if mouseclick is out of image, ignore
1374  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) {
1375  return;
1376  }
1377 // EditorState oldState = editState;
1378  if (mouse.LeftUp()) {
1379  switch(editState) {
1380  case NO_SELECTION:
1381  DEBUG_DEBUG("mouse release without selection");
1382  break;
1383  case KNOWN_POINT_SELECTED:
1384  {
1385  DEBUG_DEBUG("mouse release with known point " << selectedPointNr);
1386  // scroll so that currently selected point is centered
1388  if (! (m_selectedPoint == m_points[selectedPointNr]) ) {
1389  CPEvent e( this, CPEvent::POINT_CHANGED, selectedPointNr, m_points[selectedPointNr].GetControlPoint());
1390  emit(e);
1391  }
1392  break;
1393  }
1394  case NEW_POINT_SELECTED:
1395  {
1396  DEBUG_DEBUG("new Point changed (event fire): x:" << mpos.x << " y:" << mpos.y);
1397  // fire the wxWin event
1398  CPEvent e( this, newPoint);
1399  emit(e);
1400  break;
1401  }
1402  case NEW_LINE_CREATING:
1403  {
1404  //notify parent
1406  emit(e);
1407  break;
1408  }
1409  case SELECT_DELETE_REGION:
1410  case NO_IMAGE:
1411  break;
1412 
1413  }
1414 // DEBUG_DEBUG("ImageDisplay: mouse release, state change: " << oldState
1415 // << " -> " << editState);
1416  }
1417 
1418 }
1419 
1420 
1421 void CPImageCtrl::mouseReleaseMMBEvent(wxMouseEvent& mouse)
1422 {
1423  DEBUG_DEBUG("middle mouse button released, leaving scroll mode")
1424 // SetCursor(wxCursor(wxCURSOR_BULLSEYE));
1425 }
1426 
1427 
1428 void CPImageCtrl::mousePressMMBEvent(wxMouseEvent& mouse)
1429 {
1430  DEBUG_DEBUG("middle mouse button pressed, entering scroll mode")
1431  if (!m_img.get()) return; // ignore events if no image loaded.
1432  m_mouseScrollPos = mouse.GetPosition();
1433 // SetCursor(wxCursor(wxCURSOR_HAND));
1434 }
1435 
1436 void CPImageCtrl::mousePressRMBEvent(wxMouseEvent& mouse)
1437 {
1438  //ignore event if no image loaded
1439  if(!m_img.get())
1440  return;
1441  wxPoint mpos_;
1442  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y, &mpos_.x, & mpos_.y);
1443  hugin_utils::FDiff2D mpos(mpos_.x, mpos_.y);
1444  mpos = applyRotInv(invScale(mpos));
1445  // if mouseclick is out of image, ignore
1446  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight())
1447  {
1448  return;
1449  }
1451  {
1452  rectStartPos=mpos;
1454  };
1455 };
1456 
1457 void CPImageCtrl::mouseReleaseRMBEvent(wxMouseEvent& mouse)
1458 {
1459  if (!m_img.get()) return; // ignore events if no image loaded.
1460  wxPoint mpos_;
1461  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1462  &mpos_.x, & mpos_.y);
1463  hugin_utils::FDiff2D mpos(mpos_.x, mpos_.y);
1464  mpos = applyRotInv(invScale(mpos));
1465  DEBUG_DEBUG("mouseReleaseEvent, pos:" << mpos.x
1466  << ", " << mpos.y);
1467 
1468  if (mouse.RightUp())
1469  {
1471  {
1472  // clear overlay
1473  m_overlay.Reset();
1475  CPEvent e(this,rectStartPos,mpos);
1476  emit(e);
1477  }
1478  else
1479  {
1480  // if mouseclick is out of image, ignore
1481  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) {
1482  return;
1483  }
1484  // set right up event
1485  DEBUG_DEBUG("Emitting right click (rmb release)");
1486  CPEvent e(this, CPEvent::RIGHT_CLICK, mpos);
1487  emit(e);
1488  }
1489  }
1490 }
1491 
1493 {
1494  DEBUG_TRACE("edit state:" << editState);
1495  wxClientDC dc(this);
1496  PrepareDC(dc);
1497  OnDraw(dc);
1498 }
1499 
1501 {
1502  if ( ProcessEvent( ev ) == FALSE ) {
1503  wxLogWarning( _("Could not process event!") );
1504  return false;
1505  } else {
1506  return true;
1507  }
1508 }
1509 
1510 void CPImageCtrl::setScale(double factor)
1511 {
1512  if (factor == 0) {
1513  fitToWindow = true;
1514  factor = calcAutoScaleFactor(imageSize);
1515  } else {
1516  fitToWindow = false;
1517  }
1518  DEBUG_DEBUG("new scale factor:" << factor);
1519  // update if factor changed
1520  if (factor != scaleFactor) {
1521  scaleFactor = factor;
1522  // keep existing scale focussed.
1523  rescaleImage();
1524  }
1525 }
1526 
1528 {
1529  // TODO correctly autoscale rotated iamges
1530  int w = size.GetWidth();
1531  int h = size.GetHeight();
1532  if (m_imgRotation == ROT90 || m_imgRotation == ROT270) {
1533  int t = w;
1534  w = h;
1535  h = t;
1536  }
1537 
1538 // wxSize csize = GetClientSize();
1539  wxSize csize = GetSize();
1540  DEBUG_DEBUG("csize: " << csize.GetWidth() << "x" << csize.GetHeight() << "image: " << w << "x" << h);
1541  double s1 = (double)csize.GetWidth()/w;
1542  double s2 = (double)csize.GetHeight()/h;
1543  DEBUG_DEBUG("s1: " << s1 << " s2:" << s2);
1544  return s1 < s2 ? s1 : s2;
1545 }
1546 
1548 {
1549  return scaleFactor;
1550 }
1551 
1552 void CPImageCtrl::OnSize(wxSizeEvent &e)
1553 {
1554  DEBUG_TRACE("size: " << e.GetSize().GetWidth() << "x" << e.GetSize().GetHeight());
1555  // rescale bitmap if needed.
1556  if (imageFilename != "") {
1557  if (fitToWindow) {
1558  setScale(0);
1559  }
1560  }
1561 }
1562 
1563 void CPImageCtrl::OnKey(wxKeyEvent & e)
1564 {
1565  if (!m_img.get()) return; // ignore events if no image loaded.
1566  DEBUG_TRACE(" OnKey, key:" << e.m_keyCode);
1567  wxPoint delta(0,0);
1568  // check for cursor keys, if control is not pressed
1569  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_LEFT ) delta.x = -1;
1570  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_RIGHT ) delta.x = 1;
1571  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_UP ) delta.y = -1;
1572  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_DOWN ) delta.y = 1;
1573  if ( (delta.x != 0 || delta.y != 0 ) && (e.ShiftDown() || e.CmdDown())) {
1574  // move to the left
1575  double speed = (double) GetClientSize().GetWidth()/10;
1576  delta.x = (int) (delta.x * speed);
1577  delta.y = (int) (delta.y * speed);
1578  if (e.ShiftDown()) {
1579  // emit scroll event, so that other window can be scrolled
1580  // as well.
1581  CPEvent e(this, CPEvent::SCROLLED, hugin_utils::FDiff2D(delta.x, delta.y));
1582  emit(e);
1583  } else if (e.CmdDown()) {
1584  ScrollDelta(delta);
1585  }
1586  } else if (delta.x != 0 || delta.y != 0 ) {
1587 
1588  hugin_utils::FDiff2D shift(delta.x/3.0, delta.y/3.0);
1589  // rotate shift according to current display
1590  double t;
1591  switch (m_imgRotation) {
1592  case ROT90:
1593  t = shift.x;
1594  shift.x = shift.y;
1595  shift.y = -t;
1596  break;
1597  case ROT180:
1598  shift.x = -shift.x;
1599  shift.y = -shift.y;
1600  break;
1601  case ROT270:
1602  t = shift.x;
1603  shift.x = -shift.y;
1604  shift.y = t;
1605  default:
1606  break;
1607  }
1608  // move control point by half a pixel, if a point is selected
1609  if (editState == KNOWN_POINT_SELECTED ) {
1611  updatedCp.ShiftControlPoint(shift);
1613  emit(e);
1614  m_forceMagnifier = true;
1615  m_timer.Stop();
1616  m_timer.Start(2000, true);
1617  } else if (editState == NEW_POINT_SELECTED) {
1618  newPoint = newPoint + shift;
1619  // update display.
1620  update();
1621  }
1622 
1623  }
1624  else if (e.m_keyCode == 'a') {
1625  DEBUG_DEBUG("adding point with a key, faking right click");
1626  // faking right mouse button with "a"
1627  // set right up event
1629  emit(ev);
1630  }
1631  else if (e.m_keyCode==WXK_ESCAPE) {
1632  CPEvent ev(this, CPEvent::CANCELED);
1633  emit(ev);
1634  } else {
1635  // forward some keys...
1636  bool forward = false;
1637  switch (e.GetKeyCode())
1638  {
1639  case 'g':
1640  case '0':
1641  case '1':
1642  case '2':
1643  case 'f':
1644  case WXK_RIGHT:
1645  case WXK_LEFT:
1646  case WXK_UP:
1647  case WXK_DOWN:
1648  case WXK_DELETE:
1649  forward = true;
1650  break;
1651  default:
1652  break;
1653  }
1654 
1655  if (forward) {
1656  // dangelo: I don't understand why some keys are forwarded and others are not..
1657  // Delete is forwared under wxGTK, and g not..
1658  // wxWidgets 2.6.1 using gtk 2 doesn't set the event object
1659  // properly.. do it here by hand
1660  e.SetEventObject(this);
1661  DEBUG_DEBUG("forwarding key " << e.GetKeyCode()
1662  << " origin: id:" << e.GetId() << " obj: "
1663  << e.GetEventObject());
1664  // forward all keys to our parent
1665  //GetParent()->GetEventHandler()->ProcessEvent(e);
1666  m_editPanel->GetEventHandler()->ProcessEvent(e);
1667  } else {
1668  e.Skip();
1669  }
1670  }
1671 }
1672 
1673 void CPImageCtrl::OnKeyDown(wxKeyEvent & e)
1674 {
1675  DEBUG_TRACE("key:" << e.m_keyCode);
1676  if (!m_img.get()) return; // ignore events if no image loaded.
1677  if (e.m_keyCode == WXK_SHIFT || e.m_keyCode == WXK_CONTROL) {
1678  DEBUG_DEBUG("shift or control down, reseting scoll position");
1679  m_mouseScrollPos = e.GetPosition();
1680  }
1681  e.Skip();
1682 }
1683 
1684 void CPImageCtrl::OnMouseLeave(wxMouseEvent & e)
1685 {
1686  DEBUG_TRACE("MOUSE LEAVE");
1688  m_mouseInWindow = false;
1689  update();
1690 }
1691 
1692 void CPImageCtrl::OnMouseEnter(wxMouseEvent & e)
1693 {
1694  if (huginApp::Get()->getMainFrame()->IsActive())
1695  {
1696  DEBUG_TRACE("MOUSE Enter, setting focus");
1697  m_mouseInWindow = true;
1698  SetFocus();
1699  update();
1700  };
1701 }
1702 
1704 {
1705  // only possible if a new point is actually selected
1706  // DEBUG_ASSERT(editState == NEW_POINT_SELECTED);
1707  return newPoint;
1708 }
1709 
1711 {
1712  DEBUG_DEBUG("setting new point " << p.x << "," << p.y);
1713  // should we need to check for some precondition?
1714  newPoint = p;
1716 
1717  // show new point.
1718  showPosition(p);
1719 
1720  // we do not send an event, since CPEditorPanel
1721  // caused the change.. so it doesn't need to filter
1722  // out its own change messages.
1723 }
1724 
1726 {
1727  m_showSearchArea = show;
1728  if (show)
1729  {
1730  int templSearchAreaPercent = wxConfigBase::Get()->Read(wxT("/Finetune/SearchAreaPercent"), HUGIN_FT_SEARCH_AREA_PERCENT);
1731  m_searchRectWidth = (m_realSize.GetWidth() * templSearchAreaPercent) / 200;
1732  DEBUG_DEBUG("Setting new search area: w in %:" << templSearchAreaPercent << " bitmap width: " << bitmap.GetWidth() << " resulting size: " << m_searchRectWidth);
1734  }
1735 }
1736 
1738 {
1739  m_showTemplateArea = show;
1740  if (show)
1741  {
1742  m_templateRectWidth = wxConfigBase::Get()->Read(wxT("/Finetune/TemplateSize"),HUGIN_FT_TEMPLATE_SIZE) / 2;
1743  }
1744 }
1745 
1746 wxPoint CPImageCtrl::MaxScrollDelta(wxPoint delta)
1747 {
1748  int x,y;
1749  GetViewStart( &x, &y );
1750 
1751  wxSize winSize = GetClientSize();
1752  wxSize imgSize;
1753  imgSize.x = bitmap.GetWidth();
1754  imgSize.y = bitmap.GetHeight();
1755  // check for top and left border
1756  if (x + delta.x < 0) {
1757  delta.x = -x;
1758  }
1759  if (y + delta.y < 0) {
1760  delta.y = -y;
1761  }
1762  // check for right and bottom border
1763  int right = x + delta.x + winSize.x ;
1764  if (right > imgSize.x) {
1765  delta.x = imgSize.x - right;
1766  if (delta.x < 0) {
1767  delta.x = 0;
1768  }
1769  }
1770  int bottom = y + delta.y + winSize.y ;
1771  if (bottom > imgSize.y) {
1772  delta.y = imgSize.y - bottom;
1773  if (delta.y < 0) {
1774  delta.y = 0;
1775  }
1776  }
1777  return delta;
1778 }
1779 
1780 void CPImageCtrl::ScrollDelta(const wxPoint & delta)
1781 {
1782  // TODO: adjust
1783  if (delta.x == 0 && delta.y == 0) {
1784  return;
1785  }
1786  int x,y;
1787  GetViewStart( &x, &y );
1788  x = x + delta.x;
1789  y = y + delta.y;
1790  if (x<0) x = 0;
1791  if (y<0) y = 0;
1792  Scroll( x, y);
1793 #ifdef __WXMSW__
1794  // repaint image, so that labels and magnifier are updated
1795  // only needed on Windows, on wxGTK this is handled by the
1796  // underlying control
1797  update();
1798 #endif
1799 }
1800 
1801 const wxSize CPImageCtrl::GetBitmapSize() const
1802 {
1803  return bitmap.GetSize();
1804 };
1805 
1807 {
1808  return m_img->get8BitImage();
1809 };
1810 
1811 void CPImageCtrl::ShowLines(bool isShown)
1812 {
1813  m_showLines = isShown;
1814 }
1815 
1817 {
1818  return m_showLines;
1819 }
1820 
1821 IMPLEMENT_DYNAMIC_CLASS(CPImageCtrl, wxScrolledWindow)
1822 
1824  : wxXmlResourceHandler()
1825 {
1826  AddWindowStyles();
1827 }
1828 
1830 {
1831  XRC_MAKE_INSTANCE(cp, CPImageCtrl)
1832 
1833  cp->Create(m_parentAsWindow,
1834  GetID(),
1835  GetPosition(), GetSize(),
1836  GetStyle(wxT("style")),
1837  GetName());
1838 
1839  SetupWindow( cp);
1840 
1841  return cp;
1842 }
1843 
1845 {
1846  return IsOfClass(node, wxT("CPImageCtrl"));
1847 }
1848 
1849 IMPLEMENT_DYNAMIC_CLASS(CPImageCtrlXmlHandler, wxXmlResourceHandler)
wxDEFINE_EVENT(EVT_QUEUE_PROGRESS, wxCommandEvent)
int pointNr
Definition: CPImageCtrl.h:88
int m_templateRectWidth
Definition: CPImageCtrl.h:510
void ScrollDelta(const wxPoint &delta)
scroll the window by delta pixels
implementation of huginApp Class
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
CPEventMode mode
Definition: CPImageCtrl.h:82
Dummy progress display, without output.
double calcAutoScaleFactor(wxSize size)
calculate new scale factor for this image
wxColour m_pointColour
colour of the point
Definition: CPImageCtrl.h:153
HuginBase::PTools::Transform * getFirstInvTrans() const
Definition: CPImageCtrl.h:250
DisplayedControlPoint()
default constructor
Definition: CPImageCtrl.h:98
int scale(int x) const
Definition: CPImageCtrl.h:319
wxSize DoGetBestSize() const
int m_searchRectWidth
Definition: CPImageCtrl.h:504
int invScale(int x) const
Definition: CPImageCtrl.h:341
wxSize imageSize
Definition: CPImageCtrl.h:457
int roundi(T x)
Definition: hugin_math.h:73
void setNewPoint(const hugin_utils::FDiff2D &p)
set new point to a specific point
ImageRotation m_imgRotation
Definition: CPImageCtrl.h:518
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
#define HUGIN_FT_SEARCH_AREA_PERCENT
hugin_utils::FDiff2D GetPos() const
returns selected position
void deselect()
remove selection.
void SetColour(wxColour pointColour, wxColour textColour)
set colours for drawing control points
void OnKeyDown(wxKeyEvent &e)
double getScaleFactor() const
get scale factor (calculates factor when fit to window is active)
ImageCache::RequestPtr m_imgRequest
Definition: CPImageCtrl.h:521
const bool GetForceMagnifier() const
Definition: CPImageCtrl.h:415
control point editor panel.
Definition: CPEditorPanel.h:64
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
bool operator==(const DisplayedControlPoint other)
compare operator
wxBitmap & GetMagBitmap(hugin_utils::FDiff2D point)
draw the magnified view of a selected control point
void Draw(wxDC &dc, const wxRect &visibleRect, bool selected, bool newPoint=false)
draw the control points to the given device context
const bool IsMirrored() const
return true, if cp is used with mirrored coordinates by current CPImageCtrl
Definition: CPImageCtrl.h:118
#define DEBUG_TRACE(msg)
Definition: utils.h:67
virtual wxEvent * Clone() const
wxBitmap bitmap
Definition: CPImageCtrl.h:454
void selectPoint(unsigned int, bool scrollTo=true)
select a point for usage
Events to notify about new point / region / point change.
Definition: CPImageCtrl.h:40
void mousePressLMBEvent(wxMouseEvent &mouse)
const cmsHPROFILE GetMonitorProfile() const
returns the monitor profile, if no monitor profile was found the sRGB profile is used instead ...
Definition: huginApp.h:129
bool m_sameImage
true, if in control point tab the same image is selected 2 times in this case a special treatment for...
Definition: CPImageCtrl.h:481
void DrawSelectionRectangle(hugin_utils::FDiff2D pos1, hugin_utils::FDiff2D pos2)
hugin_utils::FDiff2D m_magImgCenter
Definition: CPImageCtrl.h:464
bool m_forceMagnifier
Definition: CPImageCtrl.h:524
double scaleFactor
Definition: CPImageCtrl.h:500
include file for the hugin project
bool m_showLines
Definition: CPImageCtrl.h:466
wxBitmap m_magImg
Definition: CPImageCtrl.h:463
helper class to display and manipulate cp in cp tab
Definition: CPImageCtrl.h:94
brief description.
Definition: CPImageCtrl.h:169
EditorState isOccupied(wxPoint mousePos, const hugin_utils::FDiff2D &point, unsigned int &pointNr) const
check if p is over a known point, if it is, pointNr contains the point
EditorState
state machine for selection process:
Definition: CPImageCtrl.h:220
represents a control point
Definition: ControlPoint.h:38
wxCursor * m_CPSelectCursor
Definition: CPImageCtrl.h:470
void mousePressRMBEvent(wxMouseEvent &mouse)
wxPoint m_mouseScrollPos
Definition: CPImageCtrl.h:507
void mouseMoveEvent(wxMouseEvent &mouse)
void DrawLineSegment(wxDC &dc)
draw line control point over different images
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:645
ImageCache::EntryPtr m_img
Definition: CPImageCtrl.h:520
const wxSize GetRealImageSize() const
return the real size of the image in the control
Definition: CPImageCtrl.h:421
bool m_mirrored
is first or second image in cp used
Definition: CPImageCtrl.h:149
cubic interpolation
void OnImageLoaded(ImageCache::EntryPtr entry, std::string filename, bool load_small)
~CPImageCtrl()
dtor.
HuginBase::ImageCache::ImageCacheRGB8Ptr GetImg()
get pointer to image, for DisplayedControlPoint
void SetControl(CPImageCtrl *control)
remember the control, where the information should be drawn
void UpdateControlPointY(double y)
update y coordinate of selected cp coordinate
const bool isOccupiedLabel(const wxPoint mousePos) const
check if given point is over label of cp, using screen coordinates
const bool GetMouseInWindow() const
Definition: CPImageCtrl.h:414
void mouseReleaseLMBEvent(wxMouseEvent &mouse)
std::vector< DisplayedControlPoint > m_points
Definition: CPImageCtrl.h:468
void clearNewPoint()
clear new point
std::string imageFilename
Definition: CPImageCtrl.h:455
void OnMouseLeave(wxMouseEvent &e)
double getScale()
return scale factor, 0 for autoscale
Definition: CPImageCtrl.h:289
bool m_showTemplateArea
Definition: CPImageCtrl.h:509
CPImageCtrl * m_control
pointer to control to access some functions
Definition: CPImageCtrl.h:151
void CheckSelection(const wxPoint mousePos, const hugin_utils::FDiff2D &p)
used by manipulating line control points, remember if the selected point given in screen coordinates ...
#define HUGIN_FT_TEMPLATE_SIZE
virtual void OnDraw(wxDC &dc)
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 Init(CPEditorPanel *parent)
void clearCtrlPointList()
clear internal control point list
HuginBase::PTools::Transform * m_firstInvTrans
Definition: CPImageCtrl.h:491
std::shared_ptr< vigra::BRGBImage > ImageCacheRGB8Ptr
use reference counted pointers
Definition: ImageCache.h:57
std::vector< wxColour > pointColors
Definition: CPImageCtrl.h:498
virtual wxObject * DoCreateResource()
void ShiftControlPoint(hugin_utils::FDiff2D shift)
shift selected cp coordinate by given
wxImage imageCacheEntry2wxImage(ImageCache::EntryPtr e)
HuginBase::PTools::Transform * getSecondInvTrans() const
Definition: CPImageCtrl.h:251
void rescaleImage()
T applyRot(const T &p) const
Definition: CPImageCtrl.h:371
void showTemplateArea(bool show=true)
wxPoint MaxScrollDelta(wxPoint delta)
calculate maximum delta that is allowed when scrolling
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
void OnMouseEnter(wxMouseEvent &e)
bool HasMonitorProfile() const
return true if we found a suitable monitor profile and could loading it
Definition: huginApp.h:134
wxRect m_labelPos
position of the point labels (in screen coordinates)
Definition: CPImageCtrl.h:159
evaluate x, points are on a vertical line
Definition: ControlPoint.h:47
IMPEX double h[25][1024]
Definition: emor.cpp:169
void DrawCross(wxDC &dc, wxPoint p, int l)
hugin_utils::FDiff2D rectStartPos
Definition: CPImageCtrl.h:484
void update()
initiate redraw
const wxString GetLabel() const
return label
Definition: CPImageCtrl.h:120
TDiff2D< double > FDiff2D
Definition: hugin_math.h:150
void transformImageIntern(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, TRANSFORM &transform, PixelTransform &pixelTransform, vigra::Diff2D destUL, Interpolator interp, bool warparound, AppBase::ProgressDisplay *progress, bool singleThreaded)
Transform an image into the panorama.
wxRect region
Definition: CPImageCtrl.h:85
wxTimer m_timer
Definition: CPImageCtrl.h:525
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"))
void mouseReleaseRMBEvent(wxMouseEvent &mouse)
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:324
T applyRotInv(const T &p) const
Definition: CPImageCtrl.h:395
#define shift
Contains functions to transform whole images.
#define DEBUG_ERROR(msg)
Definition: utils.h:76
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
void setTransforms(HuginBase::PTools::Transform *firstTrans, HuginBase::PTools::Transform *firstInvTrans, HuginBase::PTools::Transform *secondInvTrans)
void showSearchArea(bool show=true)
show/hide the search area rectangle
const wxSize GetBitmapSize() const
return the size of the drawn bitmap (possible rotate is applied)
wxSize m_realSize
Definition: CPImageCtrl.h:459
const HuginBase::ControlPoint GetControlPoint() const
returns the control point
Definition: CPImageCtrl.h:134
wxColour m_textColour
colour of the text background
Definition: CPImageCtrl.h:155
HuginBase::PTools::Transform * m_magTrans
Definition: CPImageCtrl.h:494
bool m_mouseInWindow
Definition: CPImageCtrl.h:523
HuginBase::ControlPoint m_cp
Definition: CPImageCtrl.h:87
void OnKey(wxKeyEvent &e)
hugin_utils::FDiff2D getNewPoint()
get the new point
void OnSize(wxSizeEvent &e)
HuginBase::PTools::Transform * m_magInvTrans
Definition: CPImageCtrl.h:495
void DrawLine(wxDC &dc)
draw line control point on same image
include file for the hugin project
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
std::vector< wxColour > textColours
Definition: CPImageCtrl.h:499
HuginBase::PTools::Transform * m_secondInvTrans
Definition: CPImageCtrl.h:492
virtual bool CanHandle(wxXmlNode *node)
bool fitToWindow
Definition: CPImageCtrl.h:501
void StartLineControlPoint(hugin_utils::FDiff2D newPoint)
starts a new line control point with given coodinates
static T max(T x, T y)
Definition: svm.cpp:65
Holds transformations for Image -&gt; Pano and the other way.
bool IsDrawingLine() const
return true, if line cp should be drawn as separate line
bool emit(CPEvent &ev)
helper func to emit a region
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
HuginBase::ControlPoint m_cp
representation of underlying control point
Definition: CPImageCtrl.h:147
void setCtrlPoint(const HuginBase::ControlPoint &cp, const bool mirrored)
add control piont to internal cp list
wxRect DrawTextMag(wxDC &dc, wxPoint p, hugin_utils::FDiff2D pointInput, bool drawMag, wxColour pointColour, wxColour textColour)
draw magnified area
const bool isOccupiedPos(const hugin_utils::FDiff2D &p) const
check if the given point is over the drawn cp, using image coordinates
hugin_utils::FDiff2D newPoint
Definition: CPImageCtrl.h:477
void mousePressMMBEvent(wxMouseEvent &mouse)
void setScale(double factor)
set the scaling factor for cp display.
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
EditorState editState
Definition: CPImageCtrl.h:488
void OnTimer(wxTimerEvent &e)
void setImage(const std::string &filename, ImageRotation rot)
display img.
void setMagTransforms(HuginBase::PTools::Transform *magTrans, HuginBase::PTools::Transform *magInvTrans)
void showPosition(hugin_utils::FDiff2D point, bool warpPointer=false)
Show point x, y.
DisplayedControlPoint m_selectedPoint
Definition: CPImageCtrl.h:476
CPEditorPanel * m_editPanel
Definition: CPImageCtrl.h:516
wxOverlay m_overlay
Definition: CPImageCtrl.h:461
void setSameImage(bool sameImage)
void OnScrollWin(wxScrollWinEvent &e)
const wxString & GetXRCPath()
return the current xrc path
Definition: huginApp.h:112
bool m_line
true, if line control point on same image
Definition: CPImageCtrl.h:162
hugin_utils::FDiff2D point
Definition: CPImageCtrl.h:86
HuginBase::PTools::Transform * getFirstTrans() const
Definition: CPImageCtrl.h:249
wxPoint roundP(const hugin_utils::FDiff2D &p) const
Definition: CPImageCtrl.h:363
void UpdateControlPoint(hugin_utils::FDiff2D newPoint)
update selected cp coordinate
void UpdateControlPointX(double x)
update x coordinate of selected cp coordinate
void mouseReleaseMMBEvent(wxMouseEvent &mouse)
bool m_showSearchArea
Definition: CPImageCtrl.h:503
static T min(T x, T y)
Definition: svm.cpp:62
bool IsShowingLines() const
ImageRotation
image rotation.
Definition: CPImageCtrl.h:241
wxString m_label
label of displayed control point: number or new
Definition: CPImageCtrl.h:157
unsigned int selectedPointNr
Definition: CPImageCtrl.h:474
hugin_utils::FDiff2D m_mousePos
Definition: CPImageCtrl.h:506
T squareDistance(TDiff2D< T > other) const
Return square of the distance to another point.
Definition: hugin_math.h:135
void ShowLines(bool isShown)
HuginBase::PTools::Transform * m_firstTrans
Definition: CPImageCtrl.h:490
void SetLabel(wxString newLabel)
set label to given wxString