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