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

Generated on 30 Aug 2016 for Hugintrunk by  doxygen 1.4.7