TuttleOFX
1
|
00001 #include "CropDefinitions.hpp" 00002 #include "CropPlugin.hpp" 00003 #include "CropProcess.hpp" 00004 00005 #include <tuttle/plugin/ofxToGil/point.hpp> 00006 00007 #include <boost/gil/gil_all.hpp> 00008 #include <boost/math/special_functions/round.hpp> 00009 00010 namespace tuttle 00011 { 00012 namespace plugin 00013 { 00014 namespace crop 00015 { 00016 00017 using namespace boost::math; 00018 using namespace boost::gil; 00019 00020 CropPlugin::CropPlugin(OfxImageEffectHandle handle) : 00021 ImageEffectGilPlugin(handle) 00022 { 00023 00024 _paramMode = fetchChoiceParam(kParamMode); 00025 _paramFillColor = fetchRGBAParam(kParamFillColor); 00026 _paramAxis = fetchChoiceParam(kParamAxis); 00027 _paramSymmetric = fetchChoiceParam(kParamSymmetric); 00028 _paramFixedRatio = fetchBooleanParam(kParamFixedRatio); 00029 _paramRatio = fetchDoubleParam(kParamRatio); 00030 _paramPreset = fetchChoiceParam(kParamPreset); 00031 _paramOverlay = fetchBooleanParam(kParamOverlay); 00032 _paramCropRegion = fetchGroupParam(kParamGroupCropRegion); 00033 _paramXMin = fetchIntParam(kParamXMin); 00034 _paramYMin = fetchIntParam(kParamYMin); 00035 _paramXMax = fetchIntParam(kParamXMax); 00036 _paramYMax = fetchIntParam(kParamYMax); 00037 // changedParam( _changedArgs, kParamMode ); 00038 changedParam(_changedArgs, kParamAxis); 00039 changedParam(_changedArgs, kParamFixedRatio); 00040 changedParam(_changedArgs, kParamRatio); 00041 changedParam(_changedArgs, kParamPreset); 00042 } 00043 00044 OfxRectI 00045 CropPlugin::getCropRegionValue() const 00046 { 00047 OfxRectI cropRegion; 00048 cropRegion.x1 = _paramXMin->getValue(); 00049 cropRegion.y1 = _paramYMin->getValue(); 00050 cropRegion.x2 = _paramXMax->getValue(); 00051 cropRegion.y2 = _paramYMax->getValue(); 00052 return cropRegion; 00053 } 00054 00055 int 00056 CropPlugin::safeModulo(const int &cropValue, const int &rodValue) 00057 { 00058 if (rodValue == 0 || cropValue == 0) 00059 { 00060 return 0; 00061 } 00062 else 00063 return cropValue % int(rodValue * 0.5); 00064 } 00065 00066 OfxRectI 00067 CropPlugin::computeCropRegion(const OfxTime time, 00068 const bool fromRatio) const 00069 { 00070 OfxRectI cropRegion = getCropRegionValue(); 00071 00072 if (!_clipSrc->isConnected()) 00073 { 00074 return cropRegion; 00075 } 00076 00077 const OfxRectI sRod = _clipSrc->getPixelRod(time); 00078 const OfxPointI sRodSize = _clipSrc->getPixelRodSize(time); 00079 const EParamAxis axis = static_cast<EParamAxis>(_paramAxis->getValue()); 00080 const EParamSymmetric symmetric = 00081 static_cast<EParamSymmetric>(_paramSymmetric->getValue()); 00082 switch (axis) 00083 { 00084 case eParamAxisXY: 00085 { 00086 if (symmetric == eParamSymmetricNone) 00087 break; 00088 00089 if (symmetric == eParamSymmetricX || symmetric == eParamSymmetricXY) 00090 { 00091 cropRegion.x1 = safeModulo(cropRegion.x1, sRodSize.x); 00092 cropRegion.x2 = sRodSize.x - cropRegion.x1; 00093 } 00094 if (symmetric == eParamSymmetricY || symmetric == eParamSymmetricXY) 00095 { 00096 cropRegion.y1 = safeModulo(cropRegion.y1, sRodSize.y); 00097 cropRegion.y2 = sRodSize.y - cropRegion.y1; 00098 } 00099 break; 00100 } 00101 case eParamAxisX: 00102 { 00103 // don't modify Y axis 00104 cropRegion.y1 = sRod.y1; 00105 cropRegion.y2 = sRod.y2; 00106 if (symmetric == eParamSymmetricX || symmetric == eParamSymmetricXY) 00107 { 00108 cropRegion.x1 = safeModulo(cropRegion.x1, sRodSize.x); 00109 cropRegion.x2 = sRodSize.x - cropRegion.x1; 00110 } 00111 break; 00112 } 00113 case eParamAxisY: 00114 { 00115 // don't modify X axis 00116 cropRegion.x1 = sRod.x1; 00117 cropRegion.x2 = sRod.x2; 00118 if (symmetric == eParamSymmetricY || symmetric == eParamSymmetricXY) 00119 { 00120 cropRegion.y1 = safeModulo(cropRegion.y1, sRodSize.y); 00121 cropRegion.y2 = sRodSize.y - cropRegion.y1; 00122 } 00123 break; 00124 } 00125 } 00126 bool fixedRatio = _paramFixedRatio->getValue(); 00127 if (fromRatio || fixedRatio) 00128 { 00129 double ratio = _paramRatio->getValue(); 00130 if (ratio == 0.0) 00131 ratio = 1.0; 00132 00133 switch (axis) 00134 { 00135 case eParamAxisXY: 00136 { 00137 const double xD2 = (cropRegion.x2 - cropRegion.x1) * 0.5; 00138 const double yD2 = (cropRegion.y2 - cropRegion.y1) * 0.5; 00139 const double yCenter = cropRegion.y1 + yD2; 00140 const double nyD2 = xD2 / ratio; 00141 cropRegion.y1 = int(yCenter - nyD2); 00142 cropRegion.y2 = int(yCenter + nyD2); 00143 break; 00144 } 00145 case eParamAxisY: 00146 { 00147 const double xD2 = (sRod.x2 - sRod.x1) * 0.5; 00148 const double yD2 = (sRod.y2 - sRod.y1) * 0.5; 00149 const double yCenter = sRod.y1 + yD2; 00150 const double nyD2 = xD2 / ratio; 00151 cropRegion.y1 = int(yCenter - nyD2); 00152 cropRegion.y2 = int(yCenter + nyD2); 00153 break; 00154 } 00155 case eParamAxisX: 00156 { 00157 const double xD2 = (sRod.x2 - sRod.x1) * 0.5; 00158 const double yD2 = (sRod.y2 - sRod.y1) * 0.5; 00159 const double xCenter = sRod.x1 + xD2; 00160 const double nxD2 = yD2 * ratio; 00161 cropRegion.x1 = int(xCenter - nxD2); 00162 cropRegion.x2 = int(xCenter + nxD2); 00163 break; 00164 } 00165 } 00166 } 00167 00168 if (cropRegion.x1 > cropRegion.x2) 00169 { 00170 std::swap(cropRegion.x1, cropRegion.x2); 00171 } 00172 if (cropRegion.y1 > cropRegion.y2) 00173 { 00174 std::swap(cropRegion.y1, cropRegion.y2); 00175 } 00176 00177 return cropRegion; 00178 } 00179 00180 void 00181 CropPlugin::changedClip(const OFX::InstanceChangedArgs& args, 00182 const std::string& clipName) 00183 { 00184 // TUTTLE_TLOG( TUTTLE_INFO, "changedClip:" << clipName ); 00185 if (clipName == kOfxImageEffectSimpleSourceClipName) 00186 { 00187 changedParam(_changedArgs, kParamRatio); 00188 } 00189 } 00190 00191 void 00192 CropPlugin::changedParam(const OFX::InstanceChangedArgs& args, 00193 const std::string& paramName) 00194 { 00195 // TUTTLE_TLOG( TUTTLE_INFO, "changedParam:" << paramName ); 00196 // if( paramName == kParamMode ) 00197 // { 00198 // EParamMode mode = static_cast<EParamMode>( _paramMode->getValue() ); 00199 // switch( mode ) 00200 // { 00201 // case eParamModeCrop: 00202 // { 00203 // _paramFillColor->setIsSecretAndDisabled( true ); 00204 // break; 00205 // } 00206 // case eParamModeColor: 00207 // { 00208 // _paramFillColor->setIsSecretAndDisabled( false ); 00209 // break; 00210 // } 00211 // } 00212 // } 00213 // else 00214 if (paramName == kParamAxis || paramName == kParamSymmetric 00215 || paramName == kParamFixedRatio) 00216 { 00217 EParamAxis axis = static_cast<EParamAxis>(_paramAxis->getValue()); 00218 EParamSymmetric symmetric = 00219 static_cast<EParamSymmetric>(_paramSymmetric->getValue()); 00220 bool xMinEnabled = false; 00221 bool yMinEnabled = false; 00222 bool xMaxEnabled = false; 00223 bool yMaxEnabled = false; 00224 switch (axis) 00225 { 00226 case eParamAxisXY: 00227 { 00228 xMinEnabled = true; 00229 yMinEnabled = true; 00230 00231 xMaxEnabled = true; 00232 yMaxEnabled = true; 00233 break; 00234 } 00235 case eParamAxisX: 00236 { 00237 xMinEnabled = true; 00238 xMaxEnabled = true; 00239 00240 yMinEnabled = false; 00241 yMaxEnabled = false; 00242 break; 00243 } 00244 case eParamAxisY: 00245 { 00246 xMinEnabled = false; 00247 xMaxEnabled = false; 00248 00249 yMinEnabled = true; 00250 yMaxEnabled = true; 00251 break; 00252 } 00253 } 00254 if (symmetric == eParamSymmetricX || symmetric == eParamSymmetricXY) 00255 { 00256 xMaxEnabled = false; 00257 } 00258 if (symmetric == eParamSymmetricY || symmetric == eParamSymmetricXY) 00259 { 00260 yMaxEnabled = false; 00261 } 00262 bool fixedRatio = _paramFixedRatio->getValue(); 00263 if (fixedRatio) 00264 { 00265 yMinEnabled = false; 00266 yMaxEnabled = false; 00267 } 00268 _paramXMin->setEnabled(xMinEnabled); 00269 _paramYMin->setEnabled(yMinEnabled); 00270 _paramXMax->setEnabled(xMaxEnabled); 00271 _paramYMax->setEnabled(yMaxEnabled); 00272 00273 if (paramName == kParamFixedRatio) 00274 { 00275 if (_paramFixedRatio->getValue()) 00276 { 00277 _paramRatio->setEnabled(true); 00278 _paramPreset->setIsSecretAndDisabled(false); 00279 } 00280 else 00281 { 00282 _paramRatio->setEnabled(false); 00283 _paramPreset->setIsSecretAndDisabled(true); 00284 } 00285 } 00286 } 00287 else if (paramName == kParamRatio) 00288 { 00289 // if( ??? ) 00290 // { 00291 _paramPreset->setValue(eParamPreset_custom); 00292 // } 00293 // bool fixedRatio = _paramFixedRatio->getValue(); 00294 // 00295 // if( fixedRatio && 00296 // _clipSrc->isConnected() ) 00297 // { 00298 // OfxRectI cropRegion = computeCropRegion( args.time, true ); 00299 // _paramXMin->setValue( cropRegion.x1 ); 00300 // _paramXMax->setValue( cropRegion.x2 ); 00301 // _paramYMin->setValue( cropRegion.y1 ); 00302 // _paramYMax->setValue( cropRegion.y2 ); 00303 // } 00304 } 00305 else if (paramName == kParamPreset) 00306 { 00307 double ratio = 0.0; 00308 EParamPreset preset = 00309 static_cast<EParamPreset>(_paramPreset->getValue()); 00310 00311 switch (preset) 00312 { 00313 case eParamPreset_custom: 00314 break; 00315 // 4/3 00316 case eParamPreset_1_33: 00317 ratio = 4.0 / 3.0; 00318 break; 00319 // 16 / 9 00320 case eParamPreset_1_77: 00321 ratio = 16.0 / 9.0; 00322 break; 00323 // 1:1.85 00324 case eParamPreset_1_85: 00325 ratio = 1.85; 00326 break; 00327 // Cinemascope 00328 case eParamPreset_2_35: 00329 ratio = 2.35; 00330 break; 00331 case eParamPreset_2_40: 00332 ratio = 2.40; 00333 break; 00334 } 00335 if (preset != eParamPreset_custom) 00336 { 00337 _paramRatio->setValue(ratio); 00338 } 00339 } 00340 00341 // if a param which have an impact on crop region 00342 // we need to recompute this region 00343 if (paramName == kParamXMin || paramName == kParamYMin 00344 || paramName == kParamXMax || paramName == kParamYMax 00345 || paramName == kParamAxis || paramName == kParamSymmetric 00346 || paramName == kParamRatio) 00347 { 00348 // bool fixedRatio = _paramFixedRatio->getValue(); 00349 const OfxRectI cropRegionParams = getCropRegionValue(); 00350 const OfxRectI cropRegion = computeCropRegion(args.time); 00351 // if( fixedRatio ) 00352 // { 00353 if (cropRegionParams.x1 != cropRegion.x1) 00354 _paramXMin->setValue(cropRegion.x1); 00355 if (cropRegionParams.y1 != cropRegion.y1) 00356 _paramYMin->setValue(cropRegion.y1); 00357 if (cropRegionParams.x2 != cropRegion.x2) 00358 _paramXMax->setValue(cropRegion.x2); 00359 if (cropRegionParams.y2 != cropRegion.y2) 00360 _paramYMax->setValue(cropRegion.y2); 00361 // } 00362 // else 00363 // { 00364 const double x = cropRegion.x2 - cropRegion.x1; 00365 const double y = cropRegion.y2 - cropRegion.y1; 00366 const double nRatio = (y != 0) ? (x / y) : 0; 00367 if (nRatio != _paramRatio->getValue()) 00368 _paramRatio->setValue(nRatio); 00369 // } 00370 } 00371 } 00372 00373 bool 00374 CropPlugin::getRegionOfDefinition( 00375 const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod) 00376 { 00377 00378 CropProcessParams<rgba32f_pixel_t> params = getProcessParams< 00379 rgba32f_pixel_t>(args.time); 00380 00381 switch (_paramMode->getValue()) 00382 { 00383 case eParamModeCrop: 00384 { 00385 rod.x1 = params._cropRegion.x1; 00386 rod.y1 = params._cropRegion.y1; 00387 rod.x2 = params._cropRegion.x2; 00388 rod.y2 = params._cropRegion.y2; 00389 return true; 00390 } 00391 case eParamModeFillColor: 00392 { 00393 break; 00394 } 00395 } 00396 return false; 00397 } 00398 00399 /** 00400 * @brief The overridden render function 00401 * @param[in] args Rendering parameters 00402 */ 00403 void 00404 CropPlugin::render(const OFX::RenderArguments& args) 00405 { 00406 doGilRender<CropProcess>(*this, args); 00407 } 00408 00409 } 00410 } 00411 }