2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
|
|
|
|
#include "tfxparam.h"
|
|
|
|
#include "stdfx.h"
|
|
|
|
#include "tspectrumparam.h"
|
|
|
|
#include "tpixelutils.h"
|
|
|
|
#include "tparamuiconcept.h"
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
namespace {
|
2016-03-19 06:57:51 +13:00
|
|
|
inline void pixelConvert(TPixel32 &dst, const TPixel32 &src) { dst = src; }
|
2016-06-15 18:43:10 +12:00
|
|
|
inline void pixelConvert(TPixel64 &dst, const TPixel32 &src) {
|
|
|
|
dst = toPixel64(src);
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
2016-06-29 18:17:12 +12:00
|
|
|
class FourPointsGradientFx final : public TStandardZeraryFx {
|
2016-06-15 18:43:10 +12:00
|
|
|
FX_PLUGIN_DECLARATION(FourPointsGradientFx)
|
|
|
|
TSpectrumParamP m_colors;
|
|
|
|
TPointParamP m_point1;
|
|
|
|
TPointParamP m_point2;
|
|
|
|
TPointParamP m_point3;
|
|
|
|
TPointParamP m_point4;
|
|
|
|
TPixelParamP m_color1;
|
|
|
|
TPixelParamP m_color2;
|
|
|
|
TPixelParamP m_color3;
|
|
|
|
TPixelParamP m_color4;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
FourPointsGradientFx()
|
|
|
|
: m_point1(TPointD(200.0, 200.0))
|
|
|
|
, m_point2(TPointD(-200.0, 200.0))
|
|
|
|
, m_point3(TPointD(-200.0, -200.0))
|
|
|
|
, m_point4(TPointD(200.0, -200.0))
|
|
|
|
, m_color1(TPixel32::Red)
|
|
|
|
, m_color2(TPixel32::Green)
|
|
|
|
, m_color3(TPixel32::Blue)
|
|
|
|
, m_color4(TPixel32::Yellow) {
|
|
|
|
m_point1->getX()->setMeasureName("fxLength");
|
|
|
|
m_point1->getY()->setMeasureName("fxLength");
|
|
|
|
m_point2->getX()->setMeasureName("fxLength");
|
|
|
|
m_point2->getY()->setMeasureName("fxLength");
|
|
|
|
m_point3->getX()->setMeasureName("fxLength");
|
|
|
|
m_point3->getY()->setMeasureName("fxLength");
|
|
|
|
m_point4->getX()->setMeasureName("fxLength");
|
|
|
|
m_point4->getY()->setMeasureName("fxLength");
|
|
|
|
/*
|
|
|
|
bindParam(this,"point1", m_point1);
|
|
|
|
bindParam(this,"point2", m_point2);
|
|
|
|
bindParam(this,"point3", m_point3);
|
|
|
|
bindParam(this,"point4", m_point4);
|
|
|
|
bindParam(this,"color_1", m_color1);
|
|
|
|
bindParam(this,"color_2", m_color2);
|
|
|
|
bindParam(this,"color_3", m_color3);
|
|
|
|
bindParam(this,"color_4", m_color4);
|
2016-03-19 06:57:51 +13:00
|
|
|
*/
|
2016-06-15 18:43:10 +12:00
|
|
|
bindParam(this, "Point_1", m_point1);
|
|
|
|
bindParam(this, "Color_1", m_color1);
|
|
|
|
|
|
|
|
bindParam(this, "Point_2", m_point2);
|
|
|
|
bindParam(this, "Color_2", m_color2);
|
|
|
|
|
|
|
|
bindParam(this, "Point_3", m_point3);
|
|
|
|
bindParam(this, "Color_3", m_color3);
|
|
|
|
|
|
|
|
bindParam(this, "Point_4", m_point4);
|
|
|
|
bindParam(this, "Color_4", m_color4);
|
|
|
|
}
|
|
|
|
~FourPointsGradientFx(){};
|
|
|
|
|
2016-06-19 20:06:29 +12:00
|
|
|
bool doGetBBox(double, TRectD &bbox, const TRenderSettings &info) override {
|
2016-06-15 18:43:10 +12:00
|
|
|
bbox = TConsts::infiniteRectD;
|
|
|
|
return true;
|
|
|
|
};
|
2016-06-19 20:06:29 +12:00
|
|
|
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
|
2016-06-20 14:23:05 +12:00
|
|
|
bool canHandle(const TRenderSettings &info, double frame) override {
|
|
|
|
return true;
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
|
2016-06-19 20:06:29 +12:00
|
|
|
void getParamUIs(TParamUIConcept *&concepts, int &length) override {
|
2016-06-15 18:43:10 +12:00
|
|
|
concepts = new TParamUIConcept[length = 4];
|
|
|
|
|
|
|
|
concepts[0].m_type = TParamUIConcept::POINT;
|
|
|
|
concepts[0].m_label = "Point 1";
|
|
|
|
concepts[0].m_params.push_back(m_point1);
|
|
|
|
|
|
|
|
concepts[1].m_type = TParamUIConcept::POINT;
|
|
|
|
concepts[1].m_label = "Point 2";
|
|
|
|
concepts[1].m_params.push_back(m_point2);
|
|
|
|
|
|
|
|
concepts[2].m_type = TParamUIConcept::POINT;
|
|
|
|
concepts[2].m_label = "Point 3";
|
|
|
|
concepts[2].m_params.push_back(m_point3);
|
|
|
|
|
|
|
|
concepts[3].m_type = TParamUIConcept::POINT;
|
|
|
|
concepts[3].m_label = "Point 4";
|
|
|
|
concepts[3].m_params.push_back(m_point4);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename PIXEL, typename CHANNEL_TYPE>
|
2016-06-15 18:43:10 +12:00
|
|
|
void doFourPointsGradient(const TRasterPT<PIXEL> &ras, TPointD tilepos,
|
|
|
|
TPointD pos1, TPointD pos2, TPointD pos3,
|
|
|
|
TPointD pos4, TPixel32 ccol1, TPixel32 ccol2,
|
|
|
|
TPixel32 ccol3, TPixel32 ccol4) {
|
|
|
|
PIXEL col1, col2, col3, col4;
|
|
|
|
pixelConvert(col1, ccol1);
|
|
|
|
pixelConvert(col2, ccol2);
|
|
|
|
pixelConvert(col3, ccol3);
|
|
|
|
pixelConvert(col4, ccol4);
|
|
|
|
|
|
|
|
int j;
|
|
|
|
ras->lock();
|
|
|
|
for (j = 0; j < ras->getLy(); j++) {
|
|
|
|
TPointD pos = tilepos;
|
|
|
|
pos.y += j;
|
|
|
|
PIXEL *pix = ras->pixels(j);
|
|
|
|
PIXEL *endPix = pix + ras->getLx();
|
|
|
|
while (pix < endPix) {
|
|
|
|
double d1 = sqrt((pos1.x - pos.x) * (pos1.x - pos.x) +
|
|
|
|
(pos1.y - pos.y) * (pos1.y - pos.y));
|
|
|
|
if (!d1) {
|
|
|
|
*pix = col1;
|
|
|
|
pos.x += 1;
|
|
|
|
++pix;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
double d2 = sqrt((pos2.x - pos.x) * (pos2.x - pos.x) +
|
|
|
|
(pos2.y - pos.y) * (pos2.y - pos.y));
|
|
|
|
if (!d2) {
|
|
|
|
*pix = col2;
|
|
|
|
pos.x += 1;
|
|
|
|
++pix;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
double d3 = sqrt((pos3.x - pos.x) * (pos3.x - pos.x) +
|
|
|
|
(pos3.y - pos.y) * (pos3.y - pos.y));
|
|
|
|
if (!d3) {
|
|
|
|
*pix = col3;
|
|
|
|
pos.x += 1;
|
|
|
|
++pix;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
double d4 = sqrt((pos4.x - pos.x) * (pos4.x - pos.x) +
|
|
|
|
(pos4.y - pos.y) * (pos4.y - pos.y));
|
|
|
|
if (!d4) {
|
|
|
|
*pix = col4;
|
|
|
|
pos.x += 1;
|
|
|
|
++pix;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
double dtotal = 1 / d1 + 1 / d2 + 1 / d3 + 1 / d4;
|
|
|
|
pix->r = (CHANNEL_TYPE)(
|
|
|
|
((1 / d1) / dtotal) * col1.r + ((1 / d2) / dtotal) * col2.r +
|
|
|
|
((1 / d3) / dtotal) * col3.r + ((1 / d4) / dtotal) * col4.r);
|
|
|
|
pix->g = (CHANNEL_TYPE)(
|
|
|
|
((1 / d1) / dtotal) * col1.g + ((1 / d2) / dtotal) * col2.g +
|
|
|
|
((1 / d3) / dtotal) * col3.g + ((1 / d4) / dtotal) * col4.g);
|
|
|
|
pix->b = (CHANNEL_TYPE)(
|
|
|
|
((1 / d1) / dtotal) * col1.b + ((1 / d2) / dtotal) * col2.b +
|
|
|
|
((1 / d3) / dtotal) * col3.b + ((1 / d4) / dtotal) * col4.b);
|
|
|
|
pix->m = (CHANNEL_TYPE)(
|
|
|
|
((1 / d1) / dtotal) * col1.m + ((1 / d2) / dtotal) * col2.m +
|
|
|
|
((1 / d3) / dtotal) * col3.m + ((1 / d4) / dtotal) * col4.m);
|
|
|
|
pos.x += 1.0;
|
|
|
|
++pix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ras->unlock();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void FourPointsGradientFx::doCompute(TTile &tile, double frame,
|
|
|
|
const TRenderSettings &ri) {
|
|
|
|
TPointD pos1 = m_point1->getValue(frame) * (1.0 / ri.m_shrinkX);
|
|
|
|
TPointD pos2 = m_point2->getValue(frame) * (1.0 / ri.m_shrinkX);
|
|
|
|
TPointD pos3 = m_point3->getValue(frame) * (1.0 / ri.m_shrinkX);
|
|
|
|
TPointD pos4 = m_point4->getValue(frame) * (1.0 / ri.m_shrinkX);
|
|
|
|
pos1 = ri.m_affine * pos1;
|
|
|
|
pos2 = ri.m_affine * pos2;
|
|
|
|
pos3 = ri.m_affine * pos3;
|
|
|
|
pos4 = ri.m_affine * pos4;
|
|
|
|
TPixel32 col1 = m_color1->getPremultipliedValue(frame);
|
|
|
|
TPixel32 col2 = m_color2->getPremultipliedValue(frame);
|
|
|
|
TPixel32 col3 = m_color3->getPremultipliedValue(frame);
|
|
|
|
TPixel32 col4 = m_color4->getPremultipliedValue(frame);
|
|
|
|
|
|
|
|
TPointD pos = tile.m_pos;
|
|
|
|
TRaster32P raster32 = tile.getRaster();
|
|
|
|
|
|
|
|
if (raster32)
|
|
|
|
doFourPointsGradient<TPixel32, UCHAR>(raster32, pos, pos1, pos2, pos3, pos4,
|
|
|
|
col1, col2, col3, col4);
|
|
|
|
else {
|
|
|
|
TRaster64P raster64 = tile.getRaster();
|
|
|
|
if (raster64)
|
|
|
|
doFourPointsGradient<TPixel64, USHORT>(raster64, pos, pos1, pos2, pos3,
|
|
|
|
pos4, col1, col2, col3, col4);
|
|
|
|
else
|
|
|
|
throw TException("Brightness&Contrast: unsupported Pixel Type");
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
FX_PLUGIN_IDENTIFIER(FourPointsGradientFx, "fourPointsGradientFx");
|