#include "stdfx.h"
#include "tfxparam.h"
//#include "trop.h"
#include "tdoubleparam.h"
//#include "tnotanimatableparam.h"
#include "tpixelgr.h"
#include "trasterfx.h"
//-------------------------------------------------------------------
namespace
{
//==================================================================
enum Status {
StatusGood = 0,
OutOfTime = 1 << 1, //Non utilizzato
Port0NotConnected = 1 << 2,
Port1NotConnected = 1 << 3,
NoPortsConnected = Port0NotConnected | Port1NotConnected
};
inline Status operator|(const Status &l, const Status &r)
{
return Status(((int)l | (int)r));
}
inline int operator&(const Status &l)
{
return int(l);
}
Status getFxStatus(const TRasterFxPort &port0, const TRasterFxPort &port1)
{
Status status = StatusGood;
if (!port0.isConnected())
status = status | Port0NotConnected;
if (!port1.isConnected())
status = status | Port1NotConnected;
return status;
}
/*inline*/
template <typename T, typename Q, typename P>
void doLocalTransparency(TRasterPT<T> out, TRasterPT<T> src, TRasterPT<T> ref, double transp)
{
out->lock();
ref->lock();
src->lock();
T *outRow = out->pixels();
T *refRow = ref->pixels();
T *srcRow = src->pixels();
int outWrap = out->getWrap();
int refWrap = ref->getWrap();
int srcWrap = src->getWrap();
T *outPix = outRow;
T *srcPix = srcRow;
T *refPix = refRow;
T *lastPix = outRow + outWrap * out->getLy();
const int cropVal = T::maxChannelValue;
double factor = transp / (double)cropVal;
while (outPix < lastPix) {
T *endPix = outPix + out->getLx();
while (outPix < endPix) {
double local_transp = 1 - (Q::from(*refPix).value) * factor;
if (local_transp > 0.0) {
int val = (int)(local_transp * srcPix->r + 0.5);
outPix->r = (P)((val < cropVal) ? val : cropVal);
val = (int)(local_transp * srcPix->g + 0.5);
outPix->g = (P)((val < cropVal) ? val : cropVal);
val = (int)(local_transp * srcPix->b + 0.5);
outPix->b = (P)((val < cropVal) ? val : cropVal);
val = (int)(local_transp * srcPix->m + 0.5);
outPix->m = (P)((val < cropVal) ? val : cropVal);
} else {
outPix->r = outPix->g = outPix->b = outPix->m = 0;
}
++outPix;
++refPix;
++srcPix;
}
srcRow += srcWrap;
outRow += outWrap;
refRow += refWrap;
srcPix = srcRow;
outPix = outRow;
refPix = refRow;
}
out->unlock();
ref->unlock();
src->unlock();
}
//-------------------------------------------------------------------
inline double func(int x, int y, int lx, int ly)
{
return ((1 + sin(3.14 * x / (0.5 * lx))) * (1 + cos(3.14 * y / (0.5 * ly))));
}
void drawCheckboard(TRaster32P &raster)
{
int lx = raster->getLx();
int ly = raster->getLy();
//int chessSize = 4;
int x, y;
raster->lock();
for (y = 0; y < ly; ++y) {
TPixel32 *pix = raster->pixels(y);
for (x = 0; x < lx; ++x, ++pix) {
pix->r = pix->g = pix->b = troundp(255.0 * func(x, y, lx, ly) / func(lx - 1, ly - 1, lx, ly));
pix->m = 255;
}
}
raster->unlock();
}
};
//-------------------------------------------------------------------
class LocalTransparencyFx : public TStandardRasterFx
{
FX_PLUGIN_DECLARATION(LocalTransparencyFx)
protected:
TRasterFxPort m_src, m_ref;
TDoubleParamP m_value;
public:
LocalTransparencyFx()
: m_value(100)
{
addInputPort("Source", m_src);
addInputPort("Reference", m_ref);
bindParam(this, "value", m_value);
m_value->setValueRange(0, 100);
}
virtual ~LocalTransparencyFx() {}
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
{
if (m_src.isConnected())
return m_src->doGetBBox(frame, bBox, info);
else {
bBox = TRectD();
return false;
}
}
void doCompute(TTile &tile, double frame, const TRenderSettings &ri)
{
if (!checkBeforeCompute(tile, frame, ri))
return;
TTile srcTile;
m_src->allocateAndCompute(srcTile, tile.m_pos, tile.getRaster()->getSize(), tile.getRaster(), frame, ri);
//TTile refTile = tile;
m_ref->compute(tile, frame, ri);
//TRaster32P ref32 (refTile.getRaster());
TRaster32P out32(tile.getRaster());
TRaster32P src32(srcTile.getRaster());
if (out32 && src32)
doLocalTransparency<TPixelRGBM32, TPixelGR8, UCHAR>(out32, src32, out32, m_value->getValue(frame) / 100.);
else {
//TRaster64P ref64(refTile.getRaster());
TRaster64P out64(tile.getRaster());
TRaster64P src64(srcTile.getRaster());
if (out64 && src64)
doLocalTransparency<TPixelRGBM64, TPixelGR16, USHORT>(out64, src64, out64, m_value->getValue(frame) / 100.);
else
throw TException("LocalTransparencyFx: unsupported raster type");
}
}
bool checkBeforeCompute(TTile &tile, double frame, const TRenderSettings &info)
{
Status status = getFxStatus(m_src, m_ref);
if ((status & NoPortsConnected) == NoPortsConnected)
return false;
if ((status & OutOfTime) == OutOfTime)
return false;
if ((status & Port0NotConnected) == Port0NotConnected)
return false;
if ((status & Port1NotConnected) == Port1NotConnected) {
m_src->compute(tile, frame, info);
return false;
}
assert(status == StatusGood);
return true;
}
bool canHandle(const TRenderSettings &info, double frame) { return true; }
int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
{
return TRasterFx::memorySize(rect, info.m_bpp);
}
};
//-------------------------------------------------------------------
FX_PLUGIN_IDENTIFIER(LocalTransparencyFx, "localTransparencyFx")