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  m_resizeTimer.SetOwner(this);
711  // bind event handler
712  Bind(wxEVT_SIZE, &CPImageCtrl::OnSize, this);
713  Bind(wxEVT_TIMER, &CPImageCtrl::OnSizeFinished, this, m_resizeTimer.GetId());
714  Bind(wxEVT_CHAR, &CPImageCtrl::OnKey, this);
715  Bind(wxEVT_KEY_DOWN, &CPImageCtrl::OnKeyDown, this);
716  Bind(wxEVT_LEAVE_WINDOW, &CPImageCtrl::OnMouseLeave, this);
717  Bind(wxEVT_ENTER_WINDOW, &CPImageCtrl::OnMouseEnter, this);
718  Bind(wxEVT_MOTION, &CPImageCtrl::mouseMoveEvent, this);
719  Bind(wxEVT_LEFT_DOWN, &CPImageCtrl::mousePressLMBEvent, this);
720  Bind(wxEVT_LEFT_UP, &CPImageCtrl::mouseReleaseLMBEvent, this);
721  Bind(wxEVT_RIGHT_DOWN, &CPImageCtrl::mousePressRMBEvent, this);
722  Bind(wxEVT_RIGHT_UP, &CPImageCtrl::mouseReleaseRMBEvent, this);
723  Bind(wxEVT_MIDDLE_DOWN, &CPImageCtrl::mousePressMMBEvent, this);
724  Bind(wxEVT_MIDDLE_UP, &CPImageCtrl::mouseReleaseMMBEvent, this);
725  Bind(wxEVT_TIMER, &CPImageCtrl::OnTimer, this, m_timer.GetId());
726  Bind(wxEVT_PAINT, &CPImageCtrl::OnPaint, this);
727 
728  return true;
729 }
730 
732 {
733  m_editPanel = parent;
734  m_sameImage = false;
736 }
737 
739 {
740  DEBUG_TRACE("dtor");
741  this->SetCursor(wxNullCursor);
742  delete m_CPSelectCursor;
743  DEBUG_TRACE("dtor end");
744 }
745 
746 void CPImageCtrl::OnPaint(wxPaintEvent& e)
747 {
748  wxAutoBufferedPaintDC dc(this);
749  PrepareDC(dc);
750  dc.SetBackground(GetBackgroundColour());
751  dc.Clear();
752  wxSize vSize = GetClientSize();
753  // draw image (FIXME, redraw only visible regions.)
754  if (editState != NO_IMAGE && m_img.get())
755  {
756  dc.DrawBitmap(bitmap,0,0);
757  }
758  else
759  {
760  // no or valid image, exit
761  return;
762  }
763 
764  // draw known points.
765  wxRect visibleRect(GetViewStart(), vSize);
766  visibleRect.Inflate(20);
767  for(size_t i=0; i<m_points.size(); i++)
768  {
770  {
771  m_points[i].Draw(dc, visibleRect, false);
772  };
773  }
774 
775  switch(editState) {
776  case NEW_POINT_SELECTED:
777  // Boundary check
778  if ((newPoint.x < 0) || (newPoint.y < 0)) {
779  // Tried to create a point outside of the canvas. Ignore it.
780  break;
781  }
782  {
783  DisplayedControlPoint dsp(HuginBase::ControlPoint(0, newPoint.x, newPoint.y, 0, 0, 0), this, false);
784  dsp.SetLabel(_("new"));
785  dsp.Draw(dc, visibleRect, false, true);
786  }
787  if (m_showTemplateArea) {
788  dc.SetLogicalFunction(wxINVERT);
789  dc.SetPen(wxPen("RED", 1, wxPENSTYLE_SOLID));
790  dc.SetBrush(wxBrush("WHITE", wxBRUSHSTYLE_TRANSPARENT));
791  wxPoint upperLeft = applyRot(roundP(newPoint));
792  upperLeft = scale(upperLeft);
793 
794  int width = scale(m_templateRectWidth);
795 
796  dc.DrawRectangle(upperLeft.x-width, upperLeft.y-width, 2*width, 2*width);
797  dc.SetLogicalFunction(wxCOPY);
798  }
799 
800  break;
801  case NEW_LINE_CREATING:
802  m_selectedPoint.Draw(dc, visibleRect, false, true);
803  break;
805  m_points[selectedPointNr].Draw(dc, visibleRect, true);
806  break;
808  case NO_SELECTION:
809  case NO_IMAGE:
810  break;
811  }
812 
813  if (m_showSearchArea && m_mousePos.x != -1){
814  dc.SetLogicalFunction(wxINVERT);
815  dc.SetPen(wxPen("WHITE", 1, wxPENSTYLE_SOLID));
816  dc.SetBrush(wxBrush("WHITE", wxBRUSHSTYLE_TRANSPARENT));
817 
819  upperLeft = scale(upperLeft);
820  int width = scale(m_searchRectWidth);
821  DEBUG_DEBUG("drawing rect " << upperLeft << " with width " << 2*width << " orig: " << m_searchRectWidth*2 << " scale factor: " << getScaleFactor());
822 
823  dc.DrawRectangle(hugin_utils::roundi(upperLeft.x - width), hugin_utils::roundi(upperLeft.y - width), 2 * width, 2 * width);
824  dc.SetLogicalFunction(wxCOPY);
825  }
826 }
827 
829 {
830  if (m_magImgCenter == point)
831  {
832  // if point has not moved use cached image
833  return m_magImg;
834  };
835  // point has changed, we need to recalculate the magnified image
836  typedef vigra::RGBValue<vigra::UInt8> VT;
837  DEBUG_TRACE("")
838 
839  // draw magnified image
840  // width (and height) of magnifier region (output), should be odd
841  int magWidth = wxConfigBase::Get()->Read("/CPEditorPanel/MagnifierWidth",61l);
842  int hw = magWidth/2;
843  magWidth = hw*2+1;
844 
845  wxImage img(magWidth, magWidth);
846  vigra::BasicImageView<VT> magImg((VT*)img.GetData(), magWidth,magWidth);
847  vigra::BImage maskImg(magWidth, magWidth);
849 
850  // middle pixel
851  double mx, my;
852  m_magInvTrans->transformImgCoord(mx, my, point.x, point.y);
853 
854  // apply the transform, for the small window the multithreading has too much overhead, so use only single threaded version
857  vigra::destImageRange(magImg),
858  vigra::destImage(maskImg),
859  *m_magTrans,
860  ptf,
861  vigra::Diff2D(hugin_utils::roundi(mx - hw),
862  hugin_utils::roundi(my - hw)),
864  false,
865  &progDisp,
866  true);
867 
868  // TODO: contrast enhancement
869  vigra::FindMinMax<vigra::UInt8> minmax;
870  vigra::inspectImage(vigra::srcImageRange(magImg), minmax);
871 
872  // transform to range 0...255
874  vigra::linearRangeMapping(
875  VT(minmax.min), VT(minmax.max), // src range
876  VT(0, 0, 0), VT(255, 255, 255)) // dest range
877  );
878 // vigra::transformImage(srcImageRange(magImg), destImage(magImg),
879 // vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
880 
881  // draw cursor
882  for(int x=0; x < magWidth; x++) {
883  VT p =magImg(x,hw+1);
884  vigra::UInt8 v = 0.3/255*p.red() + 0.6/255*p.green() + 0.1/255*p.blue() < 0.5 ? 255 : 0;
885  p[0] = v;
886  p[1] = v;
887  p[2] = v;
888  magImg(x,hw+1) = p;
889  p = magImg(hw+1, x);
890  v = 0.3/255*p.red() + 0.6/255*p.green() + 0.1/255*p.blue() < 0.5 ? 255 : 0;
891  p[0] = v;
892  p[1] = v;
893  p[2] = v;
894  magImg(hw+1, x) = p;
895  }
896 
897  // rotate image according to current display
898  switch (m_imgRotation) {
899  case ROT90:
900  img = img.Rotate90(true);
901  break;
902  case ROT180:
903  img = img.Rotate180();
904  break;
905  case ROT270:
906  img = img.Rotate90(false);
907  break;
908  default:
909  break;
910  };
911 
912  m_magImg = wxBitmap(img);
913  m_magImgCenter = point;
914  return m_magImg;
915 }
916 
918 {
919  return wxSize(imageSize.GetWidth(),imageSize.GetHeight());
920 }
921 
922 
923 void CPImageCtrl::setImage(const std::string & file, ImageRotation imgRot)
924 {
925  DEBUG_TRACE("setting Image " << file);
926  imageFilename = file;
927  m_sameImage=false;
929  wxString fn(imageFilename.c_str(),HUGIN_CONV_FILENAME);
930  if (wxFileName::FileExists(fn)) {
931  m_imgRotation = imgRot;
932  m_img = ImageCache::getInstance().getImageIfAvailable(imageFilename);
934  if (m_img.get()) {
935  rescaleImage();
936  } else {
937  // load the image in the background.
938  m_imgRequest = ImageCache::getInstance().requestAsyncImage(imageFilename);
939  m_imgRequest->ready.push_back(
940  std::bind(&CPImageCtrl::OnImageLoaded, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)
941  );
942  // With m_img.get() 0, everything will act as normal except drawing.
943  }
944  } else {
946  bitmap = wxBitmap();
947  // delete the image (release shared_ptr)
948  // create an empty image.
949  m_img = ImageCache::EntryPtr(new ImageCache::Entry);
950  }
951 }
952 
954 {
955  m_firstTrans=firstTrans;
956  m_firstInvTrans=firstInvTrans;
957  m_secondInvTrans=secondInvTrans;
958 };
959 
961 {
962  m_magTrans = magTrans;
963  m_magInvTrans = magInvTrans;
964 }
965 
966 void CPImageCtrl::setSameImage(bool sameImage)
967 {
968  m_sameImage=sameImage;
969 };
970 
971 void CPImageCtrl::OnImageLoaded(ImageCache::EntryPtr entry, std::string filename, bool load_small)
972 {
973  // check we are still displaying this image
974  if (imageFilename == filename)
975  {
976  m_img = entry;
977  rescaleImage();
978  }
979 }
980 
982 {
983  if (editState == NO_IMAGE || !m_img.get()) {
984  return;
985  }
986  wxImage img = imageCacheEntry2wxImage(m_img);
987  if (img.GetWidth() == 0) {
988  return;
989  }
990  imageSize = wxSize(img.GetWidth(), img.GetHeight());
992  if (fitToWindow) {
994  }
995  DEBUG_DEBUG("src image size "
996  << imageSize.GetHeight() << "x" << imageSize.GetWidth());
997  if (getScaleFactor() == 1.0) {
998  //the icc correction would work on the original cached image file
999  //therefore we need to create a copy to work on it
1000  img = img.Copy();
1001  }
1002  else
1003  {
1004  // rescale image
1005  imageSize.SetWidth(scale(imageSize.GetWidth()));
1006  imageSize.SetHeight(scale(imageSize.GetHeight()));
1007  DEBUG_DEBUG("rescaling to " << imageSize.GetWidth() << "x"
1008  << imageSize.GetHeight());
1009  wxImageResizeQuality resizeQuality = wxIMAGE_QUALITY_NORMAL;
1010  if (std::max(img.GetWidth(), img.GetHeight()) > (ULONG_MAX >> 16))
1011  {
1012  // wxIMAGE_QUALITY_NORMAL resizes the image with ResampleNearest
1013  // this algorithm works only if image dimensions are smaller then
1014  // ULONG_MAX >> 16 (actual size of unsigned long differ from system
1015  // to system)
1016  resizeQuality = wxIMAGE_QUALITY_BOX_AVERAGE;
1017  };
1018  img = img.Scale(imageSize.GetWidth(), imageSize.GetHeight(), resizeQuality);
1019  };
1020  // need to rotate full image. warning. this can be very memory intensive
1021  if (m_imgRotation != ROT0)
1022  {
1023  switch (m_imgRotation)
1024  {
1025  case ROT90:
1026  img = img.Rotate90(true);
1027  break;
1028  case ROT180:
1029  img = img.Rotate180();
1030  break;
1031  case ROT270:
1032  img = img.Rotate90(false);
1033  break;
1034  default:
1035  break;
1036  };
1037  };
1038  // do color correction only if input image has icc profile or if we found a monitor profile
1039  if (!m_img->iccProfile->empty() || huginApp::Get()->HasMonitorProfile())
1040  {
1041  vigra::ImageImportInfo::ICCProfile iccProfile;
1042  // ignore icc profile for float images, because we have already color remapped image
1043  if (m_img->imageFloat->width() == 0)
1044  {
1045  iccProfile = *(m_img->iccProfile);
1046  }
1048  };
1049  bitmap = wxBitmap(img);
1050 
1051  if (m_imgRotation == ROT90 || m_imgRotation == ROT270) {
1052  SetVirtualSize(imageSize.GetHeight(), imageSize.GetWidth());
1053  } else {
1054  SetVirtualSize(imageSize.GetWidth(), imageSize.GetHeight());
1055  }
1056  SetScrollRate(1,1);
1057  Refresh(FALSE);
1058 }
1059 
1060 void CPImageCtrl::setCtrlPoint(const HuginBase::ControlPoint& cp, const bool mirrored)
1061 {
1062  DisplayedControlPoint dcp(cp, this, mirrored);
1063  dcp.SetColour(pointColors[m_points.size() % pointColors.size()], textColours[m_points.size() % textColours.size()]);
1064  dcp.SetLabel(wxString::Format("%lu", (unsigned long int)m_points.size()));
1065  m_points.push_back(dcp);
1066 }
1067 
1069 {
1070  m_points.clear();
1072  {
1074  };
1075  selectedPointNr = UINT_MAX;
1076 };
1077 
1079 {
1080  DEBUG_TRACE("clearNewPoint");
1081  if (editState != NO_IMAGE) {
1083  }
1084 }
1085 
1086 
1087 void CPImageCtrl::selectPoint(unsigned int nr, bool scrollTo)
1088 {
1089  DEBUG_TRACE("nr: " << nr);
1090  if (nr < m_points.size()) {
1091  selectedPointNr = nr;
1093  if (scrollTo)
1094  {
1095  // scroll to center only when requested
1096  showPosition(m_points[nr].GetPos());
1097  };
1098  Refresh();
1099  } else {
1100  DEBUG_DEBUG("trying to select invalid point nr: " << nr << ". Nr of points: " << m_points.size());
1101  }
1102 }
1103 
1105 {
1106  DEBUG_TRACE("deselecting points");
1109  }
1110  // update view
1111  Refresh();
1112 }
1113 
1115 {
1116  DEBUG_DEBUG("x: " << point.x << " y: " << point.y);
1117  // transform and scale the co-ordinate to the screen.
1118  point = applyRot(point);
1119  point = scale(point);
1120  int x = hugin_utils::roundi(point.x);
1121  int y = hugin_utils::roundi(point.y);
1122 
1123  wxSize sz = GetClientSize();
1124  int scrollx = x - sz.GetWidth()/2;
1125  int scrolly = y - sz.GetHeight()/2;
1126  Scroll(scrollx, scrolly);
1127  if (warpPointer) {
1128  int sx,sy;
1129  GetViewStart(&sx, &sy);
1130  DEBUG_DEBUG("relative coordinages: " << x-sx << "," << y-sy);
1131  WarpPointer(x-sx,y-sy);
1132  }
1133 }
1134 
1135 CPImageCtrl::EditorState CPImageCtrl::isOccupied(wxPoint mousePos, const hugin_utils::FDiff2D &p, unsigned int & pointNr) const
1136 {
1137  // check if mouse is hovering over a label
1138  if(!m_points.empty())
1139  {
1140  for(int i=m_points.size()-1; i>=0; i--)
1141  {
1142  if(m_points[i].isOccupiedLabel(mousePos))
1143  {
1144  pointNr = i;
1145  return KNOWN_POINT_SELECTED;
1146  }
1147  };
1148  // check if mouse is over a known point
1149  for(std::vector<DisplayedControlPoint>::const_iterator it=m_points.begin(); it!=m_points.end(); ++it)
1150  {
1151  if(it->isOccupiedPos(p))
1152  {
1153  pointNr = it - m_points.begin();
1154  return KNOWN_POINT_SELECTED;
1155  }
1156  };
1157  };
1158 
1159  return NEW_POINT_SELECTED;
1160 }
1161 
1163 {
1164 #if wxCHECK_VERSION(3,3,0)
1165  wxOverlayDC dc(m_overlay, this);
1166  PrepareDC(dc);
1167  dc.Clear();
1168 #else
1169  wxClientDC dc(this);
1170  PrepareDC(dc);
1171  wxDCOverlay overlaydc(m_overlay, &dc);
1172  overlaydc.Clear();
1173 #endif
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  Refresh(false);
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  Refresh();
1354 }
1355 
1356 void CPImageCtrl::OnScrollWin(wxScrollWinEvent& e)
1357 {
1358  // repaint image, so that labels and magnifier are updated
1359  Refresh();
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  if ( ProcessEvent( ev ) == FALSE ) {
1502  wxLogWarning( _("Could not process event!") );
1503  return false;
1504  } else {
1505  return true;
1506  }
1507 }
1508 
1509 void CPImageCtrl::setScale(double factor)
1510 {
1511  if (factor == 0) {
1512  fitToWindow = true;
1513  factor = calcAutoScaleFactor(imageSize);
1514  } else {
1515  fitToWindow = false;
1516  }
1517  DEBUG_DEBUG("new scale factor:" << factor);
1518  // update if factor changed
1519  if (factor != scaleFactor) {
1520  scaleFactor = factor;
1521  // keep existing scale focussed.
1522  rescaleImage();
1523  }
1524 }
1525 
1527 {
1528  // TODO correctly autoscale rotated iamges
1529  int w = size.GetWidth();
1530  int h = size.GetHeight();
1531  if (m_imgRotation == ROT90 || m_imgRotation == ROT270) {
1532  int t = w;
1533  w = h;
1534  h = t;
1535  }
1536 
1537 // wxSize csize = GetClientSize();
1538  wxSize csize = GetSize();
1539  DEBUG_DEBUG("csize: " << csize.GetWidth() << "x" << csize.GetHeight() << "image: " << w << "x" << h);
1540  double s1 = (double)csize.GetWidth()/w;
1541  double s2 = (double)csize.GetHeight()/h;
1542  DEBUG_DEBUG("s1: " << s1 << " s2:" << s2);
1543  return s1 < s2 ? s1 : s2;
1544 }
1545 
1547 {
1548  return scaleFactor;
1549 }
1550 
1551 void CPImageCtrl::OnSize(wxSizeEvent& e)
1552 {
1553  if (!imageFilename.empty())
1554  {
1555  m_resizeTimer.StartOnce(100);
1556  };
1557  e.Skip();
1558 }
1559 
1560 void CPImageCtrl::OnSizeFinished(wxTimerEvent & e)
1561 {
1562  // rescale bitmap if needed.
1563  if (!imageFilename.empty() && fitToWindow)
1564  {
1565  setScale(0);
1566  }
1567  e.Skip();
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  Refresh();
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  Refresh();
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  Refresh();
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("/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("/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  Refresh(false);
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("style"),
1844  GetName());
1845 
1846  SetupWindow( cp);
1847 
1848  return cp;
1849 }
1850 
1852 {
1853  return IsOfClass(node, "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
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:504
int invScale(int x) const
Definition: CPImageCtrl.h:338
wxSize imageSize
Definition: CPImageCtrl.h:455
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: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:452
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)
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)
void OnSizeFinished(wxTimerEvent &e)
hugin_utils::FDiff2D m_magImgCenter
Definition: CPImageCtrl.h:462
bool m_forceMagnifier
Definition: CPImageCtrl.h:524
double scaleFactor
Definition: CPImageCtrl.h:500
include file for the hugin project
bool m_showLines
Definition: CPImageCtrl.h:464
wxBitmap m_magImg
Definition: CPImageCtrl.h:461
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 GetMonitorProfile(wxString &profileName, cmsHPROFILE &profile)
Definition: wxcms.cpp:195
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:651
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: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:468
void clearNewPoint()
clear new point
wxTimer m_resizeTimer
Definition: CPImageCtrl.h:466
std::string imageFilename
Definition: CPImageCtrl.h:453
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
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()
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:484
const wxString GetLabel() const
return label
Definition: CPImageCtrl.h:120
TDiff2D< double > FDiff2D
Definition: hugin_math.h:162
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: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:457
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: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:459
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: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:147
void ShowLines(bool isShown)
HuginBase::PTools::Transform * m_firstTrans
Definition: CPImageCtrl.h:490
void SetLabel(wxString newLabel)
set label to given wxString