#ifdef _MSC_VER #pragma warning(disable : 4996) #endif #include "ttzpimagefx.h" #include "texception.h" #include "tfxparam.h" #include "stdfx.h" #include "trasterfx.h" #include "tspectrumparam.h" class ArtContourFx final : public TStandardRasterFx { FX_PLUGIN_DECLARATION(ArtContourFx) TRasterFxPort m_input; TRasterFxPort m_controller; TStringParamP m_colorIndex; TBoolParamP m_keepColor; TBoolParamP m_keepLine; TBoolParamP m_includeAlpha; TDoubleParamP m_density; TRangeParamP m_distance; TBoolParamP m_randomness; TRangeParamP m_orientation; TRangeParamP m_size; public: ArtContourFx() : m_colorIndex(L"1,2,3") , m_keepColor(false) , m_keepLine(false) , m_includeAlpha(true) , m_density(0.0) , m_distance(DoublePair(30.0, 30.0)) , m_randomness(true) , m_orientation(DoublePair(0.0, 180.0)) , m_size(DoublePair(30.0, 30.0)) { bindParam(this, "Color_Index", m_colorIndex); bindParam(this, "Keep_color", m_keepColor); bindParam(this, "Keep_Line", m_keepLine); bindParam(this, "Include_Alpha", m_includeAlpha); bindParam(this, "Density", m_density); bindParam(this, "Distance", m_distance); bindParam(this, "Randomness", m_randomness); bindParam(this, "Orientation", m_orientation); bindParam(this, "Size", m_size); addInputPort("Source", m_input); addInputPort("Controller", m_controller); m_density->setValueRange(0.0, 100.0); m_distance->getMin()->setValueRange(0.0, 1000.0); m_distance->getMax()->setValueRange(0.0, 1000.0); m_orientation->getMin()->setValueRange(-180.0, 180.0); m_orientation->getMax()->setValueRange(-180.0, 180.0); m_orientation->getMin()->setMeasureName("angle"); m_orientation->getMax()->setMeasureName("angle"); m_size->getMin()->setValueRange(0.0, 1000.0); m_size->getMax()->setValueRange(0.0, 1000.0); } ~ArtContourFx() {} //---------------------------------------------------------------------------- SandorFxRenderData *buildRenderData(double frame, int shrink, const TRectD &controlBox, const std::string &controllerAlias) { int argc = 12; const char *argv[12]; argv[0] = strsave(::to_string(m_colorIndex->getValue()).c_str()); getValues(argv, argc, frame); SandorFxRenderData *artContourData = new SandorFxRenderData(ArtAtContour, argc, argv, 0, shrink, controlBox); ArtAtContourParams ¶ms = artContourData->m_contourParams; params.m_density = m_density->getValue(frame) / 100; params.m_colorIndex = m_colorIndex->getValue(); params.m_keepLine = m_keepLine->getValue(); params.m_includeAlpha = m_includeAlpha->getValue(); params.m_maxOrientation = m_orientation->getValue(frame).second; params.m_maxDistance = m_distance->getValue(frame).second / 10; params.m_maxSize = m_size->getValue(frame).second / 100; params.m_minOrientation = m_orientation->getValue(frame).first; params.m_minDistance = m_distance->getValue(frame).first / 10; params.m_minSize = m_size->getValue(frame).first / 100; params.m_randomness = m_randomness->getValue(); params.m_keepColor = m_keepColor->getValue(); artContourData->m_controllerAlias = controllerAlias; return artContourData; } //---------------------------------------------------------------------------- bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &ri) override { if (m_input.isConnected() && m_controller.isConnected()) { TRectD controlBox, inputBox; TRenderSettings ri2(ri); ri2.m_affine = TAffine(); m_controller->getBBox(frame, controlBox, ri2); TRenderSettings ri3(ri); int shrink = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0); // Should be there no need for the alias... SandorFxRenderData *artContourData = buildRenderData(frame, shrink, controlBox, ""); ri3.m_data.push_back(artContourData); return m_input->doGetBBox(frame, bBox, ri3); } else if (m_input.isConnected()) { m_input->doGetBBox(frame, bBox, ri); return false; } bBox = TRectD(); return false; } //----------------------------------------------------------------------------- bool canHandle(const TRenderSettings &info, double frame) override { return true; } //----------------------------------------------------------------------------- bool allowUserCacheOnPort(int port) override { return port != 0; } //----------------------------------------------------------------------------- void doDryCompute(TRectD &rect, double frame, const TRenderSettings &ri) override; //----------------------------------------------------------------------------- void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override; //----------------------------------------------------------------------------- private: void getValues(const char *argv[], int argc, double frame) { double values[12]; values[1] = m_size->getValue(frame).second / 100; values[2] = m_size->getValue(frame).first / 100; values[3] = m_orientation->getValue(frame).second; values[4] = m_orientation->getValue(frame).first; values[5] = m_randomness->getValue() ? 1.0 : 0.0; values[6] = m_distance->getValue(frame).second / 10; values[7] = m_distance->getValue(frame).first / 10; values[8] = m_density->getValue(frame) / 100; values[9] = m_keepLine->getValue() ? 1.0 : 0.0; values[10] = m_keepColor->getValue() ? 1.0 : 0.0; values[11] = m_includeAlpha->getValue() ? 1.0 : 0.0; convertParam(values, argv, argc); } //---------------------------------------------------------------------- char *strsave(const char *t) { char *s; s = (char *)malloc(strlen(t) + 1); strcpy(s, t); return s; } //----------------------------------------------------------------------- void convertParam(double param[], const char *cParam[], int cParamLen) { std::string app; for (int i = 1; i <= 11; i++) { app = std::to_string(param[i]); cParam[i] = strsave(app.c_str()); } } }; FX_PLUGIN_IDENTIFIER(ArtContourFx, "artContourFx"); //----------------------------------------------------------------------------- void ArtContourFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &ri) { if (!m_input.isConnected()) return; if (!m_controller.isConnected()) return; TRenderSettings ri2(ri); ri2.m_affine = TAffine(); TRectD controlBox; m_controller->getBBox(frame, controlBox, ri2); if (controlBox == TConsts::infiniteRectD) controlBox = rect; TDimension dim = convert(controlBox).getSize(); TRectD controlRect(controlBox.getP00(), TDimensionD(dim.lx, dim.ly)); m_controller->dryCompute(controlRect, frame, ri2); TRenderSettings ri3(ri); int shrink = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0); std::string controlAlias = m_controller->getAlias(frame, ri2); SandorFxRenderData *artContourData = buildRenderData(frame, shrink, controlBox, controlAlias); ri3.m_data.push_back(artContourData); ri3.m_userCachable = false; m_input->dryCompute(rect, frame, ri3); } //----------------------------------------------------------------------------- void ArtContourFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { if (!m_input.isConnected()) return; if (!m_controller.isConnected()) { m_input->compute(tile, frame, ri); return; } TRenderSettings ri2(ri); ri2.m_affine = TAffine(); TRectD controlBox; m_controller->getBBox(frame, controlBox, ri2); if (controlBox == TConsts::infiniteRectD) { TDimension tileDim = tile.getRaster()->getSize(); controlBox = TRectD(tile.m_pos, TDimensionD(tileDim.lx, tileDim.ly)); } TTile ctrTile; ctrTile.m_pos = controlBox.getP00(); TDimension dim = convert(controlBox).getSize(); m_controller->allocateAndCompute(ctrTile, ctrTile.m_pos, dim, tile.getRaster(), frame, ri2); TRenderSettings ri3(ri); // Build the render data int shrink = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0); std::string controlAlias = m_controller->getAlias(frame, ri2); SandorFxRenderData *artContourData = buildRenderData(frame, shrink, controlBox, controlAlias); // Add the controller raster artContourData->m_controller = ctrTile.getRaster(); // Push the data among the others ri3.m_data.push_back(artContourData); ri3.m_userCachable = false; m_input->compute(tile, frame, ri3); }