1 #ifdef _MSC_VER
2 #pragma warning(disable : 4996)
3 #endif
4 
5 #include "ttzpimagefx.h"
6 #include "texception.h"
7 #include "tfxparam.h"
8 #include "stdfx.h"
9 #include "trasterfx.h"
10 #include "tspectrumparam.h"
11 
12 class ArtContourFx final : public TStandardRasterFx {
13   FX_PLUGIN_DECLARATION(ArtContourFx)
14 
15   TRasterFxPort m_input;
16   TRasterFxPort m_controller;
17   TStringParamP m_colorIndex;
18   TBoolParamP m_keepColor;
19   TBoolParamP m_keepLine;
20   TBoolParamP m_includeAlpha;
21   TDoubleParamP m_density;
22   TRangeParamP m_distance;
23   TBoolParamP m_randomness;
24   TRangeParamP m_orientation;
25   TRangeParamP m_size;
26 
27 public:
ArtContourFx()28   ArtContourFx()
29       : m_colorIndex(L"1,2,3")
30       , m_keepColor(false)
31       , m_keepLine(false)
32       , m_includeAlpha(true)
33       , m_density(0.0)
34       , m_distance(DoublePair(30.0, 30.0))
35       , m_randomness(true)
36       , m_orientation(DoublePair(0.0, 180.0))
37       , m_size(DoublePair(30.0, 30.0)) {
38     bindParam(this, "Color_Index", m_colorIndex);
39     bindParam(this, "Keep_color", m_keepColor);
40     bindParam(this, "Keep_Line", m_keepLine);
41     bindParam(this, "Include_Alpha", m_includeAlpha);
42     bindParam(this, "Density", m_density);
43     bindParam(this, "Distance", m_distance);
44     bindParam(this, "Randomness", m_randomness);
45     bindParam(this, "Orientation", m_orientation);
46     bindParam(this, "Size", m_size);
47     addInputPort("Source", m_input);
48     addInputPort("Controller", m_controller);
49     m_density->setValueRange(0.0, 100.0);
50     m_distance->getMin()->setValueRange(0.0, 1000.0);
51     m_distance->getMax()->setValueRange(0.0, 1000.0);
52     m_orientation->getMin()->setValueRange(-180.0, 180.0);
53     m_orientation->getMax()->setValueRange(-180.0, 180.0);
54     m_orientation->getMin()->setMeasureName("angle");
55     m_orientation->getMax()->setMeasureName("angle");
56     m_size->getMin()->setValueRange(0.0, 1000.0);
57     m_size->getMax()->setValueRange(0.0, 1000.0);
58   }
59 
~ArtContourFx()60   ~ArtContourFx() {}
61 
62   //----------------------------------------------------------------------------
63 
buildRenderData(double frame,int shrink,const TRectD & controlBox,const std::string & controllerAlias)64   SandorFxRenderData *buildRenderData(double frame, int shrink,
65                                       const TRectD &controlBox,
66                                       const std::string &controllerAlias) {
67     int argc = 12;
68     const char *argv[12];
69     argv[0] = strsave(::to_string(m_colorIndex->getValue()).c_str());
70     getValues(argv, argc, frame);
71 
72     SandorFxRenderData *artContourData =
73         new SandorFxRenderData(ArtAtContour, argc, argv, 0, shrink, controlBox);
74     ArtAtContourParams &params        = artContourData->m_contourParams;
75     params.m_density                  = m_density->getValue(frame) / 100;
76     params.m_colorIndex               = m_colorIndex->getValue();
77     params.m_keepLine                 = m_keepLine->getValue();
78     params.m_includeAlpha             = m_includeAlpha->getValue();
79     params.m_maxOrientation           = m_orientation->getValue(frame).second;
80     params.m_maxDistance              = m_distance->getValue(frame).second / 10;
81     params.m_maxSize                  = m_size->getValue(frame).second / 100;
82     params.m_minOrientation           = m_orientation->getValue(frame).first;
83     params.m_minDistance              = m_distance->getValue(frame).first / 10;
84     params.m_minSize                  = m_size->getValue(frame).first / 100;
85     params.m_randomness               = m_randomness->getValue();
86     params.m_keepColor                = m_keepColor->getValue();
87     artContourData->m_controllerAlias = controllerAlias;
88 
89     return artContourData;
90   }
91 
92   //----------------------------------------------------------------------------
93 
doGetBBox(double frame,TRectD & bBox,const TRenderSettings & ri)94   bool doGetBBox(double frame, TRectD &bBox,
95                  const TRenderSettings &ri) override {
96     if (m_input.isConnected() && m_controller.isConnected()) {
97       TRectD controlBox, inputBox;
98 
99       TRenderSettings ri2(ri);
100       ri2.m_affine = TAffine();
101 
102       m_controller->getBBox(frame, controlBox, ri2);
103 
104       TRenderSettings ri3(ri);
105 
106       int shrink = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0);
107       // Should be there no need for the alias...
108       SandorFxRenderData *artContourData =
109           buildRenderData(frame, shrink, controlBox, "");
110       ri3.m_data.push_back(artContourData);
111 
112       return m_input->doGetBBox(frame, bBox, ri3);
113     } else if (m_input.isConnected()) {
114       m_input->doGetBBox(frame, bBox, ri);
115       return false;
116     }
117     bBox = TRectD();
118     return false;
119   }
120 
121   //-----------------------------------------------------------------------------
122 
canHandle(const TRenderSettings & info,double frame)123   bool canHandle(const TRenderSettings &info, double frame) override {
124     return true;
125   }
126 
127   //-----------------------------------------------------------------------------
128 
allowUserCacheOnPort(int port)129   bool allowUserCacheOnPort(int port) override { return port != 0; }
130 
131   //-----------------------------------------------------------------------------
132 
133   void doDryCompute(TRectD &rect, double frame,
134                     const TRenderSettings &ri) override;
135 
136   //-----------------------------------------------------------------------------
137 
138   void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
139 
140   //-----------------------------------------------------------------------------
141 
142 private:
getValues(const char * argv[],int argc,double frame)143   void getValues(const char *argv[], int argc, double frame) {
144     double values[12];
145     values[1]  = m_size->getValue(frame).second / 100;
146     values[2]  = m_size->getValue(frame).first / 100;
147     values[3]  = m_orientation->getValue(frame).second;
148     values[4]  = m_orientation->getValue(frame).first;
149     values[5]  = m_randomness->getValue() ? 1.0 : 0.0;
150     values[6]  = m_distance->getValue(frame).second / 10;
151     values[7]  = m_distance->getValue(frame).first / 10;
152     values[8]  = m_density->getValue(frame) / 100;
153     values[9]  = m_keepLine->getValue() ? 1.0 : 0.0;
154     values[10] = m_keepColor->getValue() ? 1.0 : 0.0;
155     values[11] = m_includeAlpha->getValue() ? 1.0 : 0.0;
156     convertParam(values, argv, argc);
157   }
158   //----------------------------------------------------------------------
159 
strsave(const char * t)160   char *strsave(const char *t) {
161     char *s;
162     s = (char *)malloc(strlen(t) + 1);
163     strcpy(s, t);
164     return s;
165   }
166 
167   //-----------------------------------------------------------------------
168 
convertParam(double param[],const char * cParam[],int cParamLen)169   void convertParam(double param[], const char *cParam[], int cParamLen) {
170     std::string app;
171     for (int i = 1; i <= 11; i++) {
172       app       = std::to_string(param[i]);
173       cParam[i] = strsave(app.c_str());
174     }
175   }
176 };
177 
178 FX_PLUGIN_IDENTIFIER(ArtContourFx, "artContourFx");
179 
180 //-----------------------------------------------------------------------------
181 
doDryCompute(TRectD & rect,double frame,const TRenderSettings & ri)182 void ArtContourFx::doDryCompute(TRectD &rect, double frame,
183                                 const TRenderSettings &ri) {
184   if (!m_input.isConnected()) return;
185   if (!m_controller.isConnected()) return;
186 
187   TRenderSettings ri2(ri);
188   ri2.m_affine = TAffine();
189 
190   TRectD controlBox;
191   m_controller->getBBox(frame, controlBox, ri2);
192 
193   TDimension dim = convert(controlBox).getSize();
194   TRectD controlRect(controlBox.getP00(), TDimensionD(dim.lx, dim.ly));
195 
196   m_controller->dryCompute(controlRect, frame, ri2);
197 
198   TRenderSettings ri3(ri);
199 
200   int shrink               = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0);
201   std::string controlAlias = m_controller->getAlias(frame, ri2);
202   SandorFxRenderData *artContourData =
203       buildRenderData(frame, shrink, controlBox, controlAlias);
204   ri3.m_data.push_back(artContourData);
205   ri3.m_userCachable = false;
206 
207   m_input->dryCompute(rect, frame, ri3);
208 }
209 
210 //-----------------------------------------------------------------------------
211 
doCompute(TTile & tile,double frame,const TRenderSettings & ri)212 void ArtContourFx::doCompute(TTile &tile, double frame,
213                              const TRenderSettings &ri) {
214   if (!m_input.isConnected()) return;
215 
216   if (!m_controller.isConnected()) {
217     m_input->compute(tile, frame, ri);
218     return;
219   }
220 
221   TRenderSettings ri2(ri);
222   ri2.m_affine = TAffine();
223 
224   TRectD controlBox;
225   m_controller->getBBox(frame, controlBox, ri2);
226   TTile ctrTile;
227   ctrTile.m_pos  = controlBox.getP00();
228   TDimension dim = convert(controlBox).getSize();
229 
230   m_controller->allocateAndCompute(ctrTile, ctrTile.m_pos, dim,
231                                    tile.getRaster(), frame, ri2);
232 
233   TRenderSettings ri3(ri);
234 
235   // Build the render data
236   int shrink               = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0);
237   std::string controlAlias = m_controller->getAlias(frame, ri2);
238   SandorFxRenderData *artContourData =
239       buildRenderData(frame, shrink, controlBox, controlAlias);
240 
241   // Add the controller raster
242   artContourData->m_controller = ctrTile.getRaster();
243 
244   // Push the data among the others
245   ri3.m_data.push_back(artContourData);
246   ri3.m_userCachable = false;
247 
248   m_input->compute(tile, frame, ri3);
249 }
250