PreviewDifferenceTool.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00022 #include "PreviewDifferenceTool.h"
00023 #include <config.h>
00024 #if !defined Hugin_shared || !defined _WINDOWS
00025 #define GLEW_STATIC
00026 #endif
00027 #include <GL/glew.h>
00028 #include <wx/platform.h>
00029 #ifdef __WXMAC__
00030 #include <OpenGL/gl.h>
00031 #else
00032 #include <GL/gl.h>
00033 #endif
00034 
00035 // This is the number of times to double the result of the difference. It should
00036 // be between 0 and 7. Note that with  values > 0 no extra colours are used
00037 // (infact less are due to clipping), but the difference becomes easier to see.
00038 #define DIFFERENCE_DOUBLE 2
00039 
00040 PreviewDifferenceTool::PreviewDifferenceTool(ToolHelper *helper)
00041     : Tool(helper)
00042 {
00043     // rather boring constructor
00044 }
00045 
00047 bool PreviewDifferenceTool::CheckOpenGLCanDifference()
00048 {
00049     if(GLEW_ARB_imaging)
00050         return true;
00051     if((glBlendEquation!=NULL) && (GLEW_EXT_blend_subtract))
00052         return true;
00053     return false;
00054 }
00055 
00056 void PreviewDifferenceTool::Activate()
00057 {
00058     over_image = false;
00059     // Activate difference tool only if OpenGL extension GL_ARB_imaging is available
00060     // cause the extension contains required functions like glBlendEquation
00061     // In general this check should be superfluous, due to the fact that the preview frame
00062     // must check the OpenGL capabilities and never call this method if differencing is
00063     // not supported, but check twice is saver.
00064     if (CheckOpenGLCanDifference())
00065     {
00066         helper->NotifyMe(PreviewToolHelper::IMAGES_UNDER_MOUSE_CHANGE, this);
00067     }
00068 }
00069 
00070 void PreviewDifferenceTool::ImagesUnderMouseChangedEvent()
00071 {
00072     std::set<unsigned int> image_set = helper->GetImageNumbersUnderMouse();
00073     if (!image_set.empty())
00074     {
00075         // stop showing the previous one if there was one, if there wasn't, we
00076         // need to be able to draw over the preview.
00077         if (over_image)
00078         {
00079             helper->DoNotNotifyMeBeforeDrawing(image_number, this);
00080         } else {
00081             helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this);
00082             helper->NotifyMe(PreviewToolHelper::DRAW_UNDER_IMAGES, this);
00083         }
00084         // The lowest image number is drawn first, since the set is sorted.
00085         // Get notifications so we can draw it:
00086         image_number = *(image_set.begin());
00087         helper->NotifyMeBeforeDrawing(image_number, this);
00088         // Redraw the panorama with this image negated from the others.
00089         helper->GetVisualizationStatePtr()->ForceRequireRedraw();
00090         helper->GetVisualizationStatePtr()->Redraw();
00091         over_image = true;
00092     } else {
00093         if (over_image)
00094         {
00095             // We were showing a difference, now there are no images under the
00096             // mouse pointer:
00097             // Drop notifications, we don't need to do anything extra.
00098             over_image = false;
00099             helper->DoNotNotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this);
00100             helper->DoNotNotifyMe(PreviewToolHelper::DRAW_UNDER_IMAGES, this);
00101             helper->DoNotNotifyMeBeforeDrawing(image_number, this);
00102             // redraw the panorama without the negated image.
00103             helper->GetVisualizationStatePtr()->ForceRequireRedraw();
00104             helper->GetVisualizationStatePtr()->Redraw();
00105         }
00106     }
00107 }
00108 
00109 
00110 void PreviewDifferenceTool::AfterDrawImagesEvent()
00111 {
00112     // Get the display list used to generate the image
00113     unsigned int display_list;
00114         display_list = helper->GetVisualizationStatePtr()->GetMeshDisplayList(image_number);    
00115     TextureManager *tex_m = helper->GetViewStatePtr()->GetTextureManager();
00116     tex_m->BindTexture(image_number);
00117     // we will use a subtractive blend
00118     glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
00119     // multiply by the alpha value, so transparent areas appear black.
00120     glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
00121     glEnable(GL_BLEND);
00122     if (tex_m->GetPhotometricCorrect())
00123     {
00124         // The texture has full photometric correction, we can subtract it once
00125         // and be done.
00126         glCallList(display_list);
00127     } else {
00128         // otherwise we have to fake some of the photometric correction to get
00129         // good white balance and exposure.
00130         HuginBase::SrcPanoImage *img;
00131         img = helper->GetViewStatePtr()->GetSrcImage(image_number);
00132         float viewer_exposure = 1.0 / pow(2.0,
00133                     helper->GetPanoramaPtr()->getOptions().outputExposureValue);
00134         float es = viewer_exposure / img->getExposure();
00135         float scale[3] = {es / img->getWhiteBalanceRed(),
00136                           es,
00137                           es / img->getWhiteBalanceBlue()};
00138         // now we draw repeatedly until the image has been exposed properly.
00139         while (scale[0] > 0.0 && scale[1] > 0.0 && scale[2] > 0.0)
00140         {
00141             glColor3fv(scale);
00142             glCallList(display_list);
00143             scale[0] -= 1.0; scale[1] -= 1.0; scale[2] -= 1.0;
00144         }
00145         glColor3f(1.0, 1.0, 1.0);
00146     }
00147     glBlendEquation(GL_FUNC_ADD);
00148     // To make the difference stand out more, multiply it a few times:
00149     tex_m->DisableTexture();
00150     glBlendFunc(GL_DST_COLOR, GL_ONE);
00151     for (unsigned short int count = 0; count < DIFFERENCE_DOUBLE; count++)
00152     {
00153         glCallList(display_list);
00154     }
00155     glEnable(GL_TEXTURE_2D);
00156     glDisable(GL_BLEND);
00157 }
00158 
00159 //draw the images below all other images so that the difference is not computed agains something drawn in the background
00160 void PreviewDifferenceTool::BeforeDrawImagesEvent()
00161 {
00162     unsigned int display_list = helper->GetVisualizationStatePtr()->GetMeshDisplayList(image_number);    
00163     helper->GetViewStatePtr()->GetTextureManager()->DrawImage(image_number, display_list);
00164 }
00165 
00166 
00167 bool PreviewDifferenceTool::BeforeDrawImageEvent(unsigned int image)
00168 {
00169     return false;
00170 }
00171 

Generated on Fri Aug 22 01:25:38 2014 for Hugintrunk by  doxygen 1.3.9.1