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

Generated on 31 Aug 2015 for Hugintrunk by  doxygen 1.4.7