1 #ifndef _ofxsImageBlender_h_
2 #define _ofxsImageBlender_h_
3 
4 #include "ofxsProcessing.H"
5 
6 namespace OFX {
7 
8     /** @brief  Base class used to blend two images together */
9     class ImageBlenderBase : public OFX::ImageProcessor {
10     protected :
11         const OFX::Image *_fromImg; // be this at 0
12         const OFX::Image *_toImg;   // be this at 1
13         float             _blend;   // how much to blend
14 
15     public :
16         /** @brief no arg ctor */
ImageBlenderBase(OFX::ImageEffect & instance)17         ImageBlenderBase(OFX::ImageEffect &instance)
18           : OFX::ImageProcessor(instance)
19           , _fromImg(NULL)
20           , _toImg(NULL)
21           , _blend(0.5f)
22         {
23         }
24 
25         /** @brief set the src image */
setFromImg(const OFX::Image * v)26         void setFromImg(const OFX::Image *v) {_fromImg = v;}
setToImg(const OFX::Image * v)27         void setToImg(const OFX::Image *v)   {_toImg = v;}
28 
29         /** @brief set the scale */
setBlend(float v)30         void setBlend(float v) {_blend = v;}
31     };
32 
33     /** @brief templated class to blend between two images */
34     template <class PIX, int nComponents>
35     class ImageBlender : public ImageBlenderBase {
36     public :
37         // ctor
ImageBlender(OFX::ImageEffect & instance)38         ImageBlender(OFX::ImageEffect &instance)
39           : ImageBlenderBase(instance)
40         {}
41 
Lerp(const PIX & v1,const PIX & v2,float blend)42         static PIX Lerp(const PIX &v1,
43                         const PIX &v2,
44                         float blend)
45         {
46             return PIX((v2 - v1) * blend + v1);
47         }
48 
49         // and do some processing
multiThreadProcessImages(OfxRectI procWindow)50         void multiThreadProcessImages(OfxRectI procWindow)
51         {
52             float blend = _blend;
53             float blendComp = 1.0f - blend;
54 
55             for(int y = procWindow.y1; y < procWindow.y2; y++) {
56                 if(_effect.abort()) break;
57 
58                 PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y);
59 
60                 for(int x = procWindow.x1; x < procWindow.x2; x++) {
61 
62                     PIX *fromPix = (PIX *)  (_fromImg ? _fromImg->getPixelAddress(x, y) : 0);
63                     PIX *toPix   = (PIX *)  (_toImg   ? _toImg->getPixelAddress(x, y)   : 0);
64 
65                     if(fromPix && toPix) {
66                         for(int c = 0; c < nComponents; c++)
67                             dstPix[c] = Lerp(fromPix[c], toPix[c], blend);
68                     }
69                     else if(fromPix) {
70                         for(int c = 0; c < nComponents; c++)
71                             dstPix[c] = PIX(fromPix[c] * blendComp);
72                     }
73                     else if(toPix) {
74                         for(int c = 0; c < nComponents; c++)
75                             dstPix[c] = PIX(toPix[c] * blend);
76                     }
77                     else {
78                         for(int c = 0; c < nComponents; c++)
79                             dstPix[c] = PIX(0);
80                     }
81 
82                     dstPix += nComponents;
83                 }
84             }
85         }
86 
87     };
88 
89 };
90 
91 #endif
92 
93 
94