TuttleOFX  1
HistogramPlugin.cpp
Go to the documentation of this file.
00001 #include "HistogramPlugin.hpp"
00002 #include "HistogramProcess.hpp"
00003 
00004 #include <boost/gil/gil_all.hpp>
00005 
00006 #include <boost/smart_ptr/scoped_array.hpp>
00007 
00008 namespace tuttle {
00009 namespace plugin {
00010 namespace histogram {
00011 
00012 /*
00013  * fecth plugin IHM parameters with plugin parameters pointer
00014  */
00015 HistogramPlugin::HistogramPlugin( OfxImageEffectHandle handle )
00016 : ImageEffectGilPlugin( handle )
00017 {
00018         _paramGlobalDisplaySelection = fetchBooleanParam( kGlobalDisplay ); //global display
00019 
00020         _paramColorRGBSelection = fetchParametricParam( kParamRGBColorSelection ); //curve RGB
00021         _paramOverlayRSelection = fetchBooleanParam( kBoolRed ); //R (is channel selected?)
00022         _paramMutliplierR = fetchDoubleParam(kMultiplierRed); //R multiplier
00023         
00024         _paramOverlayGSelection = fetchBooleanParam( kBoolGreen ); //G (is channel selected?)
00025         _paramMutliplierG = fetchDoubleParam(kMultiplierGreen); //G multiplier
00026         
00027         _paramOverlayBSelection = fetchBooleanParam( kBoolBlue ); //B (is channel selected?)
00028         _paramMutliplierB = fetchDoubleParam(kMultiplierBlue); //B multiplier
00029         
00030         _resetRGB = fetchPushButtonParam( kButtonResetRGB ); //reset RGB button
00031 
00032         _paramColorHSLSelection = fetchParametricParam( kParamHSLColorSelection ); //curve HSL
00033         _paramOverlayHSelection = fetchBooleanParam( kBoolHue ); //H (is channel selected?)
00034         _paramMutliplierH = fetchDoubleParam(kMultiplierHue); //H multiplier
00035         
00036         _paramOverlaySSelection = fetchBooleanParam( kBoolSaturation ); //S (is channel selected?)
00037         _paramMutliplierS = fetchDoubleParam(kMultiplierSaturation); //S multiplier
00038         
00039         _paramOverlayLSelection = fetchBooleanParam( kBoolLightness ); //L (is channel selected?)
00040         _paramMutliplierL = fetchDoubleParam(kMultiplierLightness); //L multiplier
00041         
00042         _resetHSL = fetchPushButtonParam( kButtonResetHSL ); //Reset HSL button
00043 
00044         _paramDisplayTypeSelection = fetchChoiceParam( kHistoDisplayListParamLabel ); //histogram display list (Histogram overlay group)
00045         _paramResetAll = fetchPushButtonParam( kButtonResetAll ); //Reset all button (Histogram overlay group)
00046 
00047         _paramDisplaySelection = fetchBooleanParam( kBoolSelection ); //display selection on source clip (Selection group)
00048         _paramSelectionMode = fetchChoiceParam( kSelectionModeListParamLabel ); //selection mode (Selection group)
00049         _paramSelectionFromCurve = fetchIntParam( kprecisionCurveFromSelection ); //precision of selection to curve (selection group)
00050         
00051         _paramSelectionMultiplierSelection = fetchDoubleParam( kselectionMultiplier ); //selection multiplier (Advanced group)
00052         _paramRefreshOverlaySelection = fetchPushButtonParam( kButtonRefreshOverlay ); //refresh overlay (Advanced group)
00053         _paramNbStepSelection = fetchIntParam( knbStepRange ); //nb step range (Advanced group)
00054         _paramClampCurveValues = fetchBooleanParam(kBoolClampValues); //clamp curve values (Advanced group)
00055 
00056         _paramOutputSettingSelection = fetchChoiceParam( kOutputListParamLabel ); //output type (BW/alpha)
00057         _paramReverseMaskSelection = fetchBooleanParam( kBoolReverseMask ); //reverse mask
00058         
00059         _paramButtonAppendToSelectionHSL = fetchPushButtonParam(kButtonAppendSelectionToCurveHSL);      //Append to selection HSL (HSL group)
00060         _paramButtonAppendToSelectionRGB = fetchPushButtonParam(kButtonAppendSelectionToCurveRGB);      //Append to selection RGB (RGB group)
00061 
00062         //Reset param booleans
00063         _isCleaned = false;
00064         _isNbStepChanged = false;
00065         _isHistogramRefresh = false;
00066 
00067         //Initialize scoped pointer
00068         _overlayDataCount = 0;
00069 
00070         /// @todo: HACK to display curves default position
00071         OFX::InstanceChangedArgs changed( this->timeLineGetTime( ) );
00072         changedParam( changed, kButtonResetAll );
00073         changedClip( changed, kOfxImageEffectSimpleSourceClipName );
00074 }
00075 
00076 /*
00077  * create and return HistogramProcessParams structure for process
00078  */
00079 HistogramProcessParams<HistogramPlugin::Scalar> HistogramPlugin::getProcessParams( const OfxTime time, const OfxPointD& renderScale ) const
00080 {
00081         HistogramProcessParams<Scalar> params;
00082 
00083         params._paramColorRGB = _paramColorRGBSelection; //curve RGB
00084         params._boolRGB[0] = _paramOverlayRSelection; //R (is channel selected?)
00085         params._boolRGB[1] = _paramOverlayGSelection; //G (is channel selected?)
00086         params._boolRGB[2] = _paramOverlayBSelection; //B (is channel selected?)
00087 
00088         params._paramColorHSL = _paramColorHSLSelection; //curve HSL
00089         params._boolHSL[0] = _paramOverlayHSelection; //H (is channel selected?)
00090         params._boolHSL[1] = _paramOverlaySSelection; //S (is channel selected?)
00091         params._boolHSL[2] = _paramOverlayLSelection; //L (is channel selected?)
00092         
00093         params._multiplierRGB[0] = _paramMutliplierR; //R multiplier
00094         params._multiplierRGB[1] = _paramMutliplierG; //G multiplier
00095         params._multiplierRGB[2] = _paramMutliplierB; //B multiplier
00096         
00097         params._multiplierHSL[0] = _paramMutliplierH; //H multiplier
00098         params._multiplierHSL[1] = _paramMutliplierS; //S multiplier
00099         params._multiplierHSL[2] = _paramMutliplierL; //L multiplier
00100         
00101         params._paramOutputSetting = _paramOutputSettingSelection; //output selection (alpha channel or BW)
00102         params._boolReverseMask = _paramReverseMaskSelection; //reverse mask check box
00103         params._boolClampCurveValues =  _paramClampCurveValues;         //clamp curve values (Advanced group)
00104 
00105         return params;
00106 }
00107 
00108 /*
00109  * a plugin parameter as been changed
00110  */
00111 void HistogramPlugin::changedParam( const OFX::InstanceChangedArgs &args, const std::string &paramName )
00112 {
00113 
00114         /*Clean buttons*/
00115         if( paramName == kButtonResetRGB || paramName == kButtonResetHSL || paramName == kButtonResetAll ) //HSL or RGB or both
00116         {
00117                 //get nb points for each curve (RGB)
00118                 std::vector<std::size_t> nbControlPointsRGB( nbCurvesRGB ); //initialize vector
00119                 for( std::size_t i = 0; i < nbCurvesRGB; ++i ) //fill up vector
00120                 {
00121                         nbControlPointsRGB[i] = _paramColorRGBSelection->getNControlPoints( i, args.time );
00122                 }
00123 
00124                 //get nb points for each curve (HSL)
00125                 std::vector<std::size_t> nbControlPointsHSL( nbCurvesHSL ); //initialize vector
00126                 for( std::size_t i = 0; i < nbCurvesHSL; ++i ) //fill up vector
00127                 {
00128                         nbControlPointsHSL[i] = _paramColorHSLSelection->getNControlPoints( i, args.time );
00129                 }
00130 
00131                 //reset RGB curves
00132                 if( paramName == kButtonResetRGB || paramName == kButtonResetAll )//RGB or Clean all
00133                 {
00134                         for( std::size_t channel = 0; channel < nbCurvesRGB; ++channel )
00135                         {
00136                                 if(             paramName == kButtonResetAll ||                                                                 // if button is Reset all curves
00137                                                 (channel == 0 && _paramOverlayRSelection->getValue()) ||                // else if button is Reset RGB and Red is selected
00138                                                 (channel == 1 && _paramOverlayGSelection->getValue()) ||                // else if button is Reset RGB and Green is selected
00139                                                 (channel ==     2 && _paramOverlayBSelection->getValue()) )                     // else if button is Reset RGB and Blue is selected
00140                                 {
00141                                         _paramColorRGBSelection->deleteControlPoint( channel );
00142                                 }
00143                         }
00144                         for( std::size_t i = 0; i < nbCurvesRGB; ++i )//replace default points
00145                         {
00146                                 if(             paramName == kButtonResetAll ||                                                                 // if button is Reset all curves
00147                                                 (i == 0 && _paramOverlayRSelection->getValue()) ||              // else if button is Reset RGB and Red is selected
00148                                                 (i == 1 && _paramOverlayGSelection->getValue()) ||              // else if button is Reset RGB and Green is selected
00149                                                 (i == 2 && _paramOverlayBSelection->getValue()) )                       // else if button is Reset RGB and Blue is selected
00150                                 {
00151                                         _paramColorRGBSelection->addControlPoint( i, args.time, 0.0, 0.0, false );
00152                                         _paramColorRGBSelection->addControlPoint( i, args.time, 0.2, 1.0, false );
00153                                         _paramColorRGBSelection->addControlPoint( i, args.time, 0.6, 1.0, false );
00154                                         _paramColorRGBSelection->addControlPoint( i, args.time, 1.0, 0.0, false );
00155                                 }
00156                         }
00157                 }
00158                 //reset HSL curves
00159                 if( paramName == kButtonResetHSL || paramName == kButtonResetAll )//HSL or Clean all
00160                 {
00161                         for( std::size_t channel = 0; channel < nbCurvesHSL; ++channel )
00162                         {
00163                                 if(             paramName == kButtonResetAll ||                                                                 // if button is Reset all curves
00164                                                 (channel == 0 && _paramOverlayHSelection->getValue()) ||                // else if button is Reset HSL and Hue is selected
00165                                                 (channel == 1 && _paramOverlaySSelection->getValue()) ||                // else if button is Reset HSL and Saturation is selected
00166                                                 (channel ==     2 && _paramOverlayLSelection->getValue()) )                     // else if button is Reset HSL and Lightness is selected
00167                                 {
00168                                         _paramColorHSLSelection->deleteControlPoint( channel );
00169                                 }
00170                         }
00171                         for( std::size_t i = 0; i < nbCurvesHSL; ++i )//replace default points
00172                         {
00173                                 if(             paramName == kButtonResetAll ||                                                 // if button is Reset all curves
00174                                 (               i == 0 && _paramOverlayHSelection->getValue()) ||               // else if button is Reset HSL and Hue is selected
00175                                 (               i == 1 && _paramOverlaySSelection->getValue()) ||               // else if button is Reset HSL and Saturation is selected
00176                                 (               i == 2 && _paramOverlayLSelection->getValue()) )                // else if button is Reset HSL and Lightness is selected
00177                                 {
00178                                         _paramColorHSLSelection->addControlPoint( i, args.time, 0.0, 0.0, false );
00179                                         _paramColorHSLSelection->addControlPoint( i, args.time, 0.2, 1.0, false );
00180                                         _paramColorHSLSelection->addControlPoint( i, args.time, 0.6, 1.0, false );
00181                                         _paramColorHSLSelection->addControlPoint( i, args.time, 1.0, 0.0, false );
00182                                 }
00183                         }
00184                 }
00185                 /// @todo How to request a redraw on ParametricParameters?
00186                 //      _paramColorHSLSelection->getProps().propGetPointer( kOfxParamPropParametricInteractBackground );
00187         }
00188 
00189                 /*refresh histogram overlay*/
00190         else if( paramName == kButtonRefreshOverlay )
00191         {
00192                 //Draw forced
00193                 OFX::InstanceChangedArgs changed( args.time, args.renderScale );
00194                 this->changedClip( changed, this->_clipSrc->name( ) );
00195         }
00196                 /*nbStep changed*/
00197         else if( paramName == knbStepRange )
00198         {
00199                 if( this->hasOverlayData( ) ) //if there is overlay value
00200                 {
00201                         getOverlayData().setNbStep( _paramNbStepSelection->getValue( ) ); //change nbStep value
00202                         // getOverlayData( ).computeFullData( this->_clipSrc, args.time, args.renderScale ); //reset buffer and compute them
00203                         getOverlayData()._isDataInvalid = true;
00204                 }
00205         }
00206         /*Clear user selection*/
00207         else if( paramName == kButtonResetSelection )
00208         {
00209                 if( this->hasOverlayData( ) )//if there is overlay value
00210                 {
00211                         this->getOverlayData( ).clearSelection( ); //clear selection
00212                 }
00213         }
00214         /*Selection to curve */
00215         else if( paramName == kButtonSelectionToCurveHSL || paramName == kButtonSelectionToCurveRGB )
00216         {
00217                 //prepare buffer
00218                 getOverlayData()._vNbStepCurveFromSelection = _paramSelectionFromCurve->getValue();                             //change precision step (precision)
00219                 getOverlayData().computeCurveFromSelectionData( this->_clipSrc,args.time, args.renderScale);    //compute curves
00220 
00221                 //getOverlayData().resetCurvesFromSelectionData();      //reset curve from selection buffer data
00222                 //RGB
00223                 if( paramName == kButtonSelectionToCurveRGB )
00224                 {                       
00225                         //get nb points for each curve (RGB)
00226                         std::vector<std::size_t> nbControlPointsRGB( nbCurvesRGB ); //initialize vector
00227                         for( std::size_t i = 0; i < nbCurvesRGB; ++i ) //fill up vector
00228                         {
00229                                 nbControlPointsRGB[i] = _paramColorRGBSelection->getNControlPoints( i, args.time );
00230                         }
00231                         
00232                         //Delete all points on selected RGB curves
00233                         for( std::size_t channel = 0; channel < nbCurvesRGB; ++channel )
00234                         {
00235                                 if(             paramName == kButtonResetAll ||                                                                 // if button is Reset all curves
00236                                                 (channel == 0 && _paramOverlayRSelection->getValue()) ||                // else if button is Reset RGB and Red is selected
00237                                                 (channel == 1 && _paramOverlayGSelection->getValue()) ||                // else if button is Reset RGB and Green is selected
00238                                                 (channel ==     2 && _paramOverlayBSelection->getValue()) )                     // else if button is Reset RGB and Blue is selected
00239                                 {
00240                                         _paramColorRGBSelection->deleteControlPoint( channel );
00241                                 }
00242                         }
00243                         //For all selected channel create new curves from selection
00244                         
00245                         for( std::size_t i = 0; i < nbCurvesRGB; ++i )
00246                         {
00247                                 if(             paramName == kButtonResetAll ||                                                 // if button is Reset all curves
00248                                                 (i == 0 && _paramOverlayRSelection->getValue()) ||              // else if button is Reset RGB and Red is selected
00249                                                 (i == 1 && _paramOverlayGSelection->getValue()) ||              // else if button is Reset RGB and Green is selected
00250                                                 (i == 2 && _paramOverlayBSelection->getValue()) )               // else if button is Reset RGB and Blue is selected
00251                                 {
00252                                         //getMax of current selection buffer
00253                                         double maxChannel; //will contain max of the current channel (RGB)
00254                                         if(i == 0)      //working on Red channel
00255                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferRed.begin(),getOverlayData()._curveFromSelection._bufferRed.end()));
00256                                         else if(i == 1)//working on Green channel
00257                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferGreen.begin(),getOverlayData()._curveFromSelection._bufferGreen.end()));
00258                                         else //working on Blue channel
00259                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferBlue.begin(),getOverlayData()._curveFromSelection._bufferBlue.end()));
00260                                         
00261                                         //Add points to current channel
00262                                         double xPosition = 0.0;
00263                                         double yPosition = 0.0;
00264                                         double step =  (double)(1/(double)(getOverlayData()._vNbStepCurveFromSelection-1));     //compute step for curve display
00265                                         
00266                                         //for each point
00267                                         for(unsigned int x=0; x<getOverlayData()._vNbStepCurveFromSelection; ++x)
00268                                         {
00269                                                 if(i == 0)      //working on Red channel
00270                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferRed[x]));             //get current Y if Red selection buffer
00271                                                 else if(i == 1) //working on Green channel
00272                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferGreen[x]));           //get current Y if Green selection buffer
00273                                                 else    //working on Blue channel
00274                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferBlue[x]));            //get current Y if Blue selection buffer
00275                                                 
00276                                                 yPosition/=maxChannel; //yPosition between 0 and 1
00277                                                 
00278                                                 if(x==0 || x == getOverlayData()._vNbStepCurveFromSelection-1)  //current point is last of first
00279                                                         _paramColorRGBSelection->addControlPoint( i, args.time,xPosition, yPosition, false );   //place the current point
00280                                                 else //filter 
00281                                                 {
00282                                                         double value;
00283                                                         double nextValue;
00284                                                         double previousValue;
00285                                                         if(i == 0)//Red channel
00286                                                         {
00287                                                                 value= (double)getOverlayData()._curveFromSelection._bufferRed[x];                              //get actual value
00288                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferRed[x+1];               //get next value
00289                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferRed[x-1];   //get previous value
00290                                                         }
00291                                                         else if(i == 1)//Green channel
00292                                                         {
00293                                                                 value= (double)getOverlayData()._curveFromSelection._bufferGreen[x];                    //get actual value
00294                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferGreen[x+1];             //get next value
00295                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferGreen[x-1]; //get previous value
00296                                                         }
00297                                                         else //Blue channel
00298                                                         {
00299                                                                 value= (double)getOverlayData()._curveFromSelection._bufferBlue[x];                             //get actual value
00300                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferBlue[x+1];              //get next value
00301                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferBlue[x-1];  //get previous value
00302                                                         }
00303                                                         
00304                                                         value/=maxChannel;                              //set value between 0 and 1
00305                                                         nextValue/=maxChannel;                  //set next value between 0 and 1
00306                                                         previousValue/=maxChannel;              //set previous value between 0 and 1
00307                                                         
00308                                                         double betweenNextAndValue = (double)(nextValue-value);                 //get interval between value and next  (0<= interval <=1)
00309                                                         double betweenPreviousAndValue = (double)(value-previousValue); //get interval between value and previous (0<= interval <=1)
00310                                                         //get absolute values
00311                                                         if(betweenNextAndValue<0)               //change betweenNextAndValue negative to positive
00312                                                                 betweenNextAndValue*=-1;
00313                                                         if(betweenPreviousAndValue<0)   //change betweenPreviousAndValue negative to positive
00314                                                                 betweenPreviousAndValue*=-1;
00315                                                         
00316                                                         if(betweenNextAndValue> 0.01 || betweenPreviousAndValue > 0.01)
00317                                                                 _paramColorRGBSelection->addControlPoint(i,args.time,xPosition,yPosition,false);
00318                                                 }
00319                                                 xPosition += step; //add step to Xposition
00320                                         }
00321                                         
00322                                 }
00323                         }
00324                 }
00325                 
00326                 //HSL
00327                 if( paramName == kButtonSelectionToCurveHSL )
00328                 {
00329                         //get nb points for each curve (RGB)
00330                         std::vector<std::size_t> nbControlPointsHSL( nbCurvesHSL ); //initialize vector
00331                         for( std::size_t i = 0; i < nbCurvesHSL; ++i ) //fill up vector
00332                         {
00333                                 nbControlPointsHSL[i] = _paramColorHSLSelection->getNControlPoints( i, args.time );
00334                         }
00335                         
00336                         //Delete all points on selected RGB curves
00337                         for( std::size_t channel = 0; channel < nbCurvesHSL; ++channel )
00338                         {
00339                                 if(             paramName == kButtonResetAll ||                                                                 // if button is Reset all curves
00340                                                 (channel == 0 && _paramOverlayHSelection->getValue()) ||                // else if button is Reset HSL and Hue is selected
00341                                                 (channel == 1 && _paramOverlaySSelection->getValue()) ||                // else if button is Reset HSL and Saturation is selected
00342                                                 (channel ==     2 && _paramOverlayLSelection->getValue()) )                     // else if button is Reset HSL and Lightness is selected
00343                                 {
00344                                         _paramColorHSLSelection->deleteControlPoint( channel );
00345                                 }
00346                         }
00347                         //For all selected channel create new curves from selection
00348                         for( std::size_t i = 0; i < nbCurvesHSL; ++i )
00349                         {
00350                                 if(             paramName == kButtonResetAll ||                                                 // if button is Reset all curves
00351                                                 (i == 0 && _paramOverlayHSelection->getValue()) ||              // else if button is Reset HSL and Hue is selected
00352                                                 (i == 1 && _paramOverlaySSelection->getValue()) ||              // else if button is Reset HSL and Saturation is selected
00353                                                 (i == 2 && _paramOverlayLSelection->getValue()) )               // else if button is Reset HSL and Lightness is selected
00354                                 {
00355                                         //getMax of current selection buffer
00356                                         double maxChannel; //will contain max of the current channel (HSL)
00357                                         if(i == 0)      //working on Hue channel
00358                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferHue.begin(),getOverlayData()._curveFromSelection._bufferHue.end()));
00359                                         else if(i == 1)//working on Saturation channel
00360                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferSaturation.begin(),getOverlayData()._curveFromSelection._bufferSaturation.end()));
00361                                         else //working on Lightness channel
00362                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferLightness.begin(),getOverlayData()._curveFromSelection._bufferLightness.end()));
00363                                         
00364                                         //Add points to current channel
00365                                         double xPosition = 0.0;
00366                                         double yPosition = 0.0;
00367                                         double step =  (double)(1/(double)(getOverlayData()._vNbStepCurveFromSelection-1));     //compute step for curve display
00368                                         
00369                                         //for each point
00370                                         for( unsigned int x=0; x<getOverlayData()._vNbStepCurveFromSelection; ++x )
00371                                         {
00372                                                 if(i == 0)      //working on Hue channel
00373                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferHue[x]));             //get current Y if Hue selection buffer
00374                                                 else if(i == 1) //working on Saturation channel
00375                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferSaturation[x]));      //get current Y if Saturation selection buffer
00376                                                 else    //working on Lightness channel
00377                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferLightness[x]));               //get current Y if Lightness selection buffer
00378                                                 
00379                                                 yPosition/=maxChannel; //yPosition between 0 and 1
00380                                                 
00381                                                 if( x==0 || x == getOverlayData()._vNbStepCurveFromSelection-1 )        //current point is last of first
00382                                                         _paramColorHSLSelection->addControlPoint( i, args.time,xPosition, yPosition, false );   //place the current point
00383                                                 else //filter 
00384                                                 {
00385                                                         double value;
00386                                                         double nextValue;
00387                                                         double previousValue;
00388                                                         if( i == 0 )//Hue channel
00389                                                         {
00390                                                                 value= (double)getOverlayData()._curveFromSelection._bufferHue[x];                              //get actual value
00391                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferHue[x+1];               //get next value
00392                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferHue[x-1];   //get previous value
00393                                                         }
00394                                                         else if( i == 1 )//Saturation channel
00395                                                         {
00396                                                                 value= (double)getOverlayData()._curveFromSelection._bufferSaturation[x];                               //get actual value
00397                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferSaturation[x+1];                //get next value
00398                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferSaturation[x-1];    //get previous value
00399                                                         }
00400                                                         else //Lightness channel
00401                                                         {
00402                                                                 value= (double)getOverlayData()._curveFromSelection._bufferLightness[x];                        //get actual value
00403                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferLightness[x+1];         //get next value
00404                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferLightness[x-1];     //get previous value
00405                                                         }
00406                                                         
00407                                                         value/=maxChannel;                              //set value between 0 and 1
00408                                                         nextValue/=maxChannel;                  //set next value between 0 and 1
00409                                                         previousValue/=maxChannel;              //set previous value between 0 and 1
00410                                                         
00411                                                         double betweenNextAndValue = (double)(nextValue-value);                 //get interval between value and next  (0<= interval <=1)
00412                                                         double betweenPreviousAndValue = (double)(value-previousValue); //get interval between value and previous (0<= interval <=1)
00413                                                         //get absolute values
00414                                                         if(betweenNextAndValue<0)               //change betweenNextAndValue negative to positive
00415                                                                 betweenNextAndValue*=-1;
00416                                                         if(betweenPreviousAndValue<0)   //change betweenPreviousAndValue negative to positive
00417                                                                 betweenPreviousAndValue*=-1;
00418                                                         
00419                                                         if(betweenNextAndValue> 0.01 || betweenPreviousAndValue > 0.01)
00420                                                                 _paramColorHSLSelection->addControlPoint(i,args.time,xPosition,yPosition,false);
00421                                                 }
00422                                                 xPosition += step; //add step to Xposition
00423                                         }
00424                                         
00425                                 }
00426                         }
00427                 }
00428         }
00429         //Append to curve
00430         if(paramName == kButtonAppendSelectionToCurveHSL || paramName == kButtonAppendSelectionToCurveRGB)
00431         {
00432                 //prepare buffer (compute with curve precision)
00433                 getOverlayData()._vNbStepCurveFromSelection = _paramSelectionFromCurve->getValue();                             //change precision step (precision)
00434                 getOverlayData().computeCurveFromSelectionData( this->_clipSrc,args.time, args.renderScale);    //compute curves
00435                 if( paramName == kButtonAppendSelectionToCurveHSL )                                                                                             //Append to curve (HSL)
00436                 {
00437                         for(unsigned int i=0; i<nbCurvesHSL; ++i)
00438                         {
00439                                 if(     (i == 0 && _paramOverlayHSelection->getValue()) ||              // if button is append and Hue is selected
00440                                         (i == 1 && _paramOverlaySSelection->getValue()) ||              // else if button append and Saturation is selected
00441                                         (i == 2 && _paramOverlayLSelection->getValue()) )               // else if button append and Lightness is selected
00442                                 {
00443                                         //getMax of current selection buffer
00444                                         double maxChannel; //will contain max of the current channel (HSL)
00445                                         if(i == 0)      //working on Hue channel
00446                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferHue.begin(),getOverlayData()._curveFromSelection._bufferHue.end()));
00447                                         else if(i == 1)//working on Saturation channel
00448                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferSaturation.begin(),getOverlayData()._curveFromSelection._bufferSaturation.end()));
00449                                         else //working on Lightness channel
00450                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferLightness.begin(),getOverlayData()._curveFromSelection._bufferLightness.end()));
00451 
00452                                         //Add points to current channel
00453                                         double xPosition = 0.0;
00454                                         double yPosition = 0.0;
00455                                         double step =  (double)(1/(double)(getOverlayData()._vNbStepCurveFromSelection-1));     //compute step for curve display
00456 
00457                                         //for each point
00458                                         for( std::size_t x=0; x<getOverlayData()._vNbStepCurveFromSelection; ++x )
00459                                         {
00460                                                 if( i == 0 )    //working on Hue channel
00461                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferHue[x]));             //get current Y if Hue selection buffer
00462                                                 else if( i == 1 )       //working on Saturation channel
00463                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferSaturation[x]));      //get current Y if Saturation selection buffer
00464                                                 else    //working on Lightness channel
00465                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferLightness[x]));               //get current Y if Lightness selection buffer
00466 
00467                                                 yPosition /= maxChannel; //yPosition between 0 and 1
00468 
00469                                                 if(x == 0 || x == getOverlayData()._vNbStepCurveFromSelection-1 )       //current point is last of first
00470                                                 {
00471                                                         //search for existing control point on x value
00472                                                         std::pair<double,double> currentPoint;                  //define current point
00473                                                         int nbPointsInCurve = 0;                                //define indice 
00474                                                         bool pointFound = false;                                                //point has not been found
00475                                                         while( nbPointsInCurve < _paramColorHSLSelection->getNControlPoints(i,args.time) && !pointFound )
00476                                                         {
00477                                                                 currentPoint = _paramColorHSLSelection->getNthControlPoints(i,args.time,nbPointsInCurve); //get current point
00478                                                                 if(currentPoint.first == x) //current point has the same X value than this we want to add
00479                                                                         pointFound = true;              //point has been found
00480                                                                 else
00481                                                                         ++nbPointsInCurve;              //increments indice
00482                                                         }
00483                                                         if( pointFound )        //control point is already existing so replace it
00484                                                         {
00485                                                                 currentPoint.second += yPosition;                       //add value to current control point
00486                                                                 if(currentPoint.second > 1.0)                           //clamp value to 1.0
00487                                                                                 currentPoint.second = 1.0;
00488                                                                 _paramColorHSLSelection->setNthControlPoints(i,args.time,nbPointsInCurve,currentPoint,false);   //replace current control point
00489                                                         }
00490                                                         else                    //control point is not existing so add a new one
00491                                                                 _paramColorHSLSelection->addControlPoint( i, args.time,xPosition, yPosition, false );   //place the current point
00492                                                 }
00493                                                 else //filter 
00494                                                 {
00495                                                         double value;
00496                                                         double nextValue;
00497                                                         double previousValue;
00498                                                         if( i == 0 )//Hue channel
00499                                                         {
00500                                                                 value= (double)getOverlayData()._curveFromSelection._bufferHue[x];                              //get actual value
00501                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferHue[x+1];               //get next value
00502                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferHue[x-1];   //get previous value
00503                                                         }
00504                                                         else if( i == 1 )//Saturation channel
00505                                                         {
00506                                                                 value= (double)getOverlayData()._curveFromSelection._bufferSaturation[x];                               //get actual value
00507                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferSaturation[x+1];                //get next value
00508                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferSaturation[x-1];    //get previous value
00509                                                         }
00510                                                         else //Lightness channel
00511                                                         {
00512                                                                 value= (double)getOverlayData()._curveFromSelection._bufferLightness[x];                        //get actual value
00513                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferLightness[x+1];         //get next value
00514                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferLightness[x-1];     //get previous value
00515                                                         }
00516 
00517                                                         value/=maxChannel;                              //set value between 0 and 1
00518                                                         nextValue/=maxChannel;                  //set next value between 0 and 1
00519                                                         previousValue/=maxChannel;              //set previous value between 0 and 1
00520 
00521                                                         double betweenNextAndValue = (double)(nextValue-value);                 //get interval between value and next  (0<= interval <=1)
00522                                                         double betweenPreviousAndValue = (double)(value-previousValue); //get interval between value and previous (0<= interval <=1)
00523                                                         //get absolute values
00524                                                         if(betweenNextAndValue<0)               //change betweenNextAndValue negative to positive
00525                                                                 betweenNextAndValue*=-1;
00526                                                         if(betweenPreviousAndValue<0)   //change betweenPreviousAndValue negative to positive
00527                                                                 betweenPreviousAndValue*=-1;
00528 
00529                                                         if( betweenNextAndValue> 0.01 || betweenPreviousAndValue > 0.01 )
00530                                                         {
00531                                                                 //search for existing control point on x value
00532                                                                 std::pair<double,double> currentPoint;                  //define current point
00533                                                                 int nbPointsInCurve = 0;                                //define indice 
00534                                                                 bool pointFound = false;                                                //point has not been found
00535                                                                 while( nbPointsInCurve < _paramColorHSLSelection->getNControlPoints(i,args.time) && !pointFound )
00536                                                                 {
00537                                                                         currentPoint = _paramColorHSLSelection->getNthControlPoints( i, args.time, nbPointsInCurve ); //get current point
00538                                                                         double epsilon = 0.01;
00539                                                                         if( fabs(currentPoint.first-xPosition) < epsilon )  //current point has the same X value than this we want to add
00540                                                                                 pointFound = true;                                                      //point has been found
00541                                                                         else
00542                                                                                 ++nbPointsInCurve;              //increments indice
00543                                                                 }
00544                                                                 if( pointFound )        //control point is already existing so replace it
00545                                                                 {
00546                                                                         currentPoint.second += yPosition;       //add value to current control point
00547                                                                         if(currentPoint.second > 1.0)           //clamp value to 1.0
00548                                                                                 currentPoint.second = 1.0;
00549                                                                         _paramColorHSLSelection->setNthControlPoints(i,args.time,nbPointsInCurve,currentPoint,false);   //replace current control point
00550                                                                 }
00551                                                                 else                    //control point is not existing so add a new one
00552                                                                 {
00553                                                                         _paramColorHSLSelection->addControlPoint( i, args.time,xPosition, yPosition, false );   //place the current point
00554                                                                 }
00555                                                         }
00556                                                 }
00557                                                 xPosition += step; //add step to Xposition
00558                                         }
00559                                         //Correction pass
00560                                         for( int currentP = 1; currentP< _paramColorHSLSelection->getNControlPoints(i,args.time)-1; ++currentP)
00561                                         {
00562                                                 //get current point value
00563                                                 std::pair<double,double> controlPointValue = _paramColorHSLSelection->getNthControlPoints(i,args.time,currentP);
00564                                                 //get next and previous values
00565                                                 std::pair<double,double> prevControlPoint = _paramColorHSLSelection->getNthControlPoints(i,args.time,currentP-1);
00566                                                 std::pair<double,double> nextControlPoint = _paramColorHSLSelection->getNthControlPoints(i,args.time,currentP+1);
00567                                                 //if current control point is not necessary
00568                                                 if(controlPointValue.second < prevControlPoint.second && controlPointValue.second < nextControlPoint.second)//current control point is not necessary
00569                                                         _paramColorHSLSelection->deleteControlPoint(i,currentP);                                                                                                //delete current control point
00570                                         }
00571                                         
00572                                         //correct point to 1 pass
00573                                         for( int currentP = 1; currentP <_paramColorHSLSelection->getNControlPoints(i,args.time) -1; ++currentP )
00574                                         {
00575                                                 std::pair<double,double> prevControlPoint = _paramColorHSLSelection->getNthControlPoints(i,args.time,currentP-1);       //get previous control point
00576                                                 std::pair<double,double> nextControlPoint = _paramColorHSLSelection->getNthControlPoints(i,args.time,currentP+1);  //get next control point
00577                                                 if(prevControlPoint.second>=1.0 && nextControlPoint.second>=1.0)                //if current point is useless
00578                                                                 _paramColorHSLSelection->deleteControlPoint(i,currentP);                //delete it
00579                                                 
00580                                         }
00581                                 }
00582                         }
00583                 }
00584                 if(paramName == kButtonAppendSelectionToCurveRGB)               //Append to curve (RGB) 
00585                 {
00586                         for(unsigned int i=0; i<nbCurvesRGB; ++i)
00587                         {
00588                                 if(             (i == 0 && _paramOverlayRSelection->getValue()) ||              // if button is append and Red is selected
00589                                                 (i == 1 && _paramOverlayGSelection->getValue()) ||              // else if button is append and Green is selected
00590                                                 (i == 2 && _paramOverlayBSelection->getValue()) )               // else if button is append and Blue is selected
00591                                 {
00592                                         //getMax of current selection buffer
00593                                         double maxChannel; //will contain max of the current channel (RGB)
00594                                         if(i == 0)      //working on Red channel
00595                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferRed.begin(),getOverlayData()._curveFromSelection._bufferRed.end()));
00596                                         else if(i == 1)//working on Green channel
00597                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferGreen.begin(),getOverlayData()._curveFromSelection._bufferGreen.end()));
00598                                         else //working on Blue channel
00599                                                 maxChannel = *(std::max_element(getOverlayData()._curveFromSelection._bufferBlue.begin(),getOverlayData()._curveFromSelection._bufferBlue.end()));
00600 
00601                                         //Add points to current channel
00602                                         double xPosition = 0.0;
00603                                         double yPosition = 0.0;
00604                                         double step =  (double)(1/(double)(getOverlayData()._vNbStepCurveFromSelection-1));     //compute step for curve display
00605 
00606                                         //for each point
00607                                         for( std::size_t x=0; x<getOverlayData()._vNbStepCurveFromSelection; ++x )
00608                                         {
00609                                                 if( i == 0 )    //working on Red channel
00610                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferRed[x]));             //get current Y if Red selection buffer
00611                                                 else if( i == 1 )       //working on Green channel
00612                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferGreen[x]));   //get current Y if Green selection buffer
00613                                                 else    //working on Blue channel
00614                                                         yPosition = (double)((double)(getOverlayData()._curveFromSelection._bufferBlue[x]));    //get current Y if Blue selection buffer
00615 
00616                                                 yPosition/=maxChannel; //yPosition between 0 and 1
00617 
00618                                                 if( x==0 || x == getOverlayData()._vNbStepCurveFromSelection-1 )        //current point is last of first
00619                                                 {
00620                                                         //search for existing control point on x value
00621                                                         std::pair<double,double> currentPoint;                  //define current point
00622                                                         int nbPointsInCurve = 0;                                //define indice 
00623                                                         bool pointFound = false;                                                //point has not been found
00624                                                         while( nbPointsInCurve< _paramColorRGBSelection->getNControlPoints(i,args.time) && !pointFound )
00625                                                         {
00626                                                                 currentPoint = _paramColorRGBSelection->getNthControlPoints(i,args.time,nbPointsInCurve); //get current point
00627                                                                 if(currentPoint.first == x) //current point has the same X value than this we want to add
00628                                                                         pointFound = true;              //point has been found
00629                                                                 else
00630                                                                         ++nbPointsInCurve;              //increments indice
00631                                                         }
00632                                                         if( pointFound )        //control point is already existing so replace it
00633                                                         {
00634                                                                 currentPoint.second += yPosition;                       //add value to current control point
00635                                                                 if(currentPoint.second > 1.0)                           //clamp value to 1.0
00636                                                                                 currentPoint.second = 1.0;
00637                                                                 _paramColorRGBSelection->setNthControlPoints(i,args.time,nbPointsInCurve,currentPoint,false);   //replace current control point
00638                                                         }
00639                                                         else                    //control point is not existing so add a new one
00640                                                                 _paramColorRGBSelection->addControlPoint( i, args.time,xPosition, yPosition, false );   //place the current point
00641                                                 }
00642                                                 else //filter 
00643                                                 {
00644                                                         double value;
00645                                                         double nextValue;
00646                                                         double previousValue;
00647                                                         if( i == 0 )//Red channel
00648                                                         {
00649                                                                 value= (double)getOverlayData()._curveFromSelection._bufferRed[x];                              //get actual value
00650                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferRed[x+1];               //get next value
00651                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferRed[x-1];   //get previous value
00652                                                         }
00653                                                         else if( i == 1 )//Green channel
00654                                                         {
00655                                                                 value= (double)getOverlayData()._curveFromSelection._bufferGreen[x];                                    //get actual value
00656                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferGreen[x+1];                             //get next value
00657                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferGreen[x-1];                 //get previous value
00658                                                         }
00659                                                         else //Blue channel
00660                                                         {
00661                                                                 value= (double)getOverlayData()._curveFromSelection._bufferBlue[x];                                             //get actual value
00662                                                                 nextValue = (double)getOverlayData()._curveFromSelection._bufferBlue[x+1];                              //get next value
00663                                                                 previousValue = (double)getOverlayData()._curveFromSelection._bufferBlue[x-1];                  //get previous value
00664                                                         }
00665 
00666                                                         value/=maxChannel;                              //set value between 0 and 1
00667                                                         nextValue/=maxChannel;                  //set next value between 0 and 1
00668                                                         previousValue/=maxChannel;              //set previous value between 0 and 1
00669 
00670                                                         double betweenNextAndValue = (double)(nextValue-value);                 //get interval between value and next  (0<= interval <=1)
00671                                                         double betweenPreviousAndValue = (double)(value-previousValue); //get interval between value and previous (0<= interval <=1)
00672                                                         //get absolute values
00673                                                         if(betweenNextAndValue<0)               //change betweenNextAndValue negative to positive
00674                                                                 betweenNextAndValue*=-1;
00675                                                         if(betweenPreviousAndValue<0)   //change betweenPreviousAndValue negative to positive
00676                                                                 betweenPreviousAndValue*=-1;
00677 
00678                                                         if( betweenNextAndValue > 0.01 || betweenPreviousAndValue > 0.01 )
00679                                                         {
00680                                                                 //search for existing control point on x value
00681                                                                 std::pair<double,double> currentPoint;                  //define current point
00682                                                                 int nbPointsInCurve = 0;                                //define indice 
00683                                                                 bool pointFound = false;                                                //point has not been found
00684                                                                 while( nbPointsInCurve< _paramColorRGBSelection->getNControlPoints(i,args.time) && !pointFound )
00685                                                                 {
00686                                                                         currentPoint = _paramColorRGBSelection->getNthControlPoints(i,args.time,nbPointsInCurve); //get current point
00687                                                                         double epsilon = 0.01;
00688                                                                         if(fabs(currentPoint.first-xPosition)<epsilon) //current point has the same X value than this we want to add
00689                                                                                 pointFound = true;                                                 //point has been found
00690                                                                         else
00691                                                                                 ++nbPointsInCurve;              //increments indice
00692                                                                 }
00693                                                                 if( pointFound )        //control point is already existing so replace it
00694                                                                 {
00695                                                                         currentPoint.second += yPosition;       //add value to current control point
00696                                                                         if( currentPoint.second > 1.0 )         //clamp value to 1.0
00697                                                                                 currentPoint.second = 1.0;
00698                                                                         _paramColorRGBSelection->setNthControlPoints(i,args.time,nbPointsInCurve,currentPoint,false);   //replace current control point
00699                                                                 }
00700                                                                 else                    //control point is not existing so add a new one
00701                                                                 {
00702                                                                         _paramColorRGBSelection->addControlPoint( i, args.time,xPosition, yPosition, false );   //place the current point
00703                                                                 }
00704                                                         }
00705                                                 }
00706                                                 xPosition += step; //add step to Xposition
00707                                         }
00708                                         //Correction pass
00709                                         for( int currentP=1; currentP< _paramColorRGBSelection->getNControlPoints(i,args.time)-1; ++currentP )
00710                                         {
00711                                                 //get current point value
00712                                                 std::pair<double,double> controlPointValue = _paramColorRGBSelection->getNthControlPoints(i,args.time,currentP);
00713                                                 //get next and previous values
00714                                                 std::pair<double,double> prevControlPoint = _paramColorRGBSelection->getNthControlPoints(i,args.time,currentP-1);
00715                                                 std::pair<double,double> nextControlPoint = _paramColorRGBSelection->getNthControlPoints(i,args.time,currentP+1);
00716                                                 //if current control point is not necessary
00717                                                 if(controlPointValue.second < prevControlPoint.second && controlPointValue.second < nextControlPoint.second)//current control point is not necessary
00718                                                         _paramColorRGBSelection->deleteControlPoint(i,currentP);                                                                                                //delete current control point
00719                                         }
00720                                 }
00721                         }
00722                 }
00723         }
00724 }
00725 
00726 /*
00727  * the source clip has been changed
00728  */
00729 void HistogramPlugin::changedClip( const OFX::InstanceChangedArgs& args, const std::string& clipName )
00730 {
00731         if( clipName == kOfxImageEffectSimpleSourceClipName )
00732         {
00733                 if( this->hasOverlayData( ) )
00734                 {
00735                         this->getOverlayData()._isDataInvalid = true;
00736                         this->redrawOverlays();
00737                 }
00738         }
00739 }
00740 
00741 /*
00742  * does plugin do something
00743  */
00744 bool HistogramPlugin::isIdentity( const OFX::RenderArguments& args, OFX::Clip*& identityClip, double& identityTime )
00745 {
00746         /// @todo HACK: nuke doesn't call changedClip when the time is modified.
00747         //OFX::InstanceChangedArgs changed( args.time, args.renderScale );
00748         //this->changedClip(changed,this->_clipSrc->name());
00749         //      HistogramProcessParams<Scalar> params = getProcessParams();
00750         return false;
00751 }
00752 
00753 /**
00754  * @brief The overridden render function
00755  * @param[in]   args     Rendering parameters
00756  */
00757 void HistogramPlugin::render( const OFX::RenderArguments &args )
00758 {
00759         _isRendering = true;            //plugin is rendering
00760         doGilRender<HistogramProcess>( *this, args );
00761         _isRendering = false;           //plugin is not rendering anymore
00762         
00763         if( OFX::getImageEffectHostDescription()->hostName == "uk.co.thefoundry.nuke" ) /// @todo: HACK Nuke doesn't call changeClip function when time is changed
00764         {
00765                 if( getOverlayData().isCurrentTimeModified(args.time) ) //if time is changed
00766                 {
00767                         this->redrawOverlays();         //redraw scene
00768                 }
00769         }
00770 }
00771 
00772 /// @brief Overlay data
00773 /// @{
00774 
00775 /*Overlay data management*/
00776 void HistogramPlugin::addRefOverlayData( )
00777 {
00778         if( _overlayDataCount == 0 )
00779         {
00780                 const OfxPointI imgSize = this->_clipSrc->getPixelRodSize( 0 ); ///@todo set the correct time !
00781                 _overlayData.reset( new OverlayData( imgSize, this->_paramNbStepSelection->getValue( ),this->_paramSelectionFromCurve->getValue()) );
00782         }
00783         ++_overlayDataCount;
00784 }
00785 
00786 void HistogramPlugin::releaseOverlayData( )
00787 {
00788         --_overlayDataCount;
00789         if( _overlayDataCount == 0 )
00790         {
00791                 _overlayData.reset( NULL );
00792         }
00793 }
00794 
00795 bool HistogramPlugin::hasOverlayData( ) const
00796 {
00797         return _overlayDataCount != 0;
00798 }
00799 
00800 OverlayData& HistogramPlugin::getOverlayData( )
00801 {
00802         return *_overlayData.get( );
00803 }
00804 
00805 const OverlayData& HistogramPlugin::getOverlayData( ) const
00806 {
00807         return *_overlayData.get( );
00808 }
00809 /// @}
00810 }
00811 }
00812 }