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 "trop.h"
Toshihiro Shimizu 890ddd
#include "tparamset.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace stuff
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
inline void pixelConvert(TPixel32 &dst, const TPixel32 &src) { dst = src; }
Toshihiro Shimizu 890ddd
inline void pixelConvert(TPixel64 &dst, const TPixel32 &src) { dst = toPixel64(src); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TRect gridAlign(const TRect &rect, TPoint origin, double step)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRect result(rect);
Toshihiro Shimizu 890ddd
	result -= origin;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	result.x0 = step * tfloor(result.x0 / step);
Toshihiro Shimizu 890ddd
	result.y0 = step * tfloor(result.y0 / step);
Toshihiro Shimizu 890ddd
	result.x1 = step * tceil((result.x1 + 1) / step) - 1;
Toshihiro Shimizu 890ddd
	result.y1 = step * tceil((result.y1 + 1) / step) - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	result += origin;
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TRectD gridAlign(const TRectD &rect, TPointD origin, double step)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD result(rect);
Toshihiro Shimizu 890ddd
	result -= origin;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	result.x0 = step * tfloor(result.x0 / step);
Toshihiro Shimizu 890ddd
	result.y0 = step * tfloor(result.y0 / step);
Toshihiro Shimizu 890ddd
	result.x1 = step * tceil(result.x1 / step);
Toshihiro Shimizu 890ddd
	result.y1 = step * tceil(result.y1 / step);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	result += origin;
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Mosaic Namespace
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace mosaic
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
    The mosaic::CellBuilder class is the virtual base class used by MosaicFx
Toshihiro Shimizu 890ddd
    to render a Mosaic cell with supplied colors.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
class CellBuilder
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	int m_lx, m_ly;
Toshihiro Shimizu 890ddd
	double m_radius;
Toshihiro Shimizu 890ddd
	int m_wrap;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CellBuilder(int cellLx, int cellLy, double radius, int wrap)
Toshihiro Shimizu 890ddd
		: m_lx(cellLx), m_ly(cellLy), m_radius(radius), m_wrap(wrap) {}
Toshihiro Shimizu 890ddd
	virtual ~CellBuilder() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual void doCell(
Toshihiro Shimizu 890ddd
		PIXEL *cellBuffer, const PIXEL &cellColor, const PIXEL &bgColor,
Toshihiro Shimizu 890ddd
		int x0, int y0, int x1, int y1) = 0;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace mosaic
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    CellBuilder implementations
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace mosaic
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename gray="" pixel,="" typename=""></typename>
Toshihiro Shimizu 890ddd
class MaskCellBuilder : public CellBuilder<pixel></pixel>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	TRasterPT<gray> m_mask;</gray>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	MaskCellBuilder(int cellLx, int cellLy, double radius, int wrap)
Toshihiro Shimizu 890ddd
		: CellBuilder<pixel>(cellLx, cellLy, radius, wrap) {}</pixel>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void doCell(
Toshihiro Shimizu 890ddd
		PIXEL *cellBuffer, const PIXEL &cellColor, const PIXEL &bgColor,
Toshihiro Shimizu 890ddd
		int x0, int y0, int x1, int y1)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//Apply the mask to the cell. 0 pixels are bgColored, GRAY::maxChannelValue
Toshihiro Shimizu 890ddd
		//ones are cellColored.
Toshihiro Shimizu 890ddd
		PIXEL *pix, *line = cellBuffer, *lineEnd;
Toshihiro Shimizu 890ddd
		GRAY *grPix, *grLine = m_mask->pixels(y0) + x0, *grLineEnd;
Toshihiro Shimizu 890ddd
		int x, y, grWrap = m_mask->getWrap(), lx = x1 - x0;
Toshihiro Shimizu 890ddd
		for (y = y0; y < y1; ++y, line += this->m_wrap, grLine += grWrap) {
Toshihiro Shimizu 890ddd
			lineEnd = line + lx;
Toshihiro Shimizu 890ddd
			grLineEnd = grLine + lx;
Toshihiro Shimizu 890ddd
			for (x = x0, pix = line, grPix = grLine; x < x1; ++x, ++pix, ++grPix)
Toshihiro Shimizu 890ddd
				*pix = blend(bgColor, cellColor, grPix->value / (double)GRAY::maxChannelValue);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename gray="" pixel,="" typename=""></typename>
Toshihiro Shimizu 890ddd
class SquareBuilder : public MaskCellBuilder<pixel, gray=""></pixel,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	SquareBuilder(int cellLx, int cellLy, double radius, int wrap)
Toshihiro Shimizu 890ddd
		: MaskCellBuilder<pixel, gray="">(cellLx, cellLy, radius, wrap)</pixel,>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//Build the mask corresponding to a square of passed radius
Toshihiro Shimizu 890ddd
		GRAY *pix, *pixRev, *line, *lineEnd, *lineRev;
Toshihiro Shimizu 890ddd
		this->m_mask = TRasterPT<gray>(cellLx, cellLy);</gray>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//For each pixel in the lower-left quadrant, fill in the corresponding mask value.
Toshihiro Shimizu 890ddd
		//The other ones are filled by mirroring.
Toshihiro Shimizu 890ddd
		int i, j;
Toshihiro Shimizu 890ddd
		double lxHalf = 0.5 * cellLx, lyHalf = 0.5 * cellLy;
Toshihiro Shimizu 890ddd
		int lxHalfI = tceil(lxHalf), lyHalfI = tceil(lyHalf);
Toshihiro Shimizu 890ddd
		double val, addValX = radius - lxHalf + 1, addValY = radius - lyHalf + 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < lyHalfI; ++i) {
Toshihiro Shimizu 890ddd
			line = this->m_mask->pixels(i), lineRev = this->m_mask->pixels(cellLy - i - 1);
Toshihiro Shimizu 890ddd
			lineEnd = line + cellLx;
Toshihiro Shimizu 890ddd
			for (j = 0, pix = line, pixRev = lineEnd - 1; j < lxHalfI; ++j, ++pix, --pixRev) {
Toshihiro Shimizu 890ddd
				val = tcrop(addValX + i, 0.0, 1.0) * tcrop(addValY + j, 0.0, 1.0);
Toshihiro Shimizu 890ddd
				*pix = *pixRev = val * GRAY::maxChannelValue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			memcpy(lineRev, line, cellLx * sizeof(GRAY));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename gray="" pixel,="" typename=""></typename>
Toshihiro Shimizu 890ddd
class CircleBuilder : public MaskCellBuilder<pixel, gray=""></pixel,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CircleBuilder(int cellLx, int cellLy, double radius, int wrap)
Toshihiro Shimizu 890ddd
		: MaskCellBuilder<pixel, gray="">(cellLx, cellLy, radius, wrap)</pixel,>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//Build the mask corresponding to a square of passed radius
Toshihiro Shimizu 890ddd
		GRAY *pix, *pixRev, *line, *lineEnd, *lineRev;
Toshihiro Shimizu 890ddd
		this->m_mask = TRasterPT<gray>(cellLx, cellLy);</gray>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//For each pixel in the lower-left quadrant, fill in the corresponding mask value.
Toshihiro Shimizu 890ddd
		//The other ones are filled by mirroring.
Toshihiro Shimizu 890ddd
		int i, j;
Toshihiro Shimizu 890ddd
		double lxHalf = 0.5 * cellLx, lyHalf = 0.5 * cellLy;
Toshihiro Shimizu 890ddd
		int lxHalfI = tceil(lxHalf), lyHalfI = tceil(lyHalf);
Toshihiro Shimizu 890ddd
		double val, addValX = 0.5 - lxHalf, addValY = 0.5 - lyHalf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < lyHalfI; ++i) {
Toshihiro Shimizu 890ddd
			line = this->m_mask->pixels(i), lineRev = this->m_mask->pixels(cellLy - i - 1);
Toshihiro Shimizu 890ddd
			lineEnd = line + cellLx;
Toshihiro Shimizu 890ddd
			for (j = 0, pix = line, pixRev = lineEnd - 1; j < lxHalfI; ++j, ++pix, --pixRev) {
Toshihiro Shimizu 890ddd
				val = tcrop(radius - sqrt(sq(i + addValX) + sq(j + addValY)), 0.0, 1.0);
Toshihiro Shimizu 890ddd
				*pix = *pixRev = val * GRAY::maxChannelValue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			memcpy(lineRev, line, cellLx * sizeof(GRAY));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace mosaic
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
//    Mosaic Fx
Toshihiro Shimizu 890ddd
//****************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class MosaicFx : public TStandardRasterFx
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FX_PLUGIN_DECLARATION(MosaicFx)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterFxPort m_input;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_size;
Toshihiro Shimizu 890ddd
	TDoubleParamP m_distance;
Toshihiro Shimizu 890ddd
	TPixelParamP m_bgcolor;
Toshihiro Shimizu 890ddd
	TIntEnumParamP m_shape;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	MosaicFx()
Toshihiro Shimizu 890ddd
		: m_size(10.0), m_distance(10.0), m_bgcolor(TPixel32::Transparent), m_shape(new TIntEnumParam(0, "Square"))
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_size->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		m_distance->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
		bindParam(this, "size", m_size);
Toshihiro Shimizu 890ddd
		bindParam(this, "distance", m_distance);
Toshihiro Shimizu 890ddd
		bindParam(this, "bg_color", m_bgcolor);
Toshihiro Shimizu 890ddd
		bindParam(this, "shape", m_shape);
Toshihiro Shimizu 890ddd
		addInputPort("Source", m_input);
Toshihiro Shimizu 890ddd
		m_size->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
		m_distance->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
		m_shape->addItem(1, "Round");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~MosaicFx(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void doDryCompute(TRectD &rect, double frame, const TRenderSettings &ri);
Toshihiro Shimizu 890ddd
	void doCompute(TTile &tile, double frame, const TRenderSettings &ri);
Toshihiro Shimizu 890ddd
	int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//We'll return the handled affine only through handledAffine().
Toshihiro Shimizu 890ddd
		if ((m_size->getValue(frame) + m_distance->getValue(frame)) == 0.0)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TAffine handledAffine(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		//Return the default implementation: only the scale part of the affine
Toshihiro Shimizu 890ddd
		//can be handled. Rotations and other distortions would need us have to
Toshihiro Shimizu 890ddd
		//implement diagonal grid lines - and we don't want to!
Toshihiro Shimizu 890ddd
		//Also, no translational component will be dealt for the same reason.
Toshihiro Shimizu 890ddd
		TAffine scalePart(TRasterFx::handledAffine(info, frame));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Plus, we want to avoid dealing with antialiases even on plain orthogonal
Toshihiro Shimizu 890ddd
		//lines! So, we ensure that the step size will be flattened to integer.
Toshihiro Shimizu 890ddd
		double stepSize = m_size->getValue(frame) + m_distance->getValue(frame);
Toshihiro Shimizu 890ddd
		double scale = tceil(stepSize * scalePart.a11) / stepSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return TScale(scale, scale);
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 doMosaic(TRasterPT<pixel> ras, TRasterPT<pixel> cellsRas, int step, const TPoint &pos,</pixel></pixel>
Toshihiro Shimizu 890ddd
			  TPixel32 bgcolor, mosaic::CellBuilder<pixel> &cellBuilder)</pixel>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Perform the mosaic's flattening operation on each grid cell.
Toshihiro Shimizu 890ddd
	//Cells are identified directly as we traverse the raster.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int lx = ras->getLx(), ly = ras->getLy();
Toshihiro Shimizu 890ddd
	int wrap = ras->getWrap();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int cellLx = cellsRas->getLx(), cellLy = cellsRas->getLy(), cellWrap = cellsRas->getWrap();
Toshihiro Shimizu 890ddd
	int cellX, cellY;
Toshihiro Shimizu 890ddd
	int x0, y0, x1, y1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PIXEL actualBgColor;
Toshihiro Shimizu 890ddd
	pixelConvert(actualBgColor, bgcolor);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	cellsRas->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PIXEL *buffer = ras->pixels(0);
Toshihiro Shimizu 890ddd
	PIXEL *cellsBuf = cellsRas->pixels(0);
Toshihiro Shimizu 890ddd
	for (cellY = 0; cellY < cellLy; ++cellY)
Toshihiro Shimizu 890ddd
		for (cellX = 0; cellX < cellLx; ++cellX) {
Toshihiro Shimizu 890ddd
			//Build the cell geometry
Toshihiro Shimizu 890ddd
			x0 = pos.x + cellX * step, y0 = pos.y + cellY * step;
Toshihiro Shimizu 890ddd
			x1 = x0 + step, y1 = y0 + step;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Retrieve the cell buffer position and its eventual adjustment
Toshihiro Shimizu 890ddd
			int u0 = tmax(x0, 0), v0 = tmax(y0, 0);
Toshihiro Shimizu 890ddd
			int u1 = tmin(x1, lx), v1 = tmin(y1, ly);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			PIXEL *cb = buffer + u0 + v0 * wrap;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			u0 -= x0, v0 -= y0, u1 -= x0, v1 -= y0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Retrieve the cell color
Toshihiro Shimizu 890ddd
			PIXEL *color = cellsBuf + cellX + cellY * cellWrap;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			PIXEL cellBGColor = actualBgColor;
Toshihiro Shimizu 890ddd
			double mFactor = color->m / (double)PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
			cellBGColor.r *= mFactor;
Toshihiro Shimizu 890ddd
			cellBGColor.g *= mFactor;
Toshihiro Shimizu 890ddd
			cellBGColor.b *= mFactor;
Toshihiro Shimizu 890ddd
			cellBGColor.m *= mFactor;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			cellBuilder.doCell(cb, *color, cellBGColor, u0, v0, u1, v1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cellsRas->unlock();
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool MosaicFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Remember: info.m_affine MUST NOT BE CONSIDERED in doGetBBox's implementation
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve the input bbox without applied affines.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!(m_input.getFx() && m_input->doGetBBox(frame, bBox, info)))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Now, the grid has a given step size; the fx result is almost the same,
Toshihiro Shimizu 890ddd
	//except that it must be ceiled to the grid step.
Toshihiro Shimizu 890ddd
	double step = m_size->getValue(frame) + m_distance->getValue(frame);
Toshihiro Shimizu 890ddd
	if (!step)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	bBox = ::gridAlign(bBox, TPointD(), step);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MosaicFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &ri)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double scale = ri.m_affine.a11; //Legitimate due to handledAffine's implementation
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double stepD = (m_size->getValue(frame) + m_distance->getValue(frame)) * scale;
Toshihiro Shimizu 890ddd
	int step = tround(stepD);
Toshihiro Shimizu 890ddd
	if (step <= 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bboxD;
Toshihiro Shimizu 890ddd
	m_input->getBBox(frame, bboxD, ri);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD tileBoxD(::gridAlign(rect * bboxD, TPointD(), stepD));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD srcRectD(
Toshihiro Shimizu 890ddd
		tround(tileBoxD.x0 / stepD), tround(tileBoxD.y0 / stepD),
Toshihiro Shimizu 890ddd
		tround(tileBoxD.x1 / stepD), tround(tileBoxD.y1 / stepD));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int enlargement =
Toshihiro Shimizu 890ddd
		(ri.m_quality == TRenderSettings::StandardResampleQuality) ? 1.0 : (ri.m_quality == TRenderSettings::ImprovedResampleQuality) ? 2.0 : (ri.m_quality == TRenderSettings::HighResampleQuality) ? 3.0 : 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	srcRectD = srcRectD.enlarge(enlargement);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderSettings riLow(ri);
Toshihiro Shimizu 890ddd
	riLow.m_affine = TScale(1.0 / stepD) * ri.m_affine;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_input->dryCompute(srcRectD, frame, riLow);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MosaicFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_input.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//ri's affine is the one that has already been carried due to upstream geom fxs.
Toshihiro Shimizu 890ddd
	//It is handled; so, we can transfer geometrical data directly.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double scale = ri.m_affine.a11; //Legitimate due to handledAffine's implementation
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double stepD = (m_size->getValue(frame) + m_distance->getValue(frame)) * scale;
Toshihiro Shimizu 890ddd
	int step = stepD = tround(stepD);
Toshihiro Shimizu 890ddd
	if (step <= 0) {
Toshihiro Shimizu 890ddd
		//No blur will be done. The underlying fx may pass by.
Toshihiro Shimizu 890ddd
		m_input->compute(tile, frame, ri);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double radius = 0.5 * tcrop(m_size->getValue(frame) * scale, 0.0, stepD);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPixel32 bgcolor = m_bgcolor->getPremultipliedValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build the tile rect.
Toshihiro Shimizu 890ddd
	TDimension tileSize(tile.getRaster()->getSize());
Toshihiro Shimizu 890ddd
	TRectD tileRectD(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Observe that TRasterFx's documentation ensures
Toshihiro Shimizu 890ddd
	//that passed tile's position is always integer, even if it's double-defined.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve the input bbox
Toshihiro Shimizu 890ddd
	TRectD bboxD;
Toshihiro Shimizu 890ddd
	m_input->getBBox(frame, bboxD, ri);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build the grid geometry. We require that the source tile is enlarged to cover
Toshihiro Shimizu 890ddd
	//a full grid step.
Toshihiro Shimizu 890ddd
	TRectD tileBoxD(::gridAlign(tileRectD * bboxD, TPointD(), stepD));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Now, we'll extract cell colors by computing tileBox with a res-reducing affine.
Toshihiro Shimizu 890ddd
	//So, the source tile will be
Toshihiro Shimizu 890ddd
	TRect srcRect(
Toshihiro Shimizu 890ddd
		tround(tileBoxD.x0 / stepD), tround(tileBoxD.y0 / stepD),
Toshihiro Shimizu 890ddd
		tround(tileBoxD.x1 / stepD) - 1, tround(tileBoxD.y1 / stepD) - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//The calculated source rect must be enlarged by a small amount, since the
Toshihiro Shimizu 890ddd
	//resample algrotihms add some transparency to the edges.
Toshihiro Shimizu 890ddd
	int enlargement =
Toshihiro Shimizu 890ddd
		(ri.m_quality == TRenderSettings::StandardResampleQuality) ? 1 : (ri.m_quality == TRenderSettings::ImprovedResampleQuality) ? 2 : (ri.m_quality == TRenderSettings::HighResampleQuality) ? 3 : 0;
Toshihiro Shimizu 890ddd
	assert(enlargement > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	srcRect = srcRect.enlarge(enlargement);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderSettings riLow(ri);
Toshihiro Shimizu 890ddd
	riLow.m_affine = TScale(1.0 / stepD) * ri.m_affine;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Compute the input tile.
Toshihiro Shimizu 890ddd
	TRasterP srcRas(tile.getRaster()->create(srcRect.getLx(), srcRect.getLy()));
Toshihiro Shimizu 890ddd
	TTile inTile(srcRas, TPointD(srcRect.x0, srcRect.y0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_input->compute(inTile, frame, riLow);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Eliminate the enlargement performed above
Toshihiro Shimizu 890ddd
	TRect r(enlargement, enlargement, srcRas->getLx() - 1 - enlargement, srcRas->getLy() - 1 - enlargement);
Toshihiro Shimizu 890ddd
	srcRas = srcRas->extract(r);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Now, discriminate the tile's pixel size
Toshihiro Shimizu 890ddd
	TRaster32P srcRas32(srcRas);
Toshihiro Shimizu 890ddd
	TRaster64P srcRas64(srcRas);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPoint pos(tround(tileBoxD.x0 - tileRectD.x0), tround(tileBoxD.y0 - tileRectD.y0));
Toshihiro Shimizu 890ddd
	if (srcRas32) {
Toshihiro Shimizu 890ddd
		typedef mosaic::CellBuilder<tpixel32> cb;</tpixel32>
Toshihiro Shimizu 890ddd
		cb *cellsBuilder = (m_shape->getValue() == 0) ? (cb *)new mosaic::SquareBuilder<tpixel32, tpixelgr8="">(step, step, radius, tile.getRaster()->getWrap()) : (cb *)new mosaic::CircleBuilder<tpixel32, tpixelgr8="">(step, step, radius, tile.getRaster()->getWrap());</tpixel32,></tpixel32,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		doMosaic<tpixel32>(tile.getRaster(), srcRas32, step, pos, bgcolor, *cellsBuilder);</tpixel32>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete cellsBuilder;
Toshihiro Shimizu 890ddd
	} else if (srcRas64) {
Toshihiro Shimizu 890ddd
		typedef mosaic::CellBuilder<tpixel64> cb;</tpixel64>
Toshihiro Shimizu 890ddd
		cb *cellsBuilder = (m_shape->getValue() == 0) ? (cb *)new mosaic::SquareBuilder<tpixel64, tpixelgr16="">(step, step, radius, tile.getRaster()->getWrap()) : (cb *)new mosaic::CircleBuilder<tpixel64, tpixelgr16="">(step, step, radius, tile.getRaster()->getWrap());</tpixel64,></tpixel64,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		doMosaic<tpixel64>(tile.getRaster(), srcRas64, step, pos, bgcolor, *cellsBuilder);</tpixel64>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete cellsBuilder;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		assert(false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int MosaicFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double scale = info.m_affine.a11;
Toshihiro Shimizu 890ddd
	double stepD = (m_size->getValue(frame) + m_distance->getValue(frame)) * scale;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD srcRect(rect.x0 / stepD, rect.y0 / stepD,
Toshihiro Shimizu 890ddd
				   rect.x1 / stepD, rect.y1 / stepD);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TRasterFx::memorySize(srcRect, info.m_bpp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(MosaicFx, "mosaicFx");