| |
| |
| #include "stdfx.h" |
| #include "tfxparam.h" |
| |
| #include "tdoubleparam.h" |
| |
| #include "tpixelgr.h" |
| #include "trasterfx.h" |
| |
| |
| |
| namespace |
| { |
| |
| |
| |
| enum Status { |
| StatusGood = 0, |
| OutOfTime = 1 << 1, |
| 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; |
| } |
| |
| |
| 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 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); |
| |
| m_ref->compute(tile, frame, ri); |
| |
| |
| 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 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") |
| |