How to extend the ImageMath plugin.
How to extend the ImageMath plugin.
You can define binary and unary operators locally. We support a functor as well as a lambda function style.
In this case you want to add the operators (see above for examples) to the files BinaryOps.h or UnaryOps.h. Afterwards add the operators to the ExprBaseTpl by adding the operator using either the ADD_UNARY_OP or the ADD_BINARY_OP macro.
template <typename OperandT>
class ConvertToGray : public ExprBaseTpl<ConvertToGray<OperandT>>, public GlExprInterface , public ExprInterface
{
public:
using expr_type = typename OperandT::expr_type;
static constexpr bool has_variable = OperandT::has_variable;
using imf_img_type = typename OperandT::imf_img_type;
ConvertToGray(const OperandT& operand)
: m_operand(operand)
, m_channelIndices(indices)
, m_outDesc(m_operand.imgDesc())
, m_opDesc(m_operand.imgDesc())
{
m_outDesc.channels = 1;
}
OperandT& operand() { return m_operand; }
template <typename ImgT>
auto convertToMemImgExpr() const
{
return ConvertToGray<decltype(m_operand.template convertToMemImgExpr<ImgT>())>(m_operand.template convertToMemImgExpr<ImgT>());
}
auto convertToSharedImgExpr(std::size_t index) const
{
return ConvertToGray<decltype(m_operand.convertToSharedImgExpr(index))>(m_operand.convertToSharedImgExpr(index));
}
template <typename SubOperandT>
auto substituteVariable(const SubOperandT& operand) const
{
static_assert(has_variable);
return ConvertToGray<decltype(m_operand.substituteVariable(operand))>(m_operand.substituteVariable(operand));
}
const ImageDescriptor& imgDesc() const override { return m_outDesc; }
int numImgs() const override { return m_operand.numImgs(); }
IMFUSION_STRONG_INLINE expr_type eval(const std::size_t i, const vec4i& coord) const
{
const auto slicedI = m_opDesc.index(coord[0], coord[1], coord[2], coord[3]);
const auto numChannels = m_opDesc.channels;
expt_type outVal = 0.0;
for(int i = 0; i < numChannels; ++i)
outVal += m_operand.eval(slicedI + i, slicedCoord);
return outVal;
}
std::string evalString(bool tagAndAssign = true) const
{
if (tagAndAssign)
internal::tagAndAssignNamesHelper(*this);
const auto opStr = m_operand.evalString(false);
std::stringstream ss;
ss << "vec4(";
const auto numChannels = m_opDesc.channels;
for(int i = 0; i < numChannels; ++i)
{
ss << "(" << m_operand.evalString(false) << ").";
switch(i)
{
case 1: ss << "r"; break;
case 2: ss << "g"; break;
case 3: ss << "b"; break;
case 4: ss << "a"; break;
}
if(i < numChannels - 1)
ss << " + ";
}
ss << ")";
}
void tagAndAssignNames(std::unordered_map<internal::TaggingIndex, const void*>& taggedLeaves,
std::unordered_map<std::type_index, int>& countPerLeafType,
const std::string& prefix) const
{
m_operand.tagAndAssignNames(taggedLeaves, countPerLeafType, prefix);
}
void getUniformDefinitionList(std::string& definitionList, const std::string& prefix) const
{
m_operand.getUniformDefinitionList(definitionList, prefix);
}
void getVariableDefinitionList(std::string& definitionList, const std::string& prefix) const
{
m_operand.getVariableDefinitionList(definitionList, prefix);
}
int setArguments(GlProgram& p, const std::string& prefix) const { return m_operand.setArguments(p, prefix); }
{
return m_operand.deviceStrategy();
}
private:
OperandT m_operand;
ImageDescriptor m_outDesc;
const ImageDescriptor m_opDesc;
};
#define IMFUSION_ASSERT(...)
ImFusion assertion macro, supports two overloads:
Definition Assert.h:102
DeviceStrategy
Computing device strategy.
Definition Types.h:18