Merge

The Merge kernel combines two input images, srcA and srcB, using various blending modes controlled by the mode parameter. This allows for different compositing operations between the images.

Note

The max, min, and clamp functions for integer types are not supported by the BlinkScript effect in Nuke’s timeline if all the images have eAccessPoint data access. As a result, ternary operators are used in place of these functions to ensure compatibility and correct functionality.

#define kBlendPlus            1
#define kBlendDifference      2
#define kBlendDivide          3
#define kBlendMask            4
#define kBlendMax             5
#define kBlendMin             6
#define kBlendMinus           7
#define kBlendMultiply        8
#define kBlendOver            9
#define kBlendOverlay         10
#define kBlendAverage         11

kernel Merge : ImageComputationKernel<eComponentWise>
{
  Image<eRead> srcB;
  Image<eRead> srcA;
  Image<eWrite> dst;

  param:
    int mode; // Set to a value between 1 - 11. See constants above.

  void define() {
    defineParam(mode, "mode", kBlendMask);
  }

  void process(int comp) {

    // Check if the component index is valid for both srcA and srcB
    const bool validA = comp < srcA.kComps;
    const bool validB = comp < srcB.kComps;

    ValueType(dst) dstValue = 0.0f;
    ValueType(srcA) a = validA ? srcA() : 0.0f;
    ValueType(srcB) b = validB ? srcB() : 0.0f;

    // Perform blending based on the mode
    if (mode == kBlendPlus) {
      dstValue = a + b;
    } 
    else if (mode == kBlendDifference) {
      dstValue = fabs(a - b);
    } 
    else if (mode == kBlendDivide) {
      ValueType(srcB) eps = 0.000001f; 
      ValueType(srcB) denominator = (b > eps) ? b : eps;
      dstValue = a / denominator;
    } 
    else if (mode == kBlendMask) {
      ValueType(srcA) srca = clamp(a, 0.0f, 1.0f); 
      dstValue = b * srca;
    } 
    else if (mode == kBlendMax) {
      dstValue = (a > b) ? a : b;
    } 
    else if (mode == kBlendMin) {
      dstValue = (a < b) ? a : b;
    } 
    else if (mode == kBlendMinus) {
      dstValue = a - b;
    } 
    else if (mode == kBlendMultiply) {
      dstValue = a * b;
    } 
    else if (mode == kBlendOver) {
      // Assuming 'a' is the alpha component if present
      dstValue = a + b * (1.0f - a);
    } 
    else if (mode == kBlendOverlay) {
      dstValue = (a < 0.5f) ? (2.0f * a * b) : (1.0f - 2.0f * (1.0f - a) * (1.0f - b));
      dstValue = clamp(dstValue, 0.0f, 1.0f);
    } 
    else if (mode == kBlendAverage) {
      dstValue = (a + b) * 0.5f;
    } 
    else {
      // Set destination to zero for invalid modes
      dstValue = 0.0f;
    }

    dst() = dstValue;
  }
};