Composite
Input:
Output:
over
under
atop
inside
outside
screen
add
Subtract
Multiply
Divide
Diff
Min
Max
Average
Xor
Alpha
!Alpha
Input
Output
Over
Under
Atop
Inside
Outside
Screen
Add
Subtract
Multiply
Divide
Diff
Min
Max
Average
Xor
Alpha
!Alpha
Input
Output
Over
Under
Atop
Inside
Outside
Screen
Add
Subtract
Multiply
Divide
Diff
Min
Max
Average
Xor
Alpha
!Alpha
Input
Output
Over
Under
Atop
Inside
Outside
Screen
Add
Subtract
Multiply
Divide
Diff
Min
Max
Average
Xor
Alpha
!Alpha
struct Composite: INode {
virtual void apply() override {
auto image1 = get_input2<PrimitiveObject>("Foreground");
auto image2 = get_input2<PrimitiveObject>("Background");
auto compmode = get_input2<std::string>("compmode");
auto &ud1 = image1->userData();
int w1 = ud1.get2<int>("w");
int h1 = ud1.get2<int>("h");
auto &ud2 = image2->userData();
int w2 = ud2.get2<int>("w");
int h2 = ud2.get2<int>("h");
auto A1 = std::make_shared<PrimitiveObject>();
A1->verts.resize(image1->size());
A1->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
A1->verts.attr<float>("alpha")[i] = 1.0;
}
auto A2 = std::make_shared<PrimitiveObject>();
A2->verts.resize(image2->size());
A2->verts.add_attr<float>("alpha");
for(int i = 0;i < w2 * h2;i++){
A2->verts.attr<float>("alpha")[i] = 1.0;
}
std::vector<float> &alpha1 = A1->verts.attr<float>("alpha");
if(image1->verts.has_attr("alpha")){
alpha1 = image1->verts.attr<float>("alpha");
}
if(has_input("Mask1")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
Mask1->verts.add_attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
Mask1->verts.attr<float>("alpha")[i * w1 + j] = Mask1->verts[i * w1 + j][0];
}
}
alpha1 = Mask1->verts.attr<float>("alpha");
}
std::vector<float> &alpha2 = A2->verts.attr<float>("alpha");
if(image2->verts.has_attr("alpha")){
alpha2 = image2->verts.attr<float>("alpha");
}
if(has_input("Mask2")) {
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
Mask2->verts.add_attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
Mask2->verts.attr<float>("alpha")[i * w1 + j] = Mask2->verts[i * w1 + j][0];
}
}
alpha2 = Mask2->verts.attr<float>("alpha");
}
if (compmode == "Over") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 + rgb2 * (l2 - ((l1 != 0) && (l2 != 0) ? l2 : 0));
}
}
}
if (compmode == "Under") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb2 * l2 + rgb1 * (l1 - ((l1 != 0) && (l2 != 0) ? l1 : 0));
}
}
}
if (compmode == "Atop") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] =
rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0) + rgb2 * ((l1 == 0) && (l2 != 0) ? l2 : 0);
}
}
}
if (compmode == "Inside") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0);
}
}
}
if (compmode == "Outside") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 == 0) ? l1 : 0);
}
}
}
if(compmode == "Screen"){
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float var = (image1->verts[i * w1 + j][0]+image1->verts[i * w1 + j][1]+image1->verts[i * w1 + j][2])/3;
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb2 * l2 + rgb2 *((l1!=0 && l2!=0)? var: 0);
}
}
}
if (compmode == "Add") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 + rgb2 * l2;
}
}
}
if (compmode == "Subtract") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 - rgb2 * l2;
}
}
}
if (compmode == "Multiply") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 * rgb2 * l2;
}
}
}
if (compmode == "Divide") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 / (rgb2 * l2);
}
}
}
if (compmode == "Diff") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = abs(rgb1 * l1 - (rgb2 * l2));
}
}
}
if (compmode == "Min") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = l1 <= l2 ? rgb1 * l1 : rgb2 * l2;
}
}
}
if (compmode == "Max") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = l1 >= l2 ? rgb1 * l1 : rgb2 * l2;
}
}
}
if (compmode == "Average") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = (rgb1+rgb2)/2;
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb3 * (l1+l2);
}
}
}
if (compmode == "Xor") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {0, 0, 0};
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = (((l1 != 0) && (l2 != 0)) ? rgb3 : rgb1 * l1 + rgb2 * l2);
}
}
}
if (compmode == "Alpha") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {1,1,1};
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb3 * ((l1 != 0) || (l2 != 0) ? 1 : 0);
}
}
}
if (compmode == "!Alpha") {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {1,1,1};
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb3 * ((l1 != 0) || (l2 != 0) ? 0 : 1);
}
}
}
set_output("image", image1);
}
};
ZENDEFNODE(Composite, {
{
{"Foreground"},
{"Background"},
{"Mask1"},
{"Mask2"},
{"enum Over Under Atop Inside Outside Screen Add Subtract Multiply Divide Diff Min Max Average Xor Alpha !Alpha", "compmode", "Over"},
},
{
{"image"}
},
{},
{ "comp" },
});
Composite(replaced)
Input:
Output:
struct Composite: INode {
virtual void apply() override {
auto image1 = get_input2<PrimitiveObject>("Foreground");
auto image2 = get_input2<PrimitiveObject>("Background");
auto compmode = get_input2<std::string>("compmode");
auto &ud1 = image1->userData();
int w1 = ud1.get2<int>("w");
int h1 = ud1.get2<int>("h");
if (compmode == "Over") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * l1 + rgb2 * (l2 - ((l1 != 0) && (l2 != 0) ? l2 : 0));
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 + rgb2 * (l2 - ((l1 != 0) && (l2 != 0) ? l2 : 0));
}
}
}
else {
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1;
}
}
}
}
}
if (compmode == "Under") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb2 * l2 + rgb1 * (l1 - ((l1 != 0) && (l2 != 0) ? l1 : 0));
}
}
}
else{
if (image2->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb2 * l2 + rgb1 * (l1 - ((l1 != 0) && (l2 != 0) ? l1 : 0));
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb2;
}
}
}
}
}
if (compmode == "Atop") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] =
rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0) + rgb2 * ((l1 == 0) && (l2 != 0) ? l2 : 0);
}
}
}
else{
if (image2->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0) + rgb2 * ((l1 == 0) && (l2 != 0) ? l2 : 0);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1;
}
}
}
}
}
if (compmode == "Inside") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1;
}
}
}
}
}
if (compmode == "Outside") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 == 0) ? l1 : 0);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * ((l1 != 0) && (l2 == 0) ? l1 : 0);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb3 = {0, 0, 0};
image1->verts[i * w1 + j] = rgb3;
}
}
}
}
}
if(compmode == "Screen"){
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float var = (image1->verts[i * w1 + j][0] + image1->verts[i * w1 + j][1] +
image1->verts[i * w1 + j][2]) / 3;
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb2 * l2 + rgb2 * ((l1 != 0 && l2 != 0) ? var : 0);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float var = (image1->verts[i * w1 + j][0]+image1->verts[i * w1 + j][1]+image1->verts[i * w1 + j][2])/3;
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb2 * l2 + rgb2 *((l1!=0 && l2!=0)? var: 0);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float var = (image1->verts[i * w1 + j][0]+image1->verts[i * w1 + j][1]+image1->verts[i * w1 + j][2])/3;
image1->verts[i * w1 + j] = rgb2 + rgb2 * var;
}
}
}
}
}
if (compmode == "Add") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * l1 + rgb2 * l2;
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 + rgb2 * l2;
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * 0.5 + rgb2 * 0.5;
}
}
}
}
}
if (compmode == "Subtract") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * l1 - rgb2 * l2;
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 - rgb2 * l2;
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 - rgb2;
}
}
}
}
}
if (compmode == "Multiply") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * l1 * rgb2 * l2;
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 * rgb2 * l2;
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * rgb2;
}
}
}
}
}
if (compmode == "Divide") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb1 * l1 / (rgb2 * l2);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb1 * l1 / (rgb2 * l2);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = rgb1/rgb2;
}
}
}
}
}
if (compmode == "Diff") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = abs(rgb1 * l1 - (rgb2 * l2));
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = abs(rgb1*l1 - rgb2 * l2);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
image1->verts[i * w1 + j] = abs(rgb1- rgb2);
}
}
}
}
}
if (compmode == "Min") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = l1 <= l2 ? rgb1 * l1 : rgb2 * l2;
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = l1 <= l2 ? rgb1 * l1 : rgb2 * l2;
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float add1 = image1->verts[i * w1 + j][0]+image1->verts[i * w1 + j][1]+image1->verts[i * w1 + j][2];
float add2 = image2->verts[i * w1 + j][0]+image2->verts[i * w1 + j][1]+image2->verts[i * w1 + j][2];
image1->verts[i * w1 + j] = add1 <= add2 ? rgb1 : rgb2;
}
}
}
}
}
if (compmode == "Max") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = l1 >= l2 ? rgb1 * l1 : rgb2 * l2;
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = l1 >= l2 ? rgb1 * l1 : rgb2 * l2;
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
float add1 = image1->verts[i * w1 + j][0]+image1->verts[i * w1 + j][1]+image1->verts[i * w1 + j][2];
float add2 = image2->verts[i * w1 + j][0]+image2->verts[i * w1 + j][1]+image2->verts[i * w1 + j][2];
image1->verts[i * w1 + j] = add1 >= add2 ? rgb1 : rgb2;
}
}
}
}
}
if (compmode == "Average") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = (rgb1 + rgb2) / 2;
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb3 * (l1 + l2);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = (rgb1+rgb2)/2;
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb3 * (l1+l2);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = (rgb1+rgb2)/2;
image1->verts[i * w1 + j] = rgb3;
}
}
}
}
}
if (compmode == "Xor") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {0, 0, 0};
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = (((l1 != 0) && (l2 != 0)) ? rgb3 : rgb1 * l1 + rgb2 * l2);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {0, 0, 0};
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = (((l1 != 0) && (l2 != 0)) ? rgb3 : rgb1 * l1 + rgb2 * l2);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb3 = {0, 0, 0};
image1->verts[i * w1 + j] = rgb3;
}
}
}
}
}
if (compmode == "Alpha") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {1, 1, 1};
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb3 * ((l1 != 0) || (l2 != 0) ? 1 : 0);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {1,1,1};
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb3 * ((l1 != 0) || (l2 != 0) ? 1 : 0);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb3 = {0, 0, 0};
image1->verts[i * w1 + j] = rgb3;
}
}
}
}
}
if (compmode == "!Alpha") {
if(has_input("Mask1")&& has_input("Mask2")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {1, 1, 1};
float l1 = Mask1->verts[i * w1 + j][0];
float l2 = Mask2->verts[i * w1 + j][0];
image1->verts[i * w1 + j] = rgb3 * ((l1 != 0) || (l2 != 0) ? 0 : 1);
}
}
}
else{
if (image1->verts.has_attr("alpha")) {
auto &alpha1 = image1->verts.attr<float>("alpha");
auto &alpha2 = image2->verts.attr<float>("alpha");
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb1 = image1->verts[i * w1 + j];
vec3f rgb2 = image2->verts[i * w1 + j];
vec3f rgb3 = {1,1,1};
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
image1->verts[i * w1 + j] = rgb3 * ((l1 != 0) || (l2 != 0) ? 0 : 1);
}
}
}
else{
for (int i = 0; i < h1; i++) {
for (int j = 0; j < w1; j++) {
vec3f rgb3 = {1, 1, 1};
image1->verts[i * w1 + j] = rgb3;
}
}
}
}
}
set_output("image", image1);
}
};
ZENDEFNODE(Composite, {
{
{"Foreground"},
{"Background"},
{"Mask1"},
{"Mask2"},
{"enum Over Under Atop Inside Outside Screen Add Subtract Multiply Divide Diff Min Max Average Xor Alpha !Alpha", "compmode", "Over"},
},
{
{"image"}
},
{},
{ "comp" },
});