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 BEGIN_EVENT_TABLE(CPImageCtrl, wxScrolledWindow)
647  EVT_SIZE(CPImageCtrl::OnSize)
648  EVT_CHAR(CPImageCtrl::OnKey)
649 // EVT_KEY_UP(CPImageCtrl::OnKeyUp)
650  EVT_KEY_DOWN(CPImageCtrl::OnKeyDown)
651  EVT_LEAVE_WINDOW(CPImageCtrl::OnMouseLeave)
652  EVT_ENTER_WINDOW(CPImageCtrl::OnMouseEnter)
653  EVT_MOTION(CPImageCtrl::mouseMoveEvent)
654  EVT_LEFT_DOWN(CPImageCtrl::mousePressLMBEvent)
655  EVT_LEFT_UP(CPImageCtrl::mouseReleaseLMBEvent)
656  EVT_RIGHT_DOWN(CPImageCtrl::mousePressRMBEvent)
657  EVT_RIGHT_UP(CPImageCtrl::mouseReleaseRMBEvent)
658  EVT_MIDDLE_DOWN(CPImageCtrl::mousePressMMBEvent)
659  EVT_MIDDLE_UP(CPImageCtrl::mouseReleaseMMBEvent)
660  EVT_TIMER(-1, CPImageCtrl::OnTimer)
661 #ifdef __WXMSW__
662  // update view after scrolling on Windows
663  // on WXGTK this is handled already by the control
664  EVT_SCROLLWIN(CPImageCtrl::OnScrollWin)
665 #endif
667 
668 bool CPImageCtrl::Create(wxWindow * parent, wxWindowID id,
669  const wxPoint& pos,
670  const wxSize& size,
671  long style,
672  const wxString& name)
673 {
674  wxScrolledWindow::Create(parent, id, pos, size, style, name);
675  selectedPointNr = 0;
676  editState = NO_IMAGE;
677  scaleFactor = 1;
678  fitToWindow = false;
679  m_showSearchArea = false;
680  m_searchRectWidth = 0;
681  m_showTemplateArea = false;
682  m_templateRectWidth = 0;
683  m_editPanel = 0;
684  m_imgRotation = ROT0;
685  m_sameImage = false;
686  m_magImgCenter = hugin_utils::FDiff2D(-1, -1);
687 
688  wxString filename;
689 
690 #if defined(__WXMSW__)
691  wxString cursorPath = huginApp::Get()->GetXRCPath() + wxT("/data/cursor_cp_pick.cur");
692  m_CPSelectCursor = new wxCursor(cursorPath, wxBITMAP_TYPE_CUR);
693 #else
694  m_CPSelectCursor = new wxCursor(wxCURSOR_CROSS);
695 #endif
696  SetCursor(*m_CPSelectCursor);
697 
698  // TODO: define custom, light background colors.
699  pointColors.push_back(wxTheColourDatabase->Find(wxT("BLUE")));
700  textColours.push_back(wxTheColourDatabase->Find(wxT("WHITE")));
701 
702  pointColors.push_back(wxTheColourDatabase->Find(wxT("GREEN")));
703  textColours.push_back(wxTheColourDatabase->Find(wxT("WHITE")));
704 
705  pointColors.push_back(wxTheColourDatabase->Find(wxT("CYAN")));
706  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
707  pointColors.push_back(wxTheColourDatabase->Find(wxT("GOLD")));
708  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
709 
710  pointColors.push_back(wxTheColourDatabase->Find(wxT("NAVY")));
711  textColours.push_back(wxTheColourDatabase->Find(wxT("WHITE")));
712 
713  pointColors.push_back(wxTheColourDatabase->Find(wxT("DARK TURQUOISE")));
714  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
715 
716  pointColors.push_back(wxTheColourDatabase->Find(wxT("SALMON")));
717  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
718 
719  pointColors.push_back(wxTheColourDatabase->Find(wxT("MAROON")));
720  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
721 
722  pointColors.push_back(wxTheColourDatabase->Find(wxT("KHAKI")));
723  textColours.push_back(wxTheColourDatabase->Find(wxT("BLACK")));
724 
725  m_searchRectWidth = 120;
726  m_mouseInWindow = false;
727  m_forceMagnifier = false;
728  m_timer.SetOwner(this);
729 
730  return true;
731 }
732 
734 {
735  m_editPanel = parent;
736  m_sameImage = false;
738 }
739 
741 {
742  DEBUG_TRACE("dtor");
743  this->SetCursor(wxNullCursor);
744  delete m_CPSelectCursor;
745  DEBUG_TRACE("dtor end");
746 }
747 
748 void CPImageCtrl::OnDraw(wxDC & dc)
749 {
750  wxSize vSize = GetClientSize();
751  // draw image (FIXME, redraw only visible regions.)
752  if (editState != NO_IMAGE && m_img.get()) {
753  //clear the blank rectangle to the left of the image
754  if (bitmap.GetWidth() < vSize.GetWidth()) {
755  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
756  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
757  dc.DrawRectangle(bitmap.GetWidth(), 0,
758  vSize.GetWidth() - bitmap.GetWidth(),vSize.GetHeight());
759  }
760  //clear the blank rectangle below the image
761  if (bitmap.GetHeight() < vSize.GetHeight()) {
762  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
763  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
764  dc.DrawRectangle(0, bitmap.GetHeight(),
765  vSize.GetWidth(), vSize.GetHeight() - bitmap.GetHeight());
766  }
767  dc.DrawBitmap(bitmap,0,0);
768  } else {
769  // clear the rectangle and exit
770  dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
771  dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
772  dc.Clear();
773  return;
774  }
775 
776  // draw known points.
777  wxRect visibleRect(GetViewStart(), vSize);
778  visibleRect.Inflate(20);
779  for(size_t i=0; i<m_points.size(); i++)
780  {
782  {
783  m_points[i].Draw(dc, visibleRect, false);
784  };
785  }
786 
787  switch(editState) {
788  case NEW_POINT_SELECTED:
789  // Boundary check
790  if ((newPoint.x < 0) || (newPoint.y < 0)) {
791  // Tried to create a point outside of the canvas. Ignore it.
792  break;
793  }
794  {
795  DisplayedControlPoint dsp(HuginBase::ControlPoint(0, newPoint.x, newPoint.y, 0, 0, 0), this, false);
796  dsp.SetLabel(_("new"));
797  dsp.Draw(dc, visibleRect, false, true);
798  }
799  if (m_showTemplateArea) {
800  dc.SetLogicalFunction(wxINVERT);
801  dc.SetPen(wxPen(wxT("RED"), 1, wxPENSTYLE_SOLID));
802  dc.SetBrush(wxBrush(wxT("WHITE"), wxBRUSHSTYLE_TRANSPARENT));
803  wxPoint upperLeft = applyRot(roundP(newPoint));
804  upperLeft = scale(upperLeft);
805 
806  int width = scale(m_templateRectWidth);
807 
808  dc.DrawRectangle(upperLeft.x-width, upperLeft.y-width, 2*width, 2*width);
809  dc.SetLogicalFunction(wxCOPY);
810  }
811 
812  break;
813  case NEW_LINE_CREATING:
814  m_selectedPoint.Draw(dc, visibleRect, false, true);
815  break;
817  m_points[selectedPointNr].Draw(dc, visibleRect, true);
818  break;
820  case NO_SELECTION:
821  case NO_IMAGE:
822  break;
823  }
824 
825  if (m_showSearchArea && m_mousePos.x != -1){
826  dc.SetLogicalFunction(wxINVERT);
827  dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
828  dc.SetBrush(wxBrush(wxT("WHITE"), wxBRUSHSTYLE_TRANSPARENT));
829 
831  upperLeft = scale(upperLeft);
832  int width = scale(m_searchRectWidth);
833  DEBUG_DEBUG("drawing rect " << upperLeft << " with width " << 2*width << " orig: " << m_searchRectWidth*2 << " scale factor: " << getScaleFactor());
834 
835  dc.DrawRectangle(hugin_utils::roundi(upperLeft.x - width), hugin_utils::roundi(upperLeft.y - width), 2 * width, 2 * width);
836  dc.SetLogicalFunction(wxCOPY);
837  }
838 }
839 
841 {
842  if (m_magImgCenter == point)
843  {
844  // if point has not moved use cached image
845  return m_magImg;
846  };
847  // point has changed, we need to recalculate the magnified image
848  typedef vigra::RGBValue<vigra::UInt8> VT;
849  DEBUG_TRACE("")
850 
851  // draw magnified image
852  // width (and height) of magnifier region (output), should be odd
853  int magWidth = wxConfigBase::Get()->Read(wxT("/CPEditorPanel/MagnifierWidth"),61l);
854  int hw = magWidth/2;
855  magWidth = hw*2+1;
856 
857  wxImage img(magWidth, magWidth);
858  vigra::BasicImageView<VT> magImg((VT*)img.GetData(), magWidth,magWidth);
859  vigra::BImage maskImg(magWidth, magWidth);
861 
862  // middle pixel
863  double mx, my;
864  m_magInvTrans->transformImgCoord(mx, my, point.x, point.y);
865 
866  // apply the transform, for the small window the multithreading has too much overhead, so use only single threaded version
869  vigra::destImageRange(magImg),
870  vigra::destImage(maskImg),
871  *m_magTrans,
872  ptf,
873  vigra::Diff2D(hugin_utils::roundi(mx - hw),
874  hugin_utils::roundi(my - hw)),
876  false,
877  &progDisp,
878  true);
879 
880  // TODO: contrast enhancement
881  vigra::FindMinMax<vigra::UInt8> minmax;
882  vigra::inspectImage(vigra::srcImageRange(magImg), minmax);
883 
884  // transform to range 0...255
886  vigra::linearRangeMapping(
887  VT(minmax.min), VT(minmax.max), // src range
888  VT(0, 0, 0), VT(255, 255, 255)) // dest range
889  );
890 // vigra::transformImage(srcImageRange(magImg), destImage(magImg),
891 // vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
892 
893  // draw cursor
894  for(int x=0; x < magWidth; x++) {
895  VT p =magImg(x,hw+1);
896  vigra::UInt8 v = 0.3/255*p.red() + 0.6/255*p.green() + 0.1/255*p.blue() < 0.5 ? 255 : 0;
897  p[0] = v;
898  p[1] = v;
899  p[2] = v;
900  magImg(x,hw+1) = p;
901  p = magImg(hw+1, x);
902  v = 0.3/255*p.red() + 0.6/255*p.green() + 0.1/255*p.blue() < 0.5 ? 255 : 0;
903  p[0] = v;
904  p[1] = v;
905  p[2] = v;
906  magImg(hw+1, x) = p;
907  }
908 
909  // rotate image according to current display
910  switch (m_imgRotation) {
911  case ROT90:
912  img = img.Rotate90(true);
913  break;
914  case ROT180:
915  img = img.Rotate180();
916  break;
917  case ROT270:
918  img = img.Rotate90(false);
919  break;
920  default:
921  break;
922  };
923 
924  m_magImg = wxBitmap(img);
925  m_magImgCenter = point;
926  return m_magImg;
927 }
928 
930 {
931  return wxSize(imageSize.GetWidth(),imageSize.GetHeight());
932 }
933 
934 
935 void CPImageCtrl::setImage(const std::string & file, ImageRotation imgRot)
936 {
937  DEBUG_TRACE("setting Image " << file);
938  imageFilename = file;
939  m_sameImage=false;
941  wxString fn(imageFilename.c_str(),HUGIN_CONV_FILENAME);
942  if (wxFileName::FileExists(fn)) {
943  m_imgRotation = imgRot;
944  m_img = ImageCache::getInstance().getImageIfAvailable(imageFilename);
946  if (m_img.get()) {
947  rescaleImage();
948  } else {
949  // load the image in the background.
950  m_imgRequest = ImageCache::getInstance().requestAsyncImage(imageFilename);
951  m_imgRequest->ready.push_back(
952  std::bind(&CPImageCtrl::OnImageLoaded, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)
953  );
954  // With m_img.get() 0, everything will act as normal except drawing.
955  }
956  } else {
958  bitmap = wxBitmap();
959  // delete the image (release shared_ptr)
960  // create an empty image.
961  m_img = ImageCache::EntryPtr(new ImageCache::Entry);
962  }
963 }
964 
966 {
967  m_firstTrans=firstTrans;
968  m_firstInvTrans=firstInvTrans;
969  m_secondInvTrans=secondInvTrans;
970 };
971 
973 {
974  m_magTrans = magTrans;
975  m_magInvTrans = magInvTrans;
976 }
977 
978 void CPImageCtrl::setSameImage(bool sameImage)
979 {
980  m_sameImage=sameImage;
981 };
982 
983 void CPImageCtrl::OnImageLoaded(ImageCache::EntryPtr entry, std::string filename, bool load_small)
984 {
985  // check we are still displaying this image
986  if (imageFilename == filename)
987  {
988  m_img = entry;
989  rescaleImage();
990  }
991 }
992 
994 {
995  if (editState == NO_IMAGE || !m_img.get()) {
996  return;
997  }
998  wxImage img = imageCacheEntry2wxImage(m_img);
999  if (img.GetWidth() == 0) {
1000  return;
1001  }
1002  imageSize = wxSize(img.GetWidth(), img.GetHeight());
1004  if (fitToWindow) {
1006  }
1007  DEBUG_DEBUG("src image size "
1008  << imageSize.GetHeight() << "x" << imageSize.GetWidth());
1009  if (getScaleFactor() == 1.0) {
1010  //the icc correction would work on the original cached image file
1011  //therefore we need to create a copy to work on it
1012  img = img.Copy();
1013  }
1014  else
1015  {
1016  // rescale image
1017  imageSize.SetWidth(scale(imageSize.GetWidth()));
1018  imageSize.SetHeight(scale(imageSize.GetHeight()));
1019  DEBUG_DEBUG("rescaling to " << imageSize.GetWidth() << "x"
1020  << imageSize.GetHeight());
1021  wxImageResizeQuality resizeQuality = wxIMAGE_QUALITY_NORMAL;
1022  if (std::max(img.GetWidth(), img.GetHeight()) > (ULONG_MAX >> 16))
1023  {
1024  // wxIMAGE_QUALITY_NORMAL resizes the image with ResampleNearest
1025  // this algorithm works only if image dimensions are smaller then
1026  // ULONG_MAX >> 16 (actual size of unsigned long differ from system
1027  // to system)
1028  resizeQuality = wxIMAGE_QUALITY_BOX_AVERAGE;
1029  };
1030  img = img.Scale(imageSize.GetWidth(), imageSize.GetHeight(), resizeQuality);
1031  };
1032  // need to rotate full image. warning. this can be very memory intensive
1033  if (m_imgRotation != ROT0)
1034  {
1035  switch (m_imgRotation)
1036  {
1037  case ROT90:
1038  img = img.Rotate90(true);
1039  break;
1040  case ROT180:
1041  img = img.Rotate180();
1042  break;
1043  case ROT270:
1044  img = img.Rotate90(false);
1045  break;
1046  default:
1047  break;
1048  };
1049  };
1050  // do color correction only if input image has icc profile or if we found a monitor profile
1051  if (!m_img->iccProfile->empty() || huginApp::Get()->HasMonitorProfile())
1052  {
1054  };
1055  bitmap = wxBitmap(img);
1056 
1057  if (m_imgRotation == ROT90 || m_imgRotation == ROT270) {
1058  SetVirtualSize(imageSize.GetHeight(), imageSize.GetWidth());
1059  } else {
1060  SetVirtualSize(imageSize.GetWidth(), imageSize.GetHeight());
1061  }
1062  SetScrollRate(1,1);
1063  Refresh(FALSE);
1064 }
1065 
1066 void CPImageCtrl::setCtrlPoint(const HuginBase::ControlPoint& cp, const bool mirrored)
1067 {
1068  DisplayedControlPoint dcp(cp, this, mirrored);
1069  dcp.SetColour(pointColors[m_points.size() % pointColors.size()], textColours[m_points.size() % textColours.size()]);
1070  dcp.SetLabel(wxString::Format(wxT("%lu"), (unsigned long int)m_points.size()));
1071  m_points.push_back(dcp);
1072 }
1073 
1075 {
1076  m_points.clear();
1078  {
1080  };
1081  selectedPointNr = UINT_MAX;
1082 };
1083 
1085 {
1086  DEBUG_TRACE("clearNewPoint");
1087  if (editState != NO_IMAGE) {
1089  }
1090 }
1091 
1092 
1093 void CPImageCtrl::selectPoint(unsigned int nr, bool scrollTo)
1094 {
1095  DEBUG_TRACE("nr: " << nr);
1096  if (nr < m_points.size()) {
1097  selectedPointNr = nr;
1099  if (scrollTo)
1100  {
1101  // scroll to center only when requested
1102  showPosition(m_points[nr].GetPos());
1103  };
1104  update();
1105  } else {
1106  DEBUG_DEBUG("trying to select invalid point nr: " << nr << ". Nr of points: " << m_points.size());
1107  }
1108 }
1109 
1111 {
1112  DEBUG_TRACE("deselecting points");
1115  }
1116  // update view
1117  update();
1118 }
1119 
1121 {
1122  DEBUG_DEBUG("x: " << point.x << " y: " << point.y);
1123  // transform and scale the co-ordinate to the screen.
1124  point = applyRot(point);
1125  point = scale(point);
1126  int x = hugin_utils::roundi(point.x);
1127  int y = hugin_utils::roundi(point.y);
1128 
1129  wxSize sz = GetClientSize();
1130  int scrollx = x - sz.GetWidth()/2;
1131  int scrolly = y - sz.GetHeight()/2;
1132  Scroll(scrollx, scrolly);
1133  if (warpPointer) {
1134  int sx,sy;
1135  GetViewStart(&sx, &sy);
1136  DEBUG_DEBUG("relative coordinages: " << x-sx << "," << y-sy);
1137  WarpPointer(x-sx,y-sy);
1138  }
1139 }
1140 
1141 CPImageCtrl::EditorState CPImageCtrl::isOccupied(wxPoint mousePos, const hugin_utils::FDiff2D &p, unsigned int & pointNr) const
1142 {
1143  // check if mouse is hovering over a label
1144  if(!m_points.empty())
1145  {
1146  for(int i=m_points.size()-1; i>=0; i--)
1147  {
1148  if(m_points[i].isOccupiedLabel(mousePos))
1149  {
1150  pointNr = i;
1151  return KNOWN_POINT_SELECTED;
1152  }
1153  };
1154  // check if mouse is over a known point
1155  for(std::vector<DisplayedControlPoint>::const_iterator it=m_points.begin(); it!=m_points.end(); ++it)
1156  {
1157  if(it->isOccupiedPos(p))
1158  {
1159  pointNr = it - m_points.begin();
1160  return KNOWN_POINT_SELECTED;
1161  }
1162  };
1163  };
1164 
1165  return NEW_POINT_SELECTED;
1166 }
1167 
1169 {
1170  wxClientDC dc(this);
1171  PrepareDC(dc);
1172  wxDCOverlay overlaydc(m_overlay, &dc);
1173  overlaydc.Clear();
1174  dc.SetPen(wxPen(*wxWHITE, 2, wxPENSTYLE_LONG_DASH));
1175  dc.SetBrush(*wxTRANSPARENT_BRUSH);
1176  wxPoint p1=roundP(scale(applyRot(pos1)));
1177  wxPoint p2=roundP(scale(applyRot(pos2)));
1178  dc.DrawRectangle(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
1179 };
1180 
1181 void CPImageCtrl::mouseMoveEvent(wxMouseEvent& mouse)
1182 {
1183  if (!m_img.get()) return; // ignore events if no image loaded.
1184  wxPoint unScrolledMousePos;
1185  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1186  &unScrolledMousePos.x, & unScrolledMousePos.y);
1187  hugin_utils::FDiff2D mpos(unScrolledMousePos.x, unScrolledMousePos.y);
1188  bool doUpdate = false;
1189  mpos = applyRotInv(invScale(mpos));
1190  // if mouseclick is out of image, ignore
1191  if ((mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) && editState!=SELECT_DELETE_REGION)
1192  {
1193  return;
1194  }
1195 
1196 // DEBUG_DEBUG(" pos:" << mpos.x << ", " << mpos.y);
1197  // only if the shift key is not pressed.
1198  if (mouse.LeftIsDown() && ! mouse.ShiftDown()) {
1199  switch(editState) {
1200  case NO_SELECTION:
1201  DEBUG_DEBUG("mouse down movement without selection, in NO_SELECTION state!");
1202  break;
1203  case KNOWN_POINT_SELECTED:
1204  if (mpos.x >= 0 && mpos.x <= m_realSize.GetWidth()){
1205  m_points[selectedPointNr].UpdateControlPointX(mpos.x);
1206  } else if (mpos.x < 0) {
1207  m_points[selectedPointNr].UpdateControlPointX(0);
1208  } else if (mpos.x > m_realSize.GetWidth()) {
1209  m_points[selectedPointNr].UpdateControlPointX(m_realSize.GetWidth());
1210  }
1211 
1212  if (mpos.y >= 0 && mpos.y <= m_realSize.GetHeight()){
1213  m_points[selectedPointNr].UpdateControlPointY(mpos.y);
1214  } else if (mpos.y < 0) {
1215  m_points[selectedPointNr].UpdateControlPointY(0);
1216  } else if (mpos.y > m_realSize.GetHeight()) {
1217  m_points[selectedPointNr].UpdateControlPointY(m_realSize.GetHeight());
1218  }
1219  // emit a notify event here.
1220  //
1221  //emit(pointMoved(selectedPointNr, points[selectedPointNr]));
1222  // do more intelligent updating here?
1223  doUpdate = true;
1224  break;
1225  // not possible.
1226  case NEW_POINT_SELECTED:
1227  DEBUG_DEBUG("WARNING: mouse move in new point state")
1228  newPoint = mpos;
1229  doUpdate = true;
1230  break;
1231  case NEW_LINE_CREATING:
1233  doUpdate = true;
1234  break;
1235  case SELECT_DELETE_REGION:
1236  case NO_IMAGE:
1237  break;
1238  }
1239  }
1240 
1241  if ((mouse.MiddleIsDown() || mouse.ShiftDown() || mouse.m_controlDown ) && editState!=SELECT_DELETE_REGION) {
1242  // scrolling with the mouse
1243  if (m_mouseScrollPos !=mouse.GetPosition()) {
1244  wxPoint delta = mouse.GetPosition() - m_mouseScrollPos;
1245  if (mouse.MiddleIsDown())
1246  {
1247  // invert scroll direction for middle mouse click (touchpad like scrolling)
1248  delta = -delta;
1249  };
1250  // scrolling is done later
1251  if (mouse.ShiftDown()) {
1252  // emit scroll event, so that other window can be scrolled
1253  // as well.
1254  CPEvent e(this, CPEvent::SCROLLED, hugin_utils::FDiff2D(delta.x, delta.y));
1255  emit(e);
1256  } else {
1257  // scroll only our window
1258  ScrollDelta(delta);
1259  }
1260  m_mouseScrollPos = mouse.GetPosition();
1261  }
1262  }
1263 
1264  if(mouse.RightIsDown() && editState==SELECT_DELETE_REGION)
1265  {
1266  //update selection rectangle
1268  }
1269 // DEBUG_DEBUG("ImageDisplay: mouse move, state: " << editState);
1270 
1271  // draw a rectangle
1272  if (m_showSearchArea) {
1273  doUpdate = true;
1274  }
1275 
1276  unsigned int selPointNr;
1277  if (isOccupied(unScrolledMousePos, mpos, selPointNr) == KNOWN_POINT_SELECTED ) {
1278  SetCursor(wxCursor(wxCURSOR_ARROW));
1279  } else {
1280  SetCursor(*m_CPSelectCursor);
1281  }
1282 
1283  m_mousePos = mpos;
1284  // repaint
1285  if (doUpdate) {
1286  update();
1287  }
1288 }
1289 
1290 
1291 void CPImageCtrl::mousePressLMBEvent(wxMouseEvent& mouse)
1292 {
1293  DEBUG_DEBUG("LEFT MOUSE DOWN");
1294  if (!m_img.get()) return; // ignore events if no image loaded.
1295  //ignore left mouse button if selecting region with right mouse button
1297  return;
1298  wxPoint unScrolledMousePos;
1299  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1300  &unScrolledMousePos.x, & unScrolledMousePos.y);
1301  hugin_utils::FDiff2D mpos(unScrolledMousePos.x, unScrolledMousePos.y);
1302  mpos = applyRotInv(invScale(mpos));
1303  DEBUG_DEBUG("mousePressEvent, pos:" << mpos.x
1304  << ", " << mpos.y);
1305  // if mouseclick is out of image, ignore
1306  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) {
1307  return;
1308  }
1309  unsigned int selPointNr = 0;
1310  EditorState clickState = isOccupied(unScrolledMousePos, mpos, selPointNr);
1311  if (mouse.LeftDown() && editState != NO_IMAGE
1312  && mpos.x < m_realSize.x && mpos.y < m_realSize.y)
1313  {
1314  // we can always select a new point
1315  if (clickState == KNOWN_POINT_SELECTED) {
1316  DEBUG_DEBUG("click on point: " << selPointNr);
1317  selectedPointNr = selPointNr;
1318  m_points[selectedPointNr].CheckSelection(unScrolledMousePos, mpos);
1320  editState = clickState;
1321  // notify parent and therefore other CPImageCtrl to select the clicked point
1322  CPEvent e( this, selectedPointNr);
1323  // stop timer so that magnifier is always displayed when moving cp and not hidden by timer
1324  m_timer.Stop();
1325  m_forceMagnifier = true;
1326  emit(e);
1327  } else if (clickState == NEW_POINT_SELECTED) {
1328  DEBUG_DEBUG("click on new space, select new point");
1329  if(m_sameImage && mouse.AltDown())
1330  {
1334  }
1335  else
1336  {
1338  };
1339  newPoint = mpos;
1340  } else {
1341  DEBUG_ERROR("invalid state " << clickState << " on mouse down");
1342  }
1343 // DEBUG_DEBUG("ImageDisplay: mouse down, state change: " << oldstate
1344 // << " -> " << editState);
1345  }
1346  m_mousePos = mpos;
1347 }
1348 
1349 void CPImageCtrl::OnTimer(wxTimerEvent & e)
1350 {
1351  if (!m_img.get()) return; // ignore events if no image loaded.
1352  m_forceMagnifier = false;
1353  update();
1354 }
1355 
1356 void CPImageCtrl::OnScrollWin(wxScrollWinEvent& e)
1357 {
1358  // repaint image, so that labels and magnifier are updated
1359  update();
1360  e.Skip();
1361 }
1362 
1363 void CPImageCtrl::mouseReleaseLMBEvent(wxMouseEvent& mouse)
1364 {
1365  DEBUG_DEBUG("LEFT MOUSE UP");
1366  if (!m_img.get()) return; // ignore events if no image loaded.
1367  //ignore left mouse button if selecting region with right mouse button
1369  return;
1370 
1371  m_timer.Start(2000, true);
1372 
1373  wxPoint mpos_;
1374  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1375  &mpos_.x, & mpos_.y);
1376  hugin_utils::FDiff2D mpos(mpos_.x, mpos_.y);
1377  mpos = applyRotInv(invScale(mpos));
1378  DEBUG_DEBUG("mouseReleaseEvent, pos:" << mpos.x
1379  << ", " << mpos.y);
1380  // if mouseclick is out of image, ignore
1381  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) {
1382  return;
1383  }
1384 // EditorState oldState = editState;
1385  if (mouse.LeftUp()) {
1386  switch(editState) {
1387  case NO_SELECTION:
1388  DEBUG_DEBUG("mouse release without selection");
1389  break;
1390  case KNOWN_POINT_SELECTED:
1391  {
1392  DEBUG_DEBUG("mouse release with known point " << selectedPointNr);
1393  // scroll so that currently selected point is centered
1395  if (! (m_selectedPoint == m_points[selectedPointNr]) ) {
1396  CPEvent e( this, CPEvent::POINT_CHANGED, selectedPointNr, m_points[selectedPointNr].GetControlPoint());
1397  emit(e);
1398  }
1399  break;
1400  }
1401  case NEW_POINT_SELECTED:
1402  {
1403  DEBUG_DEBUG("new Point changed (event fire): x:" << mpos.x << " y:" << mpos.y);
1404  // fire the wxWin event
1405  CPEvent e( this, newPoint);
1406  emit(e);
1407  break;
1408  }
1409  case NEW_LINE_CREATING:
1410  {
1411  //notify parent
1413  emit(e);
1414  break;
1415  }
1416  case SELECT_DELETE_REGION:
1417  case NO_IMAGE:
1418  break;
1419 
1420  }
1421 // DEBUG_DEBUG("ImageDisplay: mouse release, state change: " << oldState
1422 // << " -> " << editState);
1423  }
1424 
1425 }
1426 
1427 
1428 void CPImageCtrl::mouseReleaseMMBEvent(wxMouseEvent& mouse)
1429 {
1430  DEBUG_DEBUG("middle mouse button released, leaving scroll mode")
1431 // SetCursor(wxCursor(wxCURSOR_BULLSEYE));
1432 }
1433 
1434 
1435 void CPImageCtrl::mousePressMMBEvent(wxMouseEvent& mouse)
1436 {
1437  DEBUG_DEBUG("middle mouse button pressed, entering scroll mode")
1438  if (!m_img.get()) return; // ignore events if no image loaded.
1439  m_mouseScrollPos = mouse.GetPosition();
1440 // SetCursor(wxCursor(wxCURSOR_HAND));
1441 }
1442 
1443 void CPImageCtrl::mousePressRMBEvent(wxMouseEvent& mouse)
1444 {
1445  //ignore event if no image loaded
1446  if(!m_img.get())
1447  return;
1448  wxPoint mpos_;
1449  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y, &mpos_.x, & mpos_.y);
1450  hugin_utils::FDiff2D mpos(mpos_.x, mpos_.y);
1451  mpos = applyRotInv(invScale(mpos));
1452  // if mouseclick is out of image, ignore
1453  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight())
1454  {
1455  return;
1456  }
1458  {
1459  rectStartPos=mpos;
1461  };
1462 };
1463 
1464 void CPImageCtrl::mouseReleaseRMBEvent(wxMouseEvent& mouse)
1465 {
1466  if (!m_img.get()) return; // ignore events if no image loaded.
1467  wxPoint mpos_;
1468  CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
1469  &mpos_.x, & mpos_.y);
1470  hugin_utils::FDiff2D mpos(mpos_.x, mpos_.y);
1471  mpos = applyRotInv(invScale(mpos));
1472  DEBUG_DEBUG("mouseReleaseEvent, pos:" << mpos.x
1473  << ", " << mpos.y);
1474 
1475  if (mouse.RightUp())
1476  {
1478  {
1479  // clear overlay
1480  m_overlay.Reset();
1482  CPEvent e(this,rectStartPos,mpos);
1483  emit(e);
1484  }
1485  else
1486  {
1487  // if mouseclick is out of image, ignore
1488  if (mpos.x >= m_realSize.GetWidth() || mpos.y >= m_realSize.GetHeight()) {
1489  return;
1490  }
1491  // set right up event
1492  DEBUG_DEBUG("Emitting right click (rmb release)");
1493  CPEvent e(this, CPEvent::RIGHT_CLICK, mpos);
1494  emit(e);
1495  }
1496  }
1497 }
1498 
1500 {
1501  DEBUG_TRACE("edit state:" << editState);
1502  wxClientDC dc(this);
1503  PrepareDC(dc);
1504  OnDraw(dc);
1505 }
1506 
1508 {
1509  if ( ProcessEvent( ev ) == FALSE ) {
1510  wxLogWarning( _("Could not process event!") );
1511  return false;
1512  } else {
1513  return true;
1514  }
1515 }
1516 
1517 void CPImageCtrl::setScale(double factor)
1518 {
1519  if (factor == 0) {
1520  fitToWindow = true;
1521  factor = calcAutoScaleFactor(imageSize);
1522  } else {
1523  fitToWindow = false;
1524  }
1525  DEBUG_DEBUG("new scale factor:" << factor);
1526  // update if factor changed
1527  if (factor != scaleFactor) {
1528  scaleFactor = factor;
1529  // keep existing scale focussed.
1530  rescaleImage();
1531  }
1532 }
1533 
1535 {
1536  // TODO correctly autoscale rotated iamges
1537  int w = size.GetWidth();
1538  int h = size.GetHeight();
1539  if (m_imgRotation == ROT90 || m_imgRotation == ROT270) {
1540  int t = w;
1541  w = h;
1542  h = t;
1543  }
1544 
1545 // wxSize csize = GetClientSize();
1546  wxSize csize = GetSize();
1547  DEBUG_DEBUG("csize: " << csize.GetWidth() << "x" << csize.GetHeight() << "image: " << w << "x" << h);
1548  double s1 = (double)csize.GetWidth()/w;
1549  double s2 = (double)csize.GetHeight()/h;
1550  DEBUG_DEBUG("s1: " << s1 << " s2:" << s2);
1551  return s1 < s2 ? s1 : s2;
1552 }
1553 
1555 {
1556  return scaleFactor;
1557 }
1558 
1559 void CPImageCtrl::OnSize(wxSizeEvent &e)
1560 {
1561  DEBUG_TRACE("size: " << e.GetSize().GetWidth() << "x" << e.GetSize().GetHeight());
1562  // rescale bitmap if needed.
1563  if (imageFilename != "") {
1564  if (fitToWindow) {
1565  setScale(0);
1566  }
1567  }
1568 }
1569 
1570 void CPImageCtrl::OnKey(wxKeyEvent & e)
1571 {
1572  if (!m_img.get()) return; // ignore events if no image loaded.
1573  DEBUG_TRACE(" OnKey, key:" << e.m_keyCode);
1574  wxPoint delta(0,0);
1575  // check for cursor keys, if control is not pressed
1576  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_LEFT ) delta.x = -1;
1577  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_RIGHT ) delta.x = 1;
1578  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_UP ) delta.y = -1;
1579  if ((!e.CmdDown()) && e.GetKeyCode() == WXK_DOWN ) delta.y = 1;
1580  if ( (delta.x != 0 || delta.y != 0 ) && (e.ShiftDown() || e.CmdDown())) {
1581  // move to the left
1582  double speed = (double) GetClientSize().GetWidth()/10;
1583  delta.x = (int) (delta.x * speed);
1584  delta.y = (int) (delta.y * speed);
1585  if (e.ShiftDown()) {
1586  // emit scroll event, so that other window can be scrolled
1587  // as well.
1588  CPEvent e(this, CPEvent::SCROLLED, hugin_utils::FDiff2D(delta.x, delta.y));
1589  emit(e);
1590  } else if (e.CmdDown()) {
1591  ScrollDelta(delta);
1592  }
1593  } else if (delta.x != 0 || delta.y != 0 ) {
1594 
1595  hugin_utils::FDiff2D shift(delta.x/3.0, delta.y/3.0);
1596  // rotate shift according to current display
1597  double t;
1598  switch (m_imgRotation) {
1599  case ROT90:
1600  t = shift.x;
1601  shift.x = shift.y;
1602  shift.y = -t;
1603  break;
1604  case ROT180:
1605  shift.x = -shift.x;
1606  shift.y = -shift.y;
1607  break;
1608  case ROT270:
1609  t = shift.x;
1610  shift.x = -shift.y;
1611  shift.y = t;
1612  default:
1613  break;
1614  }
1615  // move control point by half a pixel, if a point is selected
1616  if (editState == KNOWN_POINT_SELECTED ) {
1618  updatedCp.ShiftControlPoint(shift);
1620  emit(e);
1621  m_forceMagnifier = true;
1622  m_timer.Stop();
1623  m_timer.Start(2000, true);
1624  } else if (editState == NEW_POINT_SELECTED) {
1625  newPoint = newPoint + shift;
1626  // update display.
1627  update();
1628  }
1629 
1630  }
1631  else if (e.m_keyCode == 'a') {
1632  DEBUG_DEBUG("adding point with a key, faking right click");
1633  // faking right mouse button with "a"
1634  // set right up event
1636  emit(ev);
1637  }
1638  else if (e.m_keyCode==WXK_ESCAPE) {
1639  CPEvent ev(this, CPEvent::CANCELED);
1640  emit(ev);
1641  } else {
1642  // forward some keys...
1643  bool forward = false;
1644  switch (e.GetKeyCode())
1645  {
1646  case 'g':
1647  case '0':
1648  case '1':
1649  case '2':
1650  case 'f':
1651  case WXK_RIGHT:
1652  case WXK_LEFT:
1653  case WXK_UP:
1654  case WXK_DOWN:
1655  case WXK_DELETE:
1656  forward = true;
1657  break;
1658  default:
1659  break;
1660  }
1661 
1662  if (forward) {
1663  // dangelo: I don't understand why some keys are forwarded and others are not..
1664  // Delete is forwared under wxGTK, and g not..
1665  // wxWidgets 2.6.1 using gtk 2 doesn't set the event object
1666  // properly.. do it here by hand
1667  e.SetEventObject(this);
1668  DEBUG_DEBUG("forwarding key " << e.GetKeyCode()
1669  << " origin: id:" << e.GetId() << " obj: "
1670  << e.GetEventObject());
1671  // forward all keys to our parent
1672  //GetParent()->GetEventHandler()->ProcessEvent(e);
1673  m_editPanel->GetEventHandler()->ProcessEvent(e);
1674  } else {
1675  e.Skip();
1676  }
1677  }
1678 }
1679 
1680 void CPImageCtrl::OnKeyDown(wxKeyEvent & e)
1681 {
1682  DEBUG_TRACE("key:" << e.m_keyCode);
1683  if (!m_img.get()) return; // ignore events if no image loaded.
1684  if (e.m_keyCode == WXK_SHIFT || e.m_keyCode == WXK_CONTROL) {
1685  DEBUG_DEBUG("shift or control down, reseting scoll position");
1686  m_mouseScrollPos = e.GetPosition();
1687  }
1688  e.Skip();
1689 }
1690 
1691 void CPImageCtrl::OnMouseLeave(wxMouseEvent & e)
1692 {
1693  DEBUG_TRACE("MOUSE LEAVE");
1695  m_mouseInWindow = false;
1696  update();
1697 }
1698 
1699 void CPImageCtrl::OnMouseEnter(wxMouseEvent & e)
1700 {
1701  if (huginApp::Get()->getMainFrame()->IsActive())
1702  {
1703  DEBUG_TRACE("MOUSE Enter, setting focus");
1704  m_mouseInWindow = true;
1705  SetFocus();
1706  update();
1707  };
1708 }
1709 
1711 {
1712  // only possible if a new point is actually selected
1713  // DEBUG_ASSERT(editState == NEW_POINT_SELECTED);
1714  return newPoint;
1715 }
1716 
1718 {
1719  DEBUG_DEBUG("setting new point " << p.x << "," << p.y);
1720  // should we need to check for some precondition?
1721  newPoint = p;
1723 
1724  // show new point.
1725  showPosition(p);
1726 
1727  // we do not send an event, since CPEditorPanel
1728  // caused the change.. so it doesn't need to filter
1729  // out its own change messages.
1730 }
1731 
1733 {
1734  m_showSearchArea = show;
1735  if (show)
1736  {
1737  int templSearchAreaPercent = wxConfigBase::Get()->Read(wxT("/Finetune/SearchAreaPercent"), HUGIN_FT_SEARCH_AREA_PERCENT);
1738  m_searchRectWidth = (m_realSize.GetWidth() * templSearchAreaPercent) / 200;
1739  DEBUG_DEBUG("Setting new search area: w in %:" << templSearchAreaPercent << " bitmap width: " << bitmap.GetWidth() << " resulting size: " << m_searchRectWidth);
1741  }
1742 }
1743 
1745 {
1746  m_showTemplateArea = show;
1747  if (show)
1748  {
1749  m_templateRectWidth = wxConfigBase::Get()->Read(wxT("/Finetune/TemplateSize"),HUGIN_FT_TEMPLATE_SIZE) / 2;
1750  }
1751 }
1752 
1753 wxPoint CPImageCtrl::MaxScrollDelta(wxPoint delta)
1754 {
1755  int x,y;
1756  GetViewStart( &x, &y );
1757 
1758  wxSize winSize = GetClientSize();
1759  wxSize imgSize;
1760  imgSize.x = bitmap.GetWidth();
1761  imgSize.y = bitmap.GetHeight();
1762  // check for top and left border
1763  if (x + delta.x < 0) {
1764  delta.x = -x;
1765  }
1766  if (y + delta.y < 0) {
1767  delta.y = -y;
1768  }
1769  // check for right and bottom border
1770  int right = x + delta.x + winSize.x ;
1771  if (right > imgSize.x) {
1772  delta.x = imgSize.x - right;
1773  if (delta.x < 0) {
1774  delta.x = 0;
1775  }
1776  }
1777  int bottom = y + delta.y + winSize.y ;
1778  if (bottom > imgSize.y) {
1779  delta.y = imgSize.y - bottom;
1780  if (delta.y < 0) {
1781  delta.y = 0;
1782  }
1783  }
1784  return delta;
1785 }
1786 
1787 void CPImageCtrl::ScrollDelta(const wxPoint & delta)
1788 {
1789  // TODO: adjust
1790  if (delta.x == 0 && delta.y == 0) {
1791  return;
1792  }
1793  int x,y;
1794  GetViewStart( &x, &y );
1795  x = x + delta.x;
1796  y = y + delta.y;
1797  if (x<0) x = 0;
1798  if (y<0) y = 0;
1799  Scroll( x, y);
1800 #ifdef __WXMSW__
1801  // repaint image, so that labels and magnifier are updated
1802  // only needed on Windows, on wxGTK this is handled by the
1803  // underlying control
1804  update();
1805 #endif
1806 }
1807 
1808 const wxSize CPImageCtrl::GetBitmapSize() const
1809 {
1810  return bitmap.GetSize();
1811 };
1812 
1814 {
1815  return m_img->get8BitImage();
1816 };
1817 
1818 void CPImageCtrl::ShowLines(bool isShown)
1819 {
1820  m_showLines = isShown;
1821 }
1822 
1824 {
1825  return m_showLines;
1826 }
1827 
1828 IMPLEMENT_DYNAMIC_CLASS(CPImageCtrl, wxScrolledWindow)
1829 
1831  : wxXmlResourceHandler()
1832 {
1833  AddWindowStyles();
1834 }
1835 
1837 {
1838  XRC_MAKE_INSTANCE(cp, CPImageCtrl)
1839 
1840  cp->Create(m_parentAsWindow,
1841  GetID(),
1842  GetPosition(), GetSize(),
1843  GetStyle(wxT("style")),
1844  GetName());
1845 
1846  SetupWindow( cp);
1847 
1848  return cp;
1849 }
1850 
1852 {
1853  return IsOfClass(node, wxT("CPImageCtrl"));
1854 }
1855 
1856 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
static const int NO_IMAGE
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:147
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
END_EVENT_TABLE()
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:641
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:152
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
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:130
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