1 
2 
3 #include "texception.h"
4 #include "stdfx.h"
5 #include "tpixelutils.h"
6 #include "tbasefx.h"
7 #include "tfxparam.h"
8 #include "trop.h"
9 
10 #include "tparamset.h"
11 
12 //---------------------------------------------------------------------
13 
backlit(TRaster32P lighted,TRaster32P light,TRaster32P out,double blur,const TPixel & color,double fade,double scale)14 static void backlit(TRaster32P lighted, TRaster32P light, TRaster32P out,
15                     double blur, const TPixel &color, double fade,
16                     double scale) {
17   assert(light && lighted && out);
18 
19   assert(lighted->getSize() == light->getSize());
20   assert(lighted->getSize() == out->getSize());
21 
22   int j;
23 
24   if (fade > 0.0) {
25     assert(fade <= 1.0);
26     light->lock();
27     for (j = 0; j < light->getLy(); j++) {
28       TPixel *pix    = light->pixels(j);
29       TPixel *endPix = pix + light->getLx();
30 
31       while (pix < endPix) {
32         if (pix->m > 0) {
33           if (pix->m == 255) {
34             pix->r = troundp(pix->r + fade * (color.r - pix->r));
35             pix->g = troundp(pix->g + fade * (color.g - pix->g));
36             pix->b = troundp(pix->b + fade * (color.b - pix->b));
37             pix->m = troundp(pix->m + fade * (color.m - pix->m));
38           } else {
39             int val;
40             double factor = pix->m / 255.0;
41             val    = troundp(pix->r + fade * (color.r * factor - pix->r));
42             pix->r = (val > 255) ? 255 : val;
43             val    = troundp(pix->g + fade * (color.g * factor - pix->g));
44             pix->g = (val > 255) ? 255 : val;
45             val    = troundp(pix->b + fade * (color.b * factor - pix->b));
46             pix->b = (val > 255) ? 255 : val;
47             val    = troundp(pix->m + fade * (color.m * factor - pix->m));
48             pix->m = (val > 255) ? 255 : val;
49           }
50         }
51         ++pix;
52       }
53     }
54     light->unlock();
55   }
56 
57   TRop::ropout(light, lighted, light);
58 
59   if (blur > 0) {
60     double _blur = blur * scale;
61     int bi       = tceil(_blur);
62     TRaster32P ras(light->getLx() + bi, light->getLy() + bi);
63 
64     TRect rect(light->getBounds() + TPoint(bi, bi));
65     TRop::copy(ras->extract(rect), light);
66 
67     TRop::blur(out, ras, _blur, -bi, -bi, true);
68 
69     double ampl = 1.0 + blur / 15.0;
70     out->lock();
71     for (j = 0; j < out->getLy(); j++) {
72       TPixel *pix    = out->pixels(j);
73       TPixel *endPix = pix + out->getLx();
74       while (pix < endPix) {
75         if (pix->m != 0) {
76           int val = troundp(pix->r * ampl);
77           pix->r  = (val > 204) ? 204 : val;
78           val     = troundp(pix->g * ampl);
79           pix->g  = (val > 204) ? 204 : val;
80           val     = troundp(pix->b * ampl);
81           pix->b  = (val > 204) ? 204 : val;
82           val     = troundp(pix->m * ampl);
83           pix->m  = (val > 204) ? 204 : val;
84         }
85         pix++;
86       }
87     }
88     out->unlock();
89     TRop::over(out, lighted, out);
90   } else
91     TRop::over(out, lighted, light);
92 }
93 
94 //---------------------------------------------------------------------
95 
backlit(TRaster64P lighted,TRaster64P light,TRaster64P out,double blur,const TPixel & color32,double fade,double scale)96 static void backlit(TRaster64P lighted, TRaster64P light, TRaster64P out,
97                     double blur, const TPixel &color32, double fade,
98                     double scale) {
99   assert(light && lighted && out);
100 
101   assert(lighted->getSize() == light->getSize());
102   assert(lighted->getSize() == out->getSize());
103 
104   int j;
105   TPixel64 color = toPixel64(color32);
106 
107   if (fade > 0.0) {
108     assert(fade <= 1.0);
109     light->lock();
110     for (j = 0; j < light->getLy(); j++) {
111       TPixel64 *pix    = light->pixels(j);
112       TPixel64 *endPix = pix + light->getLx();
113 
114       while (pix < endPix) {
115         if (pix->m > 0) {
116           if (pix->m == 65535) {
117             pix->r = troundp(pix->r + fade * (color.r - pix->r));
118             pix->g = troundp(pix->g + fade * (color.g - pix->g));
119             pix->b = troundp(pix->b + fade * (color.b - pix->b));
120             pix->m = troundp(pix->m + fade * (color.m - pix->m));
121           } else {
122             int val;
123             double factor = pix->m / 65535.0;
124             val    = troundp(pix->r + fade * (color.r * factor - pix->r));
125             pix->r = (val > 65535) ? 65535 : val;
126             val    = troundp(pix->g + fade * (color.g * factor - pix->g));
127             pix->g = (val > 65535) ? 65535 : val;
128             val    = troundp(pix->b + fade * (color.b * factor - pix->b));
129             pix->b = (val > 65535) ? 65535 : val;
130             val    = troundp(pix->m + fade * (color.m * factor - pix->m));
131             pix->m = (val > 65535) ? 65535 : val;
132           }
133         }
134         ++pix;
135       }
136     }
137     light->unlock();
138   }
139 
140   TRop::ropout(light, lighted, light);
141 
142   if (blur > 0) {
143     double _blur = blur * scale;
144     int bi       = tceil(_blur);
145     TRaster64P ras(light->getLx() + bi, light->getLy() + bi);
146 
147     TRect rect(light->getBounds() + TPoint(bi, bi));
148     TRop::copy(ras->extract(rect), light);
149 
150     TRop::blur(out, ras, _blur, -bi, -bi, false);
151 
152     double ampl = 1.0 + blur / 15.0;
153     out->lock();
154     int fac = (204 << 8) | 204;
155 
156     for (j = 0; j < out->getLy(); j++) {
157       TPixel64 *pix    = out->pixels(j);
158       TPixel64 *endPix = pix + out->getLx();
159       while (pix < endPix) {
160         if (pix->m != 0) {
161           int val = troundp(pix->r * ampl);
162           pix->r  = (val > fac) ? fac : val;
163           val     = troundp(pix->g * ampl);
164           pix->g  = (val > fac) ? fac : val;
165           val     = troundp(pix->b * ampl);
166           pix->b  = (val > fac) ? fac : val;
167           val     = troundp(pix->m * ampl);
168           pix->m  = (val > fac) ? fac : val;
169         }
170         pix++;
171       }
172     }
173     out->unlock();
174     TRop::over(out, lighted, out);
175   } else
176     TRop::over(out, lighted, light);
177 }
178 
179 //---------------------------------------------------------------------
180 
181 class BacklitFx final : public TBaseRasterFx {
182   FX_DECLARATION(BacklitFx)
183   TRasterFxPort m_lighted, m_light;
184   TDoubleParamP m_value;
185   TDoubleParamP m_fade;
186 
187   TPixelParamP m_color;
188 
189 public:
BacklitFx()190   BacklitFx() : m_value(0.0), m_color(TPixel::White), m_fade(0.0) {
191     m_color->enableMatte(true);
192     m_value->setValueRange(0, (std::numeric_limits<double>::max)());
193     m_fade->setValueRange(0.0, 100.0);
194     bindParam(this, "value", m_value);
195     bindParam(this, "color", m_color);
196     bindParam(this, "fade", m_fade);
197 
198     addInputPort("Light", m_light);
199     addInputPort("Source", m_lighted);
200   }
~BacklitFx()201   ~BacklitFx() {}
doGetBBox(double frame,TRectD & bbox,const TRenderSettings & info)202   bool doGetBBox(double frame, TRectD &bbox,
203                  const TRenderSettings &info) override {
204     if (getActiveTimeRegion().contains(frame)) {
205       if (m_light.isConnected()) {
206         if (m_lighted.isConnected()) {
207           TRectD b0, b1;
208           bool ret = m_light->doGetBBox(frame, b0, info);
209           ret      = ret && m_lighted->doGetBBox(frame, b1, info);
210           bbox     = b0.enlarge(tceil(m_value->getValue(frame))) + b1;
211           return ret;
212         } else {
213           return m_light->doGetBBox(frame, bbox, info);
214 	}
215       } else if (m_lighted.isConnected()) {
216         return m_lighted->doGetBBox(frame, bbox, info);
217       }
218     }
219     return false;
220   }
221 
doDryCompute(TRectD & rect,double frame,const TRenderSettings & info)222   void doDryCompute(TRectD &rect, double frame,
223                     const TRenderSettings &info) override {
224     if (!m_light.isConnected()) return;
225     if (!m_lighted.isConnected()) {
226       m_light->dryCompute(rect, frame, info);
227       return;
228     }
229 
230     double value = m_value->getValue(frame);
231     double scale = sqrt(fabs(info.m_affine.det()));
232     int brad     = tceil(value * scale);
233 
234     TRectD inRect = rect.enlarge(brad);
235     inRect = TRectD(tfloor(inRect.x0), tfloor(inRect.y0), tceil(inRect.x1),
236                     tceil(inRect.y1));
237 
238     m_lighted->dryCompute(inRect, frame, info);
239     m_light->dryCompute(inRect, frame, info);
240   }
241 
doCompute(TTile & tile,double frame,const TRenderSettings & ri)242   void doCompute(TTile &tile, double frame,
243                  const TRenderSettings &ri) override {
244     if (!m_light.isConnected()) return;
245 
246     if (!m_lighted.isConnected()) {
247       m_light->compute(tile, frame, ri);
248       return;
249     }
250 
251     double value = m_value->getValue(frame);
252     double scale = sqrt(fabs(ri.m_affine.det()));
253     int brad     = tceil(value * scale);
254 
255     TDimension tileSize(tile.getRaster()->getSize());
256     TRectD rect(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly));
257 
258     // TRectD
259     // rect(tile.m_pos,convert(tile.getRaster()->getBounds().getP11())+tile.m_pos);
260     rect = rect.enlarge(brad);
261     TRect rectI(tfloor(rect.x0), tfloor(rect.y0), tceil(rect.x1) - 1,
262                 tceil(rect.y1) - 1);
263     // m_light->compute(tile, frame, ri);
264     TTile srcTile;
265     m_lighted->allocateAndCompute(srcTile, rect.getP00(), rectI.getSize(),
266                                   tile.getRaster(), frame, ri);
267     TTile ctrTile;
268     m_light->allocateAndCompute(ctrTile, rect.getP00(), rectI.getSize(),
269                                 tile.getRaster(), frame, ri);
270     if ((TRaster32P)srcTile.getRaster() && (TRaster32P)tile.getRaster())
271       backlit((TRaster32P)srcTile.getRaster(), (TRaster32P)ctrTile.getRaster(),
272               (TRaster32P)ctrTile.getRaster(), value, m_color->getValue(frame),
273               m_fade->getValue(frame) / 100.0, scale);
274     else if ((TRaster64P)srcTile.getRaster() && (TRaster64P)tile.getRaster())
275       backlit((TRaster64P)srcTile.getRaster(), (TRaster64P)ctrTile.getRaster(),
276               (TRaster64P)ctrTile.getRaster(), value, m_color->getValue(frame),
277               m_fade->getValue(frame) / 100.0, scale);
278     else
279       throw TRopException("TRop::max invalid raster combination");
280     tile.getRaster()->copy(ctrTile.getRaster(), TPoint(-brad, -brad));
281   }
282 
canHandle(const TRenderSettings & info,double frame)283   bool canHandle(const TRenderSettings &info, double frame) override {
284     return true;
285   }
286 
getMemoryRequirement(const TRectD & rect,double frame,const TRenderSettings & info)287   int getMemoryRequirement(const TRectD &rect, double frame,
288                            const TRenderSettings &info) override {
289     double value = m_value->getValue(frame);
290     double scale = sqrt(fabs(info.m_affine.det()));
291     int brad     = tceil(value * scale);
292 
293     return TRasterFx::memorySize(rect.enlarge(brad), info.m_bpp);
294   }
295 };
296 
297 //==================================================================
298 
299 FX_PLUGIN_IDENTIFIER(BacklitFx, "backlitFx")
300 //==================================================================
301