LensCalImageCtrl.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00011 /*  This program is free software; you can redistribute it and/or
00012  *  modify it under the terms of the GNU General Public
00013  *  License as published by the Free Software Foundation; either
00014  *  version 2 of the License, or (at your option) any later version.
00015  *
00016  *  This software is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *  General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public
00022  *  License along with this software; if not, write to the Free Software
00023  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  */
00026 
00027 #include "panoinc_WX.h"
00028 #include "panoinc.h"
00029 #include "base_wx/platform.h"
00030 #include "LensCalImageCtrl.h"
00031 #include "vigra/transformimage.hxx"
00032 #include "nona/RemappedPanoImage.h"
00033 #include "nona/ImageRemapper.h"
00034 #include "LensCalApp.h"
00035 
00036 BEGIN_EVENT_TABLE(LensCalImageCtrl, wxPanel)
00037     EVT_SIZE(LensCalImageCtrl::Resize)
00038     EVT_PAINT(LensCalImageCtrl::OnPaint)
00039     EVT_MOUSE_EVENTS(LensCalImageCtrl::OnMouseEvent)
00040 END_EVENT_TABLE()
00041 
00042 // init some values
00043 LensCalImageCtrl::LensCalImageCtrl() : wxPanel()
00044 {
00045     m_showLines=true;
00046     m_imageLines=NULL;
00047     m_edge.Create(0,0,true);
00048     m_previewMode=mode_original;
00049     m_projection=HuginBase::SrcPanoImage::RECTILINEAR;
00050     m_focallength=30;
00051     m_cropfactor=1;
00052     m_a=0;
00053     m_b=0;
00054     m_c=0;
00055     m_d=0;
00056     m_e=0;
00057 };
00058 
00059 const LensCalImageCtrl::LensCalPreviewMode LensCalImageCtrl::GetMode()
00060 {
00061     return m_previewMode;
00062 };
00063 
00064 void LensCalImageCtrl::OnMouseEvent(wxMouseEvent &e)
00065 {
00066     if(e.Entering() || e.Leaving())
00067     {
00068         e.Skip();
00069         return;
00070     };
00071     if(!e.LeftIsDown() && !e.RightIsDown())
00072     {
00073         e.Skip();
00074         return;
00075     };
00076     if(m_imageLines==NULL)
00077     {
00078         return;
00079     };
00080     vigra::Point2D pos(e.GetPosition().x,e.GetPosition().y);
00081     HuginLines::Lines lines=m_imageLines->GetLines();
00082     if(lines.empty())
00083         return;
00084     int found_line=-1;
00085     if(m_previewMode==mode_corrected)
00086     {
00087         HuginBase::PTools::Transform trans;
00088         trans.createTransform(m_panoimage,m_opts);
00089         double x;
00090         double y;
00091         if(!trans.transformImgCoord(x,y,pos.x,pos.y))
00092             return;
00093         pos.x=x;
00094         pos.y=y;
00095     }
00096     else
00097     {
00098         pos.x=hugin_utils::roundi(pos.x/m_scale);
00099         pos.y=hugin_utils::roundi(pos.y/m_scale);
00100     };
00101 
00102     //find line which is nearest the clicked position
00103     std::vector<double> min_distance(lines.size(),10000);
00104     double shortest_distance=10000;
00105     for(unsigned int i=0;i<lines.size();i++)
00106     {
00107         if(lines[i].status==HuginLines::valid_line || lines[i].status==HuginLines::valid_line_disabled)
00108         {
00109             for(unsigned int j=0;j<lines[i].line.size();j++)
00110             {
00111                 double distance=(lines[i].line[j]-pos).magnitude();
00112                 if(distance<min_distance[i])
00113                     min_distance[i]=distance;
00114             };
00115         };
00116         if(min_distance[i]<shortest_distance)
00117         {
00118             shortest_distance=min_distance[i];
00119             if(shortest_distance<50)
00120             {
00121                 found_line=i;
00122             };
00123         };
00124     };
00125     if(found_line==-1)
00126     {
00127         return;
00128     };
00129     if(e.LeftIsDown())
00130     {
00131         lines[found_line].status=HuginLines::valid_line_disabled;
00132     }
00133     else
00134     {
00135         lines[found_line].status=HuginLines::valid_line;
00136     };
00137     m_imageLines->SetLines(lines);
00138     wxGetApp().GetLensCalFrame()->UpdateListString(m_imageIndex);
00139     DrawView();
00140     Refresh();
00141 };
00142 
00143 void LensCalImageCtrl::DrawView()
00144 {
00145     if(m_imageLines==NULL)
00146         return;
00147     if(m_previewMode==mode_corrected)
00148     {
00149         m_display_img.Create(m_remapped_img.GetWidth(), m_remapped_img.GetHeight());
00150     }
00151     else
00152     {
00153         m_display_img.Create(m_scaled_img.GetWidth(), m_scaled_img.GetHeight());
00154     };
00155     wxMemoryDC memDC(m_display_img);
00156     HuginBase::PTools::Transform trans;
00157     // copy resized image into buffer
00158     if(m_previewMode==mode_corrected)
00159     {
00160         trans.createInvTransform(m_panoimage,m_opts);
00161         memDC.DrawBitmap(m_remapped_img,0,0,false);
00162     }
00163     else
00164     {
00165         memDC.DrawBitmap(m_scaled_img,0,0,false);
00166     };
00167     if(m_showLines)
00168     {
00169         HuginLines::Lines lines=m_imageLines->GetLines();
00170         for(unsigned int i=0;i<lines.size();i++)
00171         {
00172             if(lines[i].line.size()<2)
00173                 continue;
00174             switch(lines[i].status)
00175             {
00176                 case HuginLines::valid_line:
00177                     memDC.SetPen(wxPen(wxColour(0,255,0), 1, wxSOLID));
00178                     break;
00179                 case HuginLines::valid_line_disabled:
00180                     memDC.SetPen(wxPen(wxColour(255,0,0), 1, wxSOLID));
00181                     break;
00182                 default:
00183                     memDC.SetPen(wxPen(wxColour(128,128,128), 1, wxSOLID));
00184                     break;
00185             };
00186             for(unsigned int j=0;j<lines[i].line.size()-1;j++)
00187             {
00188                 int x1,y1,x2,y2;
00189                 if(m_previewMode==mode_corrected)
00190                 {
00191                     double x,y;
00192                     if(!trans.transformImgCoord(x,y,lines[i].line[j].x,lines[i].line[j].y))
00193                         continue;
00194                     x1=hugin_utils::roundi(x);
00195                     y1=hugin_utils::roundi(y);
00196                     if(!trans.transformImgCoord(x,y,lines[i].line[j+1].x,lines[i].line[j+1].y))
00197                         continue;
00198                     x2=hugin_utils::roundi(x);
00199                     y2=hugin_utils::roundi(y);
00200                 }
00201                 else
00202                 {
00203                     x1=hugin_utils::roundi(m_scale*lines[i].line[j].x);
00204                     y1=hugin_utils::roundi(m_scale*lines[i].line[j].y);
00205                     x2=hugin_utils::roundi(m_scale*lines[i].line[j+1].x);
00206                     y2=hugin_utils::roundi(m_scale*lines[i].line[j+1].y);
00207                 };
00208                 memDC.DrawLine(x1,y1,x2,y2);
00209             };
00210         };
00211     };
00212     memDC.SelectObject(wxNullBitmap);
00213 };
00214 
00215 void LensCalImageCtrl::Resize( wxSizeEvent & e )
00216 {
00217     if(m_imageLines==NULL || !m_img.Ok() || (m_previewMode==mode_edge && !m_edge.Ok()))
00218     {
00219         m_scaled_img.Create(0,0);
00220         m_display_img.Create(0,0);
00221         Refresh(true);
00222         return;
00223     }
00224     int x = GetSize().x;
00225     int y = GetSize().y;
00226     // scale to fit the window
00227     int new_width;
00228     int new_height;
00229 
00230     float r_img = (float)m_img.GetWidth() / (float)m_img.GetHeight();
00231     float r_window = (float)x/(float)y;
00232     if ( r_img > r_window )
00233     {
00234         m_scale = (float)x / m_img.GetWidth();
00235         new_width =  x;
00236         new_height = hugin_utils::roundi(m_scale * m_img.GetHeight());
00237     }
00238     else
00239     {
00240         m_scale = (float)y / m_img.GetHeight();
00241         new_height = y;
00242         new_width = hugin_utils::roundi(m_scale * m_img.GetWidth());
00243     }
00244     switch(m_previewMode)
00245     {
00246         case mode_original:
00247             m_scaled_img = wxBitmap(m_img.Scale (new_width, new_height));
00248             break;
00249         case mode_edge:
00250             m_scaled_img = wxBitmap(m_edge.Scale(new_width,new_height,wxIMAGE_QUALITY_HIGH));
00251             break;
00252         case mode_corrected:
00253             GenerateRemappedImage(new_width,new_height);
00254             break;
00255     };
00256     // draw new view into offscreen buffer
00257     DrawView();
00258     // eventually update the view
00259     Refresh(false);
00260 };
00261 
00262 // Define the repainting behaviour
00263 void LensCalImageCtrl::OnPaint(wxPaintEvent & dc)
00264 {
00265     wxPaintDC paintDC(this);
00266     if ( m_display_img.Ok() )
00267     {
00268         paintDC.DrawBitmap(m_display_img, 0,0, FALSE);
00269     }
00270 }
00271 
00272 void LensCalImageCtrl::SetImage(ImageLineList* newList, unsigned int newIndex)
00273 {
00274     m_imageLines=newList;
00275     m_imageIndex=newIndex;
00276     std::string filename(newList->GetFilename().mb_str(HUGIN_CONV_FILENAME));
00277     ImageCache::EntryPtr img = ImageCache::getInstance().getImage(filename);
00278     m_img = imageCacheEntry2wxImage(img);
00279     SetEdgeImage();
00280 
00281     wxSizeEvent e;
00282     Resize (e);
00283 }
00284 
00285 void LensCalImageCtrl::SetEmptyImage()
00286 {
00287     m_imageLines=NULL;
00288     m_img.Create(0,0,true);
00289     m_edge.Create(0,0,true);
00290     m_remapped_img.Create(0,0,true);
00291 
00292     wxSizeEvent e;
00293     Resize(e);
00294 };
00295 
00296 void LensCalImageCtrl::SetShowLines(bool showLines)
00297 {
00298     m_showLines=showLines;
00299     // draw new view into offscreen buffer
00300     DrawView();
00301     // eventually update the view
00302     Refresh(false);
00303 };
00304 
00305 void LensCalImageCtrl::SetMode(const LensCalPreviewMode newMode)
00306 {
00307     m_previewMode=newMode;
00308     wxSizeEvent e;
00309     Resize (e);
00310     Refresh(true);
00311 };
00312 
00313 void LensCalImageCtrl::SetLens(const HuginBase::SrcPanoImage::Projection newProjection,const double newFocallength, const double newCropfactor)
00314 {
00315     m_projection=newProjection;
00316     m_focallength=newFocallength;
00317     m_cropfactor=newCropfactor;
00318 };
00319 
00320 void LensCalImageCtrl::SetLensDistortions(const double newA, const double newB, const double newC, const double newD, const double newE)
00321 {
00322     m_a=newA;
00323     m_b=newB;
00324     m_c=newC;
00325     m_d=newD;
00326     m_e=newE;
00327     if(m_previewMode==mode_corrected)
00328     {
00329         wxSizeEvent e;
00330         Resize(e);
00331     };
00332 };
00333 
00334 vigra::RGBValue<vigra::UInt8> gray2RGB(vigra::UInt8 const& v)
00335 {
00336     return vigra::RGBValue<vigra::UInt8>(v,v,v);
00337 }  
00338 
00339 void LensCalImageCtrl::SetEdgeImage()
00340 {
00341     vigra::BImage* edgeImage=m_imageLines->GetEdgeImage();
00342     if(edgeImage->width()>0 && edgeImage->height()>0)
00343     {
00344         // we need to convert to RGB
00345         m_edgeImage.resize(edgeImage->width(),edgeImage->height());
00346         vigra::transformImage(srcImageRange(*edgeImage), destImage(m_edgeImage), &gray2RGB);
00347         m_edge.SetData((unsigned char*)m_edgeImage.data(),m_edgeImage.width(),m_edgeImage.height(),true);
00348     }
00349     else
00350     {
00351         m_edgeImage.resize(0,0);
00352         m_edge.Create(0,0,true);
00353     };
00354     wxSizeEvent e;
00355     Resize(e);
00356 };
00357 
00358 void LensCalImageCtrl::GenerateRemappedImage(const unsigned int newWidth,const unsigned int newHeight)
00359 {
00360     PT::RemappedPanoImage<vigra::BRGBImage,vigra::BImage>* remapped=new PT::RemappedPanoImage<vigra::BRGBImage,vigra::BImage>;
00361     AppBase::MultiProgressDisplay* progress=new AppBase::DummyMultiProgressDisplay();
00362     //generate SrcPanoImage with current settings
00363     m_panoimage=*(m_imageLines->GetPanoImage());
00364     m_panoimage.setProjection(m_projection);
00365     m_panoimage.setExifFocalLength(m_focallength);
00366     m_panoimage.setExifCropFactor(m_cropfactor);
00367     m_panoimage.setExposureValue(0);
00368     m_panoimage.setVar("a",m_a);
00369     m_panoimage.setVar("b",m_b);
00370     m_panoimage.setVar("c",m_c);
00371     m_panoimage.setVar("d",m_d);
00372     m_panoimage.setVar("e",m_e);
00373     double hfov=HuginBase::SrcPanoImage::calcHFOV(m_panoimage.getProjection(),m_panoimage.getExifFocalLength(),m_panoimage.getExifCropFactor(),m_panoimage.getSize());
00374     m_panoimage.setHFOV(hfov);
00375 
00376     std::string filename(m_imageLines->GetFilename().mb_str(HUGIN_CONV_FILENAME));
00377     ImageCache::EntryPtr img = ImageCache::getInstance().getImage(filename);
00378     //fill options with current settings
00379     switch(m_projection)
00380     {
00381         case HuginBase::SrcPanoImage::RECTILINEAR:
00382             m_opts.setProjection(HuginBase::PanoramaOptions::RECTILINEAR);
00383             break;
00384         case HuginBase::SrcPanoImage::PANORAMIC:
00385             m_opts.setProjection(HuginBase::PanoramaOptions::CYLINDRICAL);
00386             break;
00387         case HuginBase::SrcPanoImage::CIRCULAR_FISHEYE:
00388         case HuginBase::SrcPanoImage::FULL_FRAME_FISHEYE:
00389             m_opts.setProjection(HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE);
00390             break;
00391         case HuginBase::SrcPanoImage::EQUIRECTANGULAR:
00392             m_opts.setProjection(HuginBase::PanoramaOptions::EQUIRECTANGULAR);
00393             break;
00394         case HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC:
00395             m_opts.setProjection(HuginBase::PanoramaOptions::ORTHOGRAPHIC);
00396             break;
00397         case HuginBase::SrcPanoImage::FISHEYE_STEREOGRAPHIC:
00398             m_opts.setProjection(HuginBase::PanoramaOptions::STEREOGRAPHIC);
00399             break;
00400         case HuginBase::SrcPanoImage::FISHEYE_EQUISOLID:
00401             m_opts.setProjection(HuginBase::PanoramaOptions::EQUISOLID);
00402             break;
00403         case HuginBase::SrcPanoImage::FISHEYE_THOBY:
00404             m_opts.setProjection(HuginBase::PanoramaOptions::THOBY_PROJECTION);
00405             break;
00406     };
00407     m_opts.setHeight(newHeight);
00408     m_opts.setWidth(newWidth,false);
00409     m_opts.setHFOV(m_panoimage.getHFOV(),false);
00410     m_opts.setROI(vigra::Rect2D(0,0,m_opts.getWidth(),m_opts.getHeight()));
00411     //now remap image
00412     remapped->setPanoImage(m_panoimage,m_opts, m_opts.getROI());
00413     remapped->remapImage(vigra::srcImageRange(*(img->get8BitImage())),vigra_ext::INTERP_CUBIC,*progress);
00414     m_remappedImage=remapped->m_image;
00415     m_remapped_img.SetData((unsigned char*)m_remappedImage.data(),m_remappedImage.width(),m_remappedImage.height(),true);
00416     delete remapped;
00417     delete progress;
00418 
00419 };
00420 
00421 IMPLEMENT_DYNAMIC_CLASS(LensCalImageCtrl, wxPanel)
00422 
00423 LensCalImageCtrlXmlHandler::LensCalImageCtrlXmlHandler() : wxXmlResourceHandler()
00424 {
00425     AddWindowStyles();
00426 }
00427 
00428 wxObject *LensCalImageCtrlXmlHandler::DoCreateResource()
00429 {
00430     XRC_MAKE_INSTANCE(cp, LensCalImageCtrl)
00431     cp->Create(m_parentAsWindow, GetID(), GetPosition(), GetSize(), GetStyle(wxT("style")), GetName());
00432     SetupWindow(cp);
00433     return cp;
00434 }
00435 
00436 bool LensCalImageCtrlXmlHandler::CanHandle(wxXmlNode *node)
00437 {
00438     return IsOfClass(node, wxT("LensCalCanvas"));
00439 }
00440 
00441 IMPLEMENT_DYNAMIC_CLASS(LensCalImageCtrlXmlHandler, wxXmlResourceHandler)

Generated on 25 Oct 2014 for Hugintrunk by  doxygen 1.4.7