TuttleOFX
1
|
00001 #include "HistogramKeyerPlugin.hpp" 00002 #include "HistogramKeyerProcess.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 histogramKeyer { 00011 00012 /* 00013 * fecth plugin IHM parameters with plugin parameters pointer 00014 */ 00015 HistogramKeyerPlugin::HistogramKeyerPlugin( 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 HistogramKeyerProcessParams structure for process 00078 */ 00079 HistogramKeyerProcessParams<HistogramKeyerPlugin::Scalar> HistogramKeyerPlugin::getProcessParams( const OfxTime time, const OfxPointD& renderScale ) const 00080 { 00081 HistogramKeyerProcessParams<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 HistogramKeyerPlugin::changedParam( const OFX::InstanceChangedArgs &args, const std::string ¶mName ) 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 HistogramKeyerPlugin::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 HistogramKeyerPlugin::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 // HistogramKeyerProcessParams<Scalar> params = getProcessParams(); 00750 return false; 00751 } 00752 00753 /** 00754 * @brief The overridden render function 00755 * @param[in] args Rendering parameters 00756 */ 00757 void HistogramKeyerPlugin::render( const OFX::RenderArguments &args ) 00758 { 00759 _isRendering = true; //plugin is rendering 00760 doGilRender<HistogramKeyerProcess>( *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 HistogramKeyerPlugin::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 HistogramKeyerPlugin::releaseOverlayData( ) 00787 { 00788 --_overlayDataCount; 00789 if( _overlayDataCount == 0 ) 00790 { 00791 _overlayData.reset( NULL ); 00792 } 00793 } 00794 00795 bool HistogramKeyerPlugin::hasOverlayData( ) const 00796 { 00797 return _overlayDataCount != 0; 00798 } 00799 00800 OverlayData& HistogramKeyerPlugin::getOverlayData( ) 00801 { 00802 return *_overlayData.get( ); 00803 } 00804 00805 const OverlayData& HistogramKeyerPlugin::getOverlayData( ) const 00806 { 00807 return *_overlayData.get( ); 00808 } 00809 /// @} 00810 } 00811 } 00812 }