Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "tparamset.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
enum PixelOp { OVER = 0,
Toshihiro Shimizu 890ddd
			   ADD,
Toshihiro Shimizu 890ddd
			   SUBTRACT,
Toshihiro Shimizu 890ddd
			   MULTIPLY,
Toshihiro Shimizu 890ddd
			   LIGHTEN,
Toshihiro Shimizu 890ddd
			   DARKEN };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
int doBlurValue(PIXEL *SRC, int SRC_WRAP, int BLUR)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	unsigned int count = 0;
Toshihiro Shimizu 890ddd
	int h, k;
Toshihiro Shimizu 890ddd
	int blur_val;
Toshihiro Shimizu 890ddd
	PIXEL *pix, *line;
Toshihiro Shimizu 890ddd
	pix = line = (SRC) + (-(BLUR) + 1) * (SRC_WRAP);
Toshihiro Shimizu 890ddd
	for (h = -(BLUR) + 1; h < (BLUR); h++) {
Toshihiro Shimizu 890ddd
		for (k = -(BLUR) + 1; k < (BLUR); k++)
Toshihiro Shimizu 890ddd
			count += pix[k].m;
Toshihiro Shimizu 890ddd
		line += SRC_WRAP;
Toshihiro Shimizu 890ddd
		pix = line;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	blur_val = (int)(count / (4 * (float)(BLUR) * (float)((BLUR)-1) + 1));
Toshihiro Shimizu 890ddd
	return blur_val;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename channel_type="" pixel,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void doBlur(CHANNEL_TYPE *greymap, const TRasterPT<pixel> &rin, int blur)</pixel>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Perform a flat mean-convolution filter
Toshihiro Shimizu 890ddd
	//NOTE: This is improved due to separability of convolution kernel, plus
Toshihiro Shimizu 890ddd
	// - since its elements are all the same, only pixels entering and quitting
Toshihiro Shimizu 890ddd
	//the convolution area are added/subtracted from the sums.
Toshihiro Shimizu 890ddd
	//As a result, this yields an O(row*columns) complexity, independently
Toshihiro Shimizu 890ddd
	//from the blur factor.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, j;
Toshihiro Shimizu 890ddd
	int blurDiameter = 2 * blur + 1;
Toshihiro Shimizu 890ddd
	unsigned long sum;
Toshihiro Shimizu 890ddd
	int wrapSrc = rin->getWrap();
Toshihiro Shimizu 890ddd
	int wrapOut = rin->getLx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//First, blur each column independently
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//We'll need a temporary col for storing sums
Toshihiro Shimizu 890ddd
	unsigned long *tempCol = new unsigned long[rin->getLy()];
Toshihiro Shimizu 890ddd
	int edge = tmin(blur + 1, rin->getLy());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < rin->getLx(); ++i) {
Toshihiro Shimizu 890ddd
		PIXEL *lineSrcPix = rin->pixels(0) + i;
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *lineOutPix = greymap + i;
Toshihiro Shimizu 890ddd
		PIXEL *pixin = lineSrcPix;
Toshihiro Shimizu 890ddd
		unsigned long *pixsum = tempCol;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		memset(tempCol, 0, rin->getLy() * sizeof(unsigned long));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Build up to blur with retro-sums
Toshihiro Shimizu 890ddd
		sum = 0;
Toshihiro Shimizu 890ddd
		for (j = 0; j < edge; ++j, pixin += wrapSrc, ++pixsum) {
Toshihiro Shimizu 890ddd
			sum += pixin->m;
Toshihiro Shimizu 890ddd
			*pixsum = sum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Fill in after blur
Toshihiro Shimizu 890ddd
		PIXEL *queuepix = lineSrcPix;
Toshihiro Shimizu 890ddd
		for (j = edge; j < rin->getLy(); ++j, pixin += wrapSrc, queuepix += wrapSrc, ++pixsum) {
Toshihiro Shimizu 890ddd
			sum += (pixin->m - queuepix->m);
Toshihiro Shimizu 890ddd
			*pixsum = sum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Now, the same in reverse
Toshihiro Shimizu 890ddd
		lineSrcPix = lineSrcPix + (rin->getLy() - 1) * wrapSrc;
Toshihiro Shimizu 890ddd
		pixin = lineSrcPix;
Toshihiro Shimizu 890ddd
		pixsum = tempCol + rin->getLy() - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sum = 0;
Toshihiro Shimizu 890ddd
		for (j = 0; j < edge; ++j, pixin -= wrapSrc, --pixsum) {
Toshihiro Shimizu 890ddd
			*pixsum += sum;
Toshihiro Shimizu 890ddd
			sum += pixin->m;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		queuepix = lineSrcPix;
Toshihiro Shimizu 890ddd
		for (j = edge; j < rin->getLy(); ++j, pixin -= wrapSrc, queuepix -= wrapSrc, --pixsum) {
Toshihiro Shimizu 890ddd
			sum -= queuepix->m;
Toshihiro Shimizu 890ddd
			*pixsum += sum;
Toshihiro Shimizu 890ddd
			sum += pixin->m;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Finally, transfer sums to the output greymap, divided by the blur.
Toshihiro Shimizu 890ddd
		pixsum = tempCol;
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *pixout = lineOutPix;
Toshihiro Shimizu 890ddd
		for (j = 0; j < rin->getLy(); ++j, pixout += wrapOut, ++pixsum)
Toshihiro Shimizu 890ddd
			*pixout = (*pixsum) / blurDiameter;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete[] tempCol;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Then, the same for all greymap rows
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//We'll need a temporary row for sums
Toshihiro Shimizu 890ddd
	unsigned long *tempRow = new unsigned long[rin->getLx()];
Toshihiro Shimizu 890ddd
	edge = tmin(blur + 1, rin->getLx());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (j = 0; j < rin->getLy(); ++j) {
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *lineSrcPix = greymap + j * wrapOut;
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *lineOutPix = lineSrcPix;
Toshihiro Shimizu 890ddd
		unsigned long *pixsum = tempRow;
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *pixin = lineSrcPix;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		memset(tempRow, 0, rin->getLx() * sizeof(unsigned long));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Build up to blur with retro-sums
Toshihiro Shimizu 890ddd
		sum = 0;
Toshihiro Shimizu 890ddd
		for (i = 0; i < edge; ++i, ++pixin, ++pixsum) {
Toshihiro Shimizu 890ddd
			sum += *pixin;
Toshihiro Shimizu 890ddd
			*pixsum = sum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Fill in after blur
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *queuepix = lineSrcPix;
Toshihiro Shimizu 890ddd
		for (i = edge; i < rin->getLx(); ++i, ++pixin, ++pixsum, ++queuepix) {
Toshihiro Shimizu 890ddd
			sum += *pixin;
Toshihiro Shimizu 890ddd
			sum -= *queuepix;
Toshihiro Shimizu 890ddd
			*pixsum = sum;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Now, the same in reverse
Toshihiro Shimizu 890ddd
		lineSrcPix = lineSrcPix + rin->getLx() - 1;
Toshihiro Shimizu 890ddd
		pixin = lineSrcPix;
Toshihiro Shimizu 890ddd
		pixsum = tempRow + rin->getLx() - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sum = 0;
Toshihiro Shimizu 890ddd
		for (i = 0; i < edge; ++i, --pixin, --pixsum) {
Toshihiro Shimizu 890ddd
			*pixsum += sum;
Toshihiro Shimizu 890ddd
			sum += *pixin;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		queuepix = lineSrcPix;
Toshihiro Shimizu 890ddd
		for (i = edge; i < rin->getLx(); ++i, --pixin, --pixsum, --queuepix) {
Toshihiro Shimizu 890ddd
			sum -= *queuepix;
Toshihiro Shimizu 890ddd
			*pixsum += sum;
Toshihiro Shimizu 890ddd
			sum += *pixin;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Finally, transfer sums to the output greymap, divided by the blur.
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *pixout = lineOutPix;
Toshihiro Shimizu 890ddd
		pixsum = tempRow;
Toshihiro Shimizu 890ddd
		for (i = 0; i < rin->getLx(); ++i, ++pixout, ++pixsum)
Toshihiro Shimizu 890ddd
			*pixout = (*pixsum) / blurDiameter;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete[] tempRow;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void myOver(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixout = color;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void myAdd(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixout.r = tmin(pixin.r + color.r, PIXEL::maxChannelValue);
Toshihiro Shimizu 890ddd
	pixout.g = tmin(pixin.g + color.g, PIXEL::maxChannelValue);
Toshihiro Shimizu 890ddd
	pixout.b = tmin(pixin.b + color.b, PIXEL::maxChannelValue);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void mySub(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixout.r = tmax(pixin.r - color.r, 0);
Toshihiro Shimizu 890ddd
	pixout.g = tmax(pixin.g - color.g, 0);
Toshihiro Shimizu 890ddd
	pixout.b = tmax(pixin.b - color.b, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void myMult(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static const double den = PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pixout.r = pixin.r * (color.r / den);
Toshihiro Shimizu 890ddd
	pixout.g = pixin.g * (color.g / den);
Toshihiro Shimizu 890ddd
	pixout.b = pixin.b * (color.b / den);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void myLighten(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixout.r = pixin.r > color.r ? pixin.r : color.r;
Toshihiro Shimizu 890ddd
	pixout.g = pixin.g > color.g ? pixin.g : color.g;
Toshihiro Shimizu 890ddd
	pixout.b = pixin.b > color.b ? pixin.b : color.b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void myDarken(PIXEL &pixout, const PIXEL &pixin, const PIXEL &color)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixout.r = pixin.r < color.r ? pixin.r : color.r;
Toshihiro Shimizu 890ddd
	pixout.g = pixin.g < color.g ? pixin.g : color.g;
Toshihiro Shimizu 890ddd
	pixout.b = pixin.b < color.b ? pixin.b : color.b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename channel="" pixel,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void doLayerBlending(PIXEL *pixin, PIXEL *pixout, CHANNEL *pixmatte,
Toshihiro Shimizu 890ddd
					 int inLx, int outLx, int outLy, int wrapIn, int wrapOut, int dx, int dy,
Toshihiro Shimizu 890ddd
					 double transp, PIXEL color,
Toshihiro Shimizu 890ddd
					 void (*pixelOp)(PIXEL &, const PIXEL &, const PIXEL &))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double CROP_VAL = PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
	CHANNEL U_CROP_VAL = PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int const_transp = CROP_VAL * transp + 0.5;
Toshihiro Shimizu 890ddd
	double val_r, val_g, val_b, val_m;
Toshihiro Shimizu 890ddd
	int blur_val;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PIXEL opColor;
Toshihiro Shimizu 890ddd
	double k, matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	CHANNEL shadow_matte;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int x, y;
Toshihiro Shimizu 890ddd
	for (y = 0; y < outLy; ++y, pixin += wrapIn - outLx, pixout += wrapOut - outLx, pixmatte += inLx - outLx)
Toshihiro Shimizu 890ddd
		for (x = 0; x < outLx; ++x, ++pixin, ++pixout, ++pixmatte) {
Toshihiro Shimizu 890ddd
			if (pixin->m != 0) // where the image is transparent, no shadow
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				blur_val = *(pixmatte + dy * inLx + dx);
Toshihiro Shimizu 890ddd
				shadow_matte = (blur_val) ? (int)((CROP_VAL - blur_val) * transp + 0.5) : const_transp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				k = (double)(CROP_VAL - shadow_matte) / CROP_VAL;
Toshihiro Shimizu 890ddd
				val_r = pixin->r * k + 0.5;
Toshihiro Shimizu 890ddd
				val_g = pixin->g * k + 0.5;
Toshihiro Shimizu 890ddd
				val_b = pixin->b * k + 0.5;
Toshihiro Shimizu 890ddd
				val_m = pixin->m;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				pixelOp(opColor, *pixin, color);
Toshihiro Shimizu 890ddd
				matte = (1 - k) * (val_m / CROP_VAL);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				val_r += matte * opColor.r;
Toshihiro Shimizu 890ddd
				val_g += matte * opColor.g;
Toshihiro Shimizu 890ddd
				val_b += matte * opColor.b;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				pixout->r = (val_r > CROP_VAL) ? U_CROP_VAL : ((val_r < 0) ? 0 : (CHANNEL)val_r);
Toshihiro Shimizu 890ddd
				pixout->g = (val_g > CROP_VAL) ? U_CROP_VAL : ((val_g < 0) ? 0 : (CHANNEL)val_g);
Toshihiro Shimizu 890ddd
				pixout->b = (val_b > CROP_VAL) ? U_CROP_VAL : ((val_b < 0) ? 0 : (CHANNEL)val_b);
Toshihiro Shimizu 890ddd
				pixout->m = (val_m > CROP_VAL) ? U_CROP_VAL : ((val_m < 0) ? 0 : (CHANNEL)val_m);
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				*pixout = PIXEL::Transparent;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void doBodyHighlight(const TRasterPT<pixel> rout, const TRasterPT<pixel> rin,</pixel></pixel>
Toshihiro Shimizu 890ddd
					 TRectD rectIn, int rasInLx, int rasInLy, double frame, int blur,
Toshihiro Shimizu 890ddd
					 double transp, PIXEL color, TPointD point, bool invert,
Toshihiro Shimizu 890ddd
					 void (*pixelOp)(PIXEL &, const PIXEL &, const PIXEL &),
Toshihiro Shimizu 890ddd
					 TRasterFxPort &m_input, const TRenderSettings &ri)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef typename PIXEL::Channel CHANNEL_TYPE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rin->lock();
Toshihiro Shimizu 890ddd
	rout->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int inLx = rin->getLx(), inLy = rin->getLy(), inWrap = rin->getWrap();
Toshihiro Shimizu 890ddd
	int outLx = rout->getLx(), outLy = rout->getLy(), outWrap = rout->getWrap();
Toshihiro Shimizu 890ddd
	int dx = point.x, dy = point.y;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	transp = 1.0 - transp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PIXEL *src_buf, *dst_buf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	dst_buf = rout->pixels(0);
Toshihiro Shimizu 890ddd
	src_buf = rin->pixels(0) + blur + blur * inWrap;
Toshihiro Shimizu 890ddd
	if (dy < 0)
Toshihiro Shimizu 890ddd
		src_buf -= dy * inWrap;
Toshihiro Shimizu 890ddd
	if (dx < 0)
Toshihiro Shimizu 890ddd
		src_buf -= dx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//First, perform an optimized mean-convolution of the interesting part of image's matte
Toshihiro Shimizu 890ddd
	int matteLxLy = inLx * inLy;
Toshihiro Shimizu 890ddd
	CHANNEL_TYPE *matteGreymap = (CHANNEL_TYPE *)malloc(matteLxLy * sizeof(CHANNEL_TYPE));
Toshihiro Shimizu 890ddd
	if (!matteGreymap)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	memset(matteGreymap, 0, matteLxLy * sizeof(CHANNEL_TYPE));
Toshihiro Shimizu 890ddd
	doBlur<pixel, channel_type="">(matteGreymap, rin, blur);</pixel,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	CHANNEL_TYPE U_CROP_VAL = PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//If specified, invert the matte
Toshihiro Shimizu 890ddd
	if (invert) {
Toshihiro Shimizu 890ddd
		CHANNEL_TYPE *mpix, *end = matteGreymap + matteLxLy;
Toshihiro Shimizu 890ddd
		for (mpix = matteGreymap; mpix < end; ++mpix)
Toshihiro Shimizu 890ddd
			*mpix = U_CROP_VAL - *mpix;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	CHANNEL_TYPE *mattepix = matteGreymap + blur + blur * inLx;
Toshihiro Shimizu 890ddd
	if (dy < 0)
Toshihiro Shimizu 890ddd
		mattepix -= dy * inLx;
Toshihiro Shimizu 890ddd
	if (dx < 0)
Toshihiro Shimizu 890ddd
		mattepix -= dx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	doLayerBlending(src_buf, dst_buf, mattepix, inLx, outLx, outLy,
Toshihiro Shimizu 890ddd
					inWrap, outWrap, dx, dy, transp, color, pixelOp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	free(matteGreymap);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rin->unlock();
Toshihiro Shimizu 890ddd
	rout->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
//    BodyHighLightFx implementation
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class BodyHighLightFx : public TStandardRasterFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(BodyHighLightFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterFxPort m_input;
Toshihiro Shimizu 890ddd
	TIntEnumParamP m_mode;
Toshihiro Shimizu 890ddd
	TPointParamP m_point;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_transparency;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_blur;
Toshihiro Shimizu 890ddd
	TPixelParamP m_color;
Toshihiro Shimizu 890ddd
	TBoolParamP m_invert;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	BodyHighLightFx()
Toshihiro Shimizu 890ddd
		: m_point(TPointD(10.0, 10.0)), m_mode(new TIntEnumParam(OVER, "Over")), m_transparency(0.5), m_blur(2.0), m_color(TPixel32::White), m_invert(false)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_point->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		m_point->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		m_blur->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		bindParam(this, "mode", m_mode);
Toshihiro Shimizu 890ddd
		bindParam(this, "point", m_point);
Toshihiro Shimizu 890ddd
		bindParam(this, "transparency", m_transparency);
Toshihiro Shimizu 890ddd
		bindParam(this, "blur", m_blur);
Toshihiro Shimizu 890ddd
		bindParam(this, "color", m_color);
Toshihiro Shimizu 890ddd
		bindParam(this, "invert", m_invert);
Toshihiro Shimizu 890ddd
		addInputPort("Source", m_input);
Toshihiro Shimizu 890ddd
		m_transparency->setValueRange(0.0, 1.0);
Toshihiro Shimizu 890ddd
		m_blur->setValueRange(0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
		m_color->enableMatte(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_mode->addItem(ADD, "Add");
Toshihiro Shimizu 890ddd
		m_mode->addItem(SUBTRACT, "Subtract");
Toshihiro Shimizu 890ddd
		m_mode->addItem(MULTIPLY, "Multiply");
Toshihiro Shimizu 890ddd
		m_mode->addItem(LIGHTEN, "Lighten");
Toshihiro Shimizu 890ddd
		m_mode->addItem(DARKEN, "Darken");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~BodyHighLightFx(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_input.isConnected())
Toshihiro Shimizu 890ddd
			return m_input->doGetBBox(frame, bBox, info);
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			bBox = TRectD();
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool canHandle(const TRenderSettings &info, double frame) { return true; }
Toshihiro Shimizu 890ddd
	void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
	void doCompute(TTile &tile, double frame, const TRenderSettings &);
Toshihiro Shimizu 890ddd
	int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void BodyHighLightFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_input->dryCompute(rect, frame, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double fac = sqrt(fabs(info.m_affine.det()));
Toshihiro Shimizu 890ddd
	int blur = (int)(fac * fabs(m_blur->getValue(frame)));
Toshihiro Shimizu 890ddd
	TPoint point = convert(fac * m_point->getValue(frame));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD rectIn = rect.enlarge(blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int rasInLx = tround(rectIn.getLx() + abs(point.x)) + 1;
Toshihiro Shimizu 890ddd
	int rasInLy = tround(rectIn.getLy() + abs(point.y)) + 1;
Toshihiro Shimizu 890ddd
	if (point.x < 0) {
Toshihiro Shimizu 890ddd
		rectIn.x0 += point.x;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (point.y < 0) {
Toshihiro Shimizu 890ddd
		rectIn.y0 += point.y;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	rectIn = TRectD(rectIn.getP00(), TDimensionD(rasInLx, rasInLy));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_input->dryCompute(rectIn, frame, info);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void BodyHighLightFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double fac = sqrt(fabs(ri.m_affine.det()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Compute the effective input tile
Toshihiro Shimizu 890ddd
	m_input->compute(tile, frame, ri);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double transp = m_transparency->getValue(frame);
Toshihiro Shimizu 890ddd
	int blur = (int)(fac * fabs(m_blur->getValue(frame)));
Toshihiro Shimizu 890ddd
	TPoint point = convert(fac * m_point->getValue(frame));
Toshihiro Shimizu 890ddd
	bool invert = m_invert->getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build the shadow, blurred tile
Toshihiro Shimizu 890ddd
	TDimension rectSize(tile.getRaster()->getSize());
Toshihiro Shimizu 890ddd
	TRectD rectIn(tile.m_pos, TDimensionD(rectSize.lx, rectSize.ly));
Toshihiro Shimizu 890ddd
	rectIn = rectIn.enlarge(blur);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Shift rectIn by the input 'point'
Toshihiro Shimizu 890ddd
	int rasInLx = tround(rectIn.getLx() + abs(point.x)) + 1;
Toshihiro Shimizu 890ddd
	int rasInLy = tround(rectIn.getLy() + abs(point.y)) + 1;
Toshihiro Shimizu 890ddd
	if (point.x < 0) {
Toshihiro Shimizu 890ddd
		rectIn.x0 += point.x;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		rectIn.x1 += point.x;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (point.y < 0) {
Toshihiro Shimizu 890ddd
		rectIn.y0 += point.y;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		rectIn.y1 += point.y;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TPixel32 color = m_color->getPremultipliedValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P raster32 = tile.getRaster();
Toshihiro Shimizu 890ddd
	TRaster64P raster64 = tile.getRaster();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTile tileIn;
Toshihiro Shimizu 890ddd
	m_input->allocateAndCompute(tileIn, rectIn.getP00(),
Toshihiro Shimizu 890ddd
								TDimension(rasInLx, rasInLy),
Toshihiro Shimizu 890ddd
								tile.getRaster(), frame, ri);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Select the specified pixel operation
Toshihiro Shimizu 890ddd
	void (*pixelOp32)(TPixel32 &, const TPixel32 &, const TPixel32 &);
Toshihiro Shimizu 890ddd
	void (*pixelOp64)(TPixel64 &, const TPixel64 &, const TPixel64 &);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (m_mode->getValue()) {
Toshihiro Shimizu 890ddd
	case OVER: {
Toshihiro Shimizu 890ddd
		pixelOp32 = ::myOver<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
		pixelOp64 = ::myOver<tpixel64>;</tpixel64>
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	case ADD: {
Toshihiro Shimizu 890ddd
		pixelOp32 = ::myAdd<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
		pixelOp64 = ::myAdd<tpixel64>;</tpixel64>
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	case SUBTRACT: {
Toshihiro Shimizu 890ddd
		pixelOp32 = ::mySub<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
		pixelOp64 = ::mySub<tpixel64>;</tpixel64>
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	case MULTIPLY: {
Toshihiro Shimizu 890ddd
		pixelOp32 = ::myMult<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
		pixelOp64 = ::myMult<tpixel64>;</tpixel64>
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	case LIGHTEN: {
Toshihiro Shimizu 890ddd
		pixelOp32 = ::myLighten<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
		pixelOp64 = ::myLighten<tpixel64>;</tpixel64>
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	case DARKEN: {
Toshihiro Shimizu 890ddd
		pixelOp32 = ::myDarken<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
		pixelOp64 = ::myDarken<tpixel64>;</tpixel64>
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P rin = tileIn.getRaster();
Toshihiro Shimizu 890ddd
	if (raster32)
Toshihiro Shimizu 890ddd
		doBodyHighlight<tpixel32>(</tpixel32>
Toshihiro Shimizu 890ddd
			raster32, rin, rectIn, rasInLx, rasInLy, frame, blur,
Toshihiro Shimizu 890ddd
			transp, color, convert(point), invert, pixelOp32, m_input, ri);
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		TRaster64P rin = tileIn.getRaster();
Toshihiro Shimizu 890ddd
		if (raster64)
Toshihiro Shimizu 890ddd
			doBodyHighlight<tpixel64>(</tpixel64>
Toshihiro Shimizu 890ddd
				raster64, rin, rectIn, rasInLx, rasInLy, frame, blur,
Toshihiro Shimizu 890ddd
				transp, toPixel64(color), convert(point), invert, pixelOp64, m_input, ri);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			throw TException("Brightness&Contrast: unsupported Pixel Type");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int BodyHighLightFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int blur = (int)(sqrt(fabs(info.m_affine.det())) * fabs(m_blur->getValue(frame)));
Toshihiro Shimizu 890ddd
	return TRasterFx::memorySize(rect.enlarge(blur), info.m_bpp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(BodyHighLightFx, "bodyHighLightFx")