1 
2 
3 #include "tfxparam.h"
4 #include "stdfx.h"
5 #include "tspectrumparam.h"
6 #include "tpixelutils.h"
7 #include "tparamuiconcept.h"
8 
9 namespace {
pixelConvert(TPixel32 & dst,const TPixel32 & src)10 inline void pixelConvert(TPixel32 &dst, const TPixel32 &src) { dst = src; }
pixelConvert(TPixel64 & dst,const TPixel32 & src)11 inline void pixelConvert(TPixel64 &dst, const TPixel32 &src) {
12   dst = toPixel64(src);
13 }
14 }  // namespace
15 
16 class FourPointsGradientFx final : public TStandardZeraryFx {
17   FX_PLUGIN_DECLARATION(FourPointsGradientFx)
18   TSpectrumParamP m_colors;
19   TPointParamP m_point1;
20   TPointParamP m_point2;
21   TPointParamP m_point3;
22   TPointParamP m_point4;
23   TPixelParamP m_color1;
24   TPixelParamP m_color2;
25   TPixelParamP m_color3;
26   TPixelParamP m_color4;
27 
28 public:
FourPointsGradientFx()29   FourPointsGradientFx()
30       : m_point1(TPointD(200.0, 200.0))
31       , m_point2(TPointD(-200.0, 200.0))
32       , m_point3(TPointD(-200.0, -200.0))
33       , m_point4(TPointD(200.0, -200.0))
34       , m_color1(TPixel32::Red)
35       , m_color2(TPixel32::Green)
36       , m_color3(TPixel32::Blue)
37       , m_color4(TPixel32::Yellow) {
38     m_point1->getX()->setMeasureName("fxLength");
39     m_point1->getY()->setMeasureName("fxLength");
40     m_point2->getX()->setMeasureName("fxLength");
41     m_point2->getY()->setMeasureName("fxLength");
42     m_point3->getX()->setMeasureName("fxLength");
43     m_point3->getY()->setMeasureName("fxLength");
44     m_point4->getX()->setMeasureName("fxLength");
45     m_point4->getY()->setMeasureName("fxLength");
46     /*
47 bindParam(this,"point1", m_point1);
48 bindParam(this,"point2", m_point2);
49 bindParam(this,"point3", m_point3);
50 bindParam(this,"point4", m_point4);
51 bindParam(this,"color_1", m_color1);
52 bindParam(this,"color_2", m_color2);
53 bindParam(this,"color_3", m_color3);
54 bindParam(this,"color_4", m_color4);
55 */
56     bindParam(this, "Point_1", m_point1);
57     bindParam(this, "Color_1", m_color1);
58 
59     bindParam(this, "Point_2", m_point2);
60     bindParam(this, "Color_2", m_color2);
61 
62     bindParam(this, "Point_3", m_point3);
63     bindParam(this, "Color_3", m_color3);
64 
65     bindParam(this, "Point_4", m_point4);
66     bindParam(this, "Color_4", m_color4);
67   }
~FourPointsGradientFx()68   ~FourPointsGradientFx(){};
69 
doGetBBox(double,TRectD & bbox,const TRenderSettings & info)70   bool doGetBBox(double, TRectD &bbox, const TRenderSettings &info) override {
71     bbox = TConsts::infiniteRectD;
72     return true;
73   };
74   void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
canHandle(const TRenderSettings & info,double frame)75   bool canHandle(const TRenderSettings &info, double frame) override {
76     return true;
77   }
78 
getParamUIs(TParamUIConcept * & concepts,int & length)79   void getParamUIs(TParamUIConcept *&concepts, int &length) override {
80     concepts = new TParamUIConcept[length = 4];
81 
82     concepts[0].m_type  = TParamUIConcept::POINT;
83     concepts[0].m_label = "Point 1";
84     concepts[0].m_params.push_back(m_point1);
85 
86     concepts[1].m_type  = TParamUIConcept::POINT;
87     concepts[1].m_label = "Point 2";
88     concepts[1].m_params.push_back(m_point2);
89 
90     concepts[2].m_type  = TParamUIConcept::POINT;
91     concepts[2].m_label = "Point 3";
92     concepts[2].m_params.push_back(m_point3);
93 
94     concepts[3].m_type  = TParamUIConcept::POINT;
95     concepts[3].m_label = "Point 4";
96     concepts[3].m_params.push_back(m_point4);
97   }
98 };
99 
100 template <typename PIXEL, typename CHANNEL_TYPE>
doFourPointsGradient(const TRasterPT<PIXEL> & ras,TPointD tilepos,TPointD pos1,TPointD pos2,TPointD pos3,TPointD pos4,TPixel32 ccol1,TPixel32 ccol2,TPixel32 ccol3,TPixel32 ccol4)101 void doFourPointsGradient(const TRasterPT<PIXEL> &ras, TPointD tilepos,
102                           TPointD pos1, TPointD pos2, TPointD pos3,
103                           TPointD pos4, TPixel32 ccol1, TPixel32 ccol2,
104                           TPixel32 ccol3, TPixel32 ccol4) {
105   PIXEL col1, col2, col3, col4;
106   pixelConvert(col1, ccol1);
107   pixelConvert(col2, ccol2);
108   pixelConvert(col3, ccol3);
109   pixelConvert(col4, ccol4);
110 
111   int j;
112   ras->lock();
113   for (j = 0; j < ras->getLy(); j++) {
114     TPointD pos = tilepos;
115     pos.y += j;
116     PIXEL *pix    = ras->pixels(j);
117     PIXEL *endPix = pix + ras->getLx();
118     while (pix < endPix) {
119       double d1 = sqrt((pos1.x - pos.x) * (pos1.x - pos.x) +
120                        (pos1.y - pos.y) * (pos1.y - pos.y));
121       if (!d1) {
122         *pix = col1;
123         pos.x += 1;
124         ++pix;
125         continue;
126       }
127       double d2 = sqrt((pos2.x - pos.x) * (pos2.x - pos.x) +
128                        (pos2.y - pos.y) * (pos2.y - pos.y));
129       if (!d2) {
130         *pix = col2;
131         pos.x += 1;
132         ++pix;
133         continue;
134       }
135       double d3 = sqrt((pos3.x - pos.x) * (pos3.x - pos.x) +
136                        (pos3.y - pos.y) * (pos3.y - pos.y));
137       if (!d3) {
138         *pix = col3;
139         pos.x += 1;
140         ++pix;
141         continue;
142       }
143       double d4 = sqrt((pos4.x - pos.x) * (pos4.x - pos.x) +
144                        (pos4.y - pos.y) * (pos4.y - pos.y));
145       if (!d4) {
146         *pix = col4;
147         pos.x += 1;
148         ++pix;
149         continue;
150       }
151       double dtotal = 1 / d1 + 1 / d2 + 1 / d3 + 1 / d4;
152       pix->r        = (CHANNEL_TYPE)(
153           ((1 / d1) / dtotal) * col1.r + ((1 / d2) / dtotal) * col2.r +
154           ((1 / d3) / dtotal) * col3.r + ((1 / d4) / dtotal) * col4.r);
155       pix->g = (CHANNEL_TYPE)(
156           ((1 / d1) / dtotal) * col1.g + ((1 / d2) / dtotal) * col2.g +
157           ((1 / d3) / dtotal) * col3.g + ((1 / d4) / dtotal) * col4.g);
158       pix->b = (CHANNEL_TYPE)(
159           ((1 / d1) / dtotal) * col1.b + ((1 / d2) / dtotal) * col2.b +
160           ((1 / d3) / dtotal) * col3.b + ((1 / d4) / dtotal) * col4.b);
161       pix->m = (CHANNEL_TYPE)(
162           ((1 / d1) / dtotal) * col1.m + ((1 / d2) / dtotal) * col2.m +
163           ((1 / d3) / dtotal) * col3.m + ((1 / d4) / dtotal) * col4.m);
164       pos.x += 1.0;
165       ++pix;
166     }
167   }
168   ras->unlock();
169 }
170 
doCompute(TTile & tile,double frame,const TRenderSettings & ri)171 void FourPointsGradientFx::doCompute(TTile &tile, double frame,
172                                      const TRenderSettings &ri) {
173   TPointD pos1  = m_point1->getValue(frame) * (1.0 / ri.m_shrinkX);
174   TPointD pos2  = m_point2->getValue(frame) * (1.0 / ri.m_shrinkX);
175   TPointD pos3  = m_point3->getValue(frame) * (1.0 / ri.m_shrinkX);
176   TPointD pos4  = m_point4->getValue(frame) * (1.0 / ri.m_shrinkX);
177   pos1          = ri.m_affine * pos1;
178   pos2          = ri.m_affine * pos2;
179   pos3          = ri.m_affine * pos3;
180   pos4          = ri.m_affine * pos4;
181   TPixel32 col1 = m_color1->getPremultipliedValue(frame);
182   TPixel32 col2 = m_color2->getPremultipliedValue(frame);
183   TPixel32 col3 = m_color3->getPremultipliedValue(frame);
184   TPixel32 col4 = m_color4->getPremultipliedValue(frame);
185 
186   TPointD pos         = tile.m_pos;
187   TRaster32P raster32 = tile.getRaster();
188 
189   if (raster32)
190     doFourPointsGradient<TPixel32, UCHAR>(raster32, pos, pos1, pos2, pos3, pos4,
191                                           col1, col2, col3, col4);
192   else {
193     TRaster64P raster64 = tile.getRaster();
194     if (raster64)
195       doFourPointsGradient<TPixel64, USHORT>(raster64, pos, pos1, pos2, pos3,
196                                              pos4, col1, col2, col3, col4);
197     else
198       throw TException("Brightness&Contrast: unsupported Pixel Type");
199   }
200 }
201 
202 FX_PLUGIN_IDENTIFIER(FourPointsGradientFx, "fourPointsGradientFx");
203