New CompExtractChanel & Composite
Test Mask Chanel RGBA
Test Compositemode (Mask1mode A,Mak2mode A)
Over Under Atop Inside Outside Screen Add Subtract Multiply Divide Diff Min Max Average Xor Alpha !Alpha
Test Compositemode (Mask1mode A,Mak2mode R)
Over Under Atop Inside Outside Screen Add Subtract Multiply Divide Diff Min Max Average Xor Alpha !Alpha
Test only
Test Two Opaque
struct Composite: INode {
virtual void apply() override {
auto compmode = get_input2<std::string>("Compmode");
auto maskmode1 = get_input2<std::string>("Mask1mode");
auto maskmode2 = get_input2<std::string>("Mask2mode");
int w1 = 1024 ;
int h1 = 1024 ;
auto image1 = std::make_shared<PrimitiveObject>();
image1->verts.resize(w1 * h1);
image1->userData().set2("isImage", 1);
image1->userData().set2("w", w1);
image1->userData().set2("h", h1);
auto image2 = std::make_shared<PrimitiveObject>();
image2->verts.resize(w1 * h1);
image2->userData().set2("isImage", 1);
image2->userData().set2("w", w1);
image2->userData().set2("h", h1);
auto A1 = std::make_shared<PrimitiveObject>();
A1->verts.resize(w1 * h1);
A1->userData().set2("isImage", 1);
A1->userData().set2("w", w1);
A1->userData().set2("h", h1);
A1->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
A1->verts.attr<float>("alpha")[i] = 0.0;
}
std::vector<float> &alpha1 = A1->verts.attr<float>("alpha");
auto A2 = std::make_shared<PrimitiveObject>();
A2->verts.resize(w1 * h1);
A2->userData().set2("isImage", 1);
A2->userData().set2("w", w1);
A2->userData().set2("h", h1);
A2->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
A2->verts.attr<float>("alpha")[i] = 0.0;
}
std::vector<float> &alpha2 = A2->verts.attr<float>("alpha");
if(has_input("Background")){
image2 = get_input2<PrimitiveObject>("Background");
auto &ud2 = image2->userData();
w1 = ud2.get2<int>("w");
h1 = ud2.get2<int>("h");
if(image2->verts.has_attr("alpha")){
alpha2 = image2->verts.attr<float>("alpha");
}
else{
image2->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
image2->verts.attr<float>("alpha")[i] = 1.0;
}
alpha2 = image2->verts.attr<float>("alpha");
}
if(!has_input("Foreground")){
image1->verts.resize(image2->size());
image1->userData().set2("w", w1);
image1->userData().set2("h", h1);
image1->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
image1->verts.attr<float>("alpha")[i] = 0.0;
}
alpha1 = image1->verts.attr<float>("alpha");
}
}
if(has_input("Foreground")){
image1 = get_input2<PrimitiveObject>("Foreground");
auto &ud1 = image1->userData();
w1 = ud1.get2<int>("w");
h1 = ud1.get2<int>("h");
if(image1->verts.has_attr("alpha")){
alpha1 = image1->verts.attr<float>("alpha");
}
else{
image1->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
image1->verts.attr<float>("alpha")[i] = 1.0;
}
alpha1 = image1->verts.attr<float>("alpha");
}
if(!has_input("Background")){
image2->verts.resize(image1->size());
image2->userData().set2("w", w1);
image2->userData().set2("h", h1);
image2->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
image2->verts.attr<float>("alpha")[i] = 0.0;
}
alpha2 = image2->verts.attr<float>("alpha");
}
if(has_input("Background")){
auto &ud2 = image2->userData();
int w2 = ud2.get2<int>("w");
int h2 = ud2.get2<int>("h");
if(image1->size() != image2->size() || w1 != w2 || h1 != h2){
image2->verts.resize(image1->size());
image2->userData().set2("w", w1);
image2->userData().set2("h", h1);
//todo: image1和image2大小不同的情况
// for (int i = 0; i < h1; i++) {
// for (int j = 0; j < w1; j++) {
//
// }
// }
}
}
}
if(has_input("Mask1")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
Mask1->verts.resize(w1 * h1);
Mask1->userData().set2("w", w1);
Mask1->userData().set2("h", h1);
if(maskmode1 == "R"){
Mask1->verts.add_attr<float>("alpha");
for(int i = 0;i < Mask1->size();i ++){
Mask1->verts.attr<float>("alpha")[i] = Mask1->verts[i][0];
}
alpha1 = Mask1->verts.attr<float>("alpha");
}
if(maskmode1 == "G"){
Mask1->verts.add_attr<float>("alpha");
for(int i = 0;i < Mask1->size();i ++){
Mask1->verts.attr<float>("alpha")[i] = Mask1->verts[i][1];
}
alpha1 = Mask1->verts.attr<float>("alpha");
}
if(maskmode1 == "B"){
Mask1->verts.add_attr<float>("alpha");
for(int i = 0;i < Mask1->size();i ++){
Mask1->verts.attr<float>("alpha")[i] = Mask1->verts[i][2];
}
alpha1 = Mask1->verts.attr<float>("alpha");
}
if(maskmode1 == "A"){
if(Mask1->verts.has_attr("alpha")){
alpha1 = Mask1->verts.attr<float>("alpha");
}
else{
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] = 1;
}
}
alpha1 = Mask1->verts.attr<float>("alpha");
}
}
}
if(has_input("Mask2")) {
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
Mask2->verts.resize(w1 * h1);
Mask2->userData().set2("w", w1);
Mask2->userData().set2("h", h1);
if(maskmode2 == "R"){
Mask2->verts.add_attr<float>("alpha");
for(int i = 0;i < Mask2->size();i++){
Mask2->verts.attr<float>("alpha")[i] = Mask2->verts[i][0];
}
alpha2 = Mask2->verts.attr<float>("alpha");
}
if(maskmode2 == "G"){
Mask2->verts.add_attr<float>("alpha");
for(int i = 0;i < Mask2->size();i++){
Mask2->verts.attr<float>("alpha")[i] = Mask2->verts[i][1];
}
alpha2 = Mask2->verts.attr<float>("alpha");
}
if(maskmode2 == "B"){
Mask2->verts.add_attr<float>("alpha");
for(int i = 0;i < Mask2->size();i++){
Mask2->verts.attr<float>("alpha")[i] = Mask2->verts[i][2];
}
alpha2 = Mask2->verts.attr<float>("alpha");
}
if(maskmode2 == "A"){
if(Mask2->verts.has_attr("alpha")){
alpha2 = Mask2->verts.attr<float>("alpha");
}
else{
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] = 1;
}
}
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];
vec3f c = rgb1 * l1 + rgb2 * ((l1!=1 && l2!=0)? std::min((1-l1),l2) : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = ((l1!=0 || l2!=0)? zeno::max(l2,l1): 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];
vec3f c = rgb2 * l2 + rgb1 * ((l2!=1 && l1!=0)? std::min((1-l2),l1) : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = ((l1!=0 || l2!=0)? zeno::max(l2,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];
vec3f c = rgb1 * ((l1 != 0 && l2 != 0) ? l1 : 0) + rgb2 * ((l1 == 0) && (l2 != 0) ? l2 : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = (l1 !=0 && l2 !=0)? l1 : l2;
}
}
}
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];
vec3f c = rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = (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];
vec3f c = rgb1 * ((l1 != 0) && (l2 == 0) ? l1 : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = (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 l = zeno::min(zeno::min(image1->verts[i * w1 + j][0],image1->verts[i * w1 + j][1]),image1->verts[i * w1 + j][2]);
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
vec3f c = rgb2 * l2 + rgb2 * ((l1!=0 && l2!=0)? l: 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = l2;
}
}
}
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];
vec3f c = rgb2 * l2 + rgb1 * l1;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb1 * l1 - rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb1 * l1 * rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb1 * l1 / (rgb2 * l2) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = abs(rgb1 * l1 - (rgb2 * l2)) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = l1 <= l2 ? rgb1 * l1 : rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = l1 >= l2 ? rgb1 * l1 : rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb3 * (l1+l2) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = (((l1 != 0) && (l2 != 0)) ? rgb3 : rgb1 * l1 + rgb2 * l2) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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) ? zeno::clamp(l1 + l2, 0, 1) : 0);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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 : zeno::clamp(l1 + l2, 0, 1));
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(1 - (l1 + l2), 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"},
{"enum R G B A", "Mask1mode", "R"},
{"enum R G B A", "Mask2mode", "R"},
},
{
{"image"}
},
{},
{ "comp" },
});
FIXBUG
DEPRECATED
struct CompExtractChanel : INode {
virtual void apply() override {
auto image = get_input<PrimitiveObject>("image");
auto RGB = get_input2<bool>("RGB");
auto R = get_input2<bool>("R");
auto G = get_input2<bool>("G");
auto B = get_input2<bool>("B");
auto A = get_input2<bool>("A");
auto &ud1 = image->userData();
int w = ud1.get2<int>("w");
int h = ud1.get2<int>("h");
auto image2 = std::make_shared<PrimitiveObject>();
image2->userData().set2("isImage", 1);
image2->userData().set2("w", w);
image2->userData().set2("h", h);
image2->verts.resize(image->size());
if(RGB){
for (auto i = 0; i < image->verts.size(); i++) {
float R = image->verts[i][0];
float G = image->verts[i][0];
float B = image->verts[i][0];
image2->verts[i][0] = R;
image2->verts[i][1] = G;
image2->verts[i][2] = B;
}
}
if(R && !RGB) {
for (auto i = 0; i < image->verts.size(); i++) {
float R = image->verts[i][0];
zeno::clamp(image2->verts[i][0] += R,0,1);
zeno::clamp(image2->verts[i][1] += R,0,1);
zeno::clamp(image2->verts[i][2] += R,0,1);
}
}
if(G && !RGB) {
for (auto i = 0; i < image->verts.size(); i++) {
float G = image->verts[i][1];
image2->verts[i][0] += G;
image2->verts[i][1] += G;
image2->verts[i][2] += G;
}
}
if(B && !RGB) {
for (auto i = 0; i < image->verts.size(); i++) {
float B = image->verts[i][2];
image2->verts[i][0] += B;
image2->verts[i][1] += B;
image2->verts[i][2] += B;
}
}
if(A) {
if (image->verts.has_attr("alpha")) {
auto &Alpha = image->verts.attr<float>("alpha");
image2->verts.add_attr<float>("alpha");
image2->verts.attr<float>("alpha")=image->verts.attr<float>("alpha");
}
else{
image2->verts.add_attr<float>("alpha");
for(int i = 0;i < w * h;i++){
image2->verts.attr<float>("alpha")[i] = 1.0;
}
}
}
set_output("image", image2);
}
};
ZENDEFNODE(CompExtractChanel, {
{
{"image"},
{"bool", "RGB", "0"},
{"bool", "R", "0"},
{"bool", "G", "0"},
{"bool", "B", "0"},
{"bool", "A", "0"},
},
{
{"image"}
},
{},
{ "comp" },
});
struct Composite: INode {
virtual void apply() override {
auto compmode = get_input2<std::string>("compmode");
int w1 = 1024 ;
int h1 = 1024 ;
auto image1 = std::make_shared<PrimitiveObject>();
image1->userData().set2("isImage", 1);
image1->userData().set2("w", w1);
image1->userData().set2("h", h1);
auto image2 = std::make_shared<PrimitiveObject>();
image2->userData().set2("isImage", 1);
image2->userData().set2("w", w1);
image2->userData().set2("h", h1);
if(has_input("Background")){
image2 = get_input2<PrimitiveObject>("Background");
auto &ud2 = image2->userData();
w1 = ud2.get2<int>("w");
h1 = ud2.get2<int>("h");
if(!has_input("Foreground")){
image1->verts.resize(image2->size());
image1->userData().set2("w", w1);
image1->userData().set2("h", h1);
image1->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
image1->verts.attr<float>("alpha")[i] = 1.0;
}
}
}
if(has_input("Foreground")){
image1 = get_input2<PrimitiveObject>("Foreground");
auto &ud1 = image1->userData();
w1 = ud1.get2<int>("w");
h1 = ud1.get2<int>("h");
if(!has_input("Background")){
image2->verts.resize(image1->size());
image2->userData().set2("w", w1);
image2->userData().set2("h", h1);
image2->verts.add_attr<float>("alpha");
for(int i = 0;i < w1 * h1;i++){
image2->verts.attr<float>("alpha")[i] = 1.0;
}
}
if(has_input("Background")){
auto &ud2 = image2->userData();
int w2 = ud2.get2<int>("w");
int h2 = ud2.get2<int>("h");
if(w1 != w2 || h1 != h2 || image1->size() != image2->size()){
image2->verts.resize(image1->size());
image2->userData().set2("w", w1);
image2->userData().set2("h", h1);
}
}
}
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 < w1 * h1;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");
}
else{
image1->verts.add_attr<float>("alpha");
}
if(has_input("Mask1")) {
auto Mask1 = get_input2<PrimitiveObject>("Mask1");
if(Mask1->verts.has_attr("alpha")){
alpha1 = Mask1->verts.attr<float>("alpha");
}
else{
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");
}
else{
image2->verts.add_attr<float>("alpha");
}
if(has_input("Mask2")) {
auto Mask2 = get_input2<PrimitiveObject>("Mask2");
if(Mask2->verts.has_attr("alpha")){
alpha2 = Mask2->verts.attr<float>("alpha");
}
else{
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];
vec3f c = rgb1 * l1 + rgb2 * ((l1!=1 && l2!=0)? std::min((1-l1),l2) : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = ((l1!=0 || l2!=0)? zeno::max(l2,l1): 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];
vec3f c = rgb2 * l2 + rgb1 * ((l2!=1 && l1!=0)? std::min((1-l2),l1) : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = ((l1!=0 || l2!=0)? zeno::max(l2,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];
vec3f c = rgb1 * ((l1 != 0 && l2 != 0) ? l1 : 0) + rgb2 * ((l1 == 0) && (l2 != 0) ? l2 : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = (l1 !=0 && l2 !=0)? l1 : l2;
}
}
}
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];
vec3f c = rgb1 * ((l1 != 0) && (l2 != 0) ? l1 : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = (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];
vec3f c = rgb1 * ((l1 != 0) && (l2 == 0) ? l1 : 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = (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 l = zeno::min(zeno::min(image1->verts[i * w1 + j][0],image1->verts[i * w1 + j][1]),image1->verts[i * w1 + j][2]);
float l1 = alpha1[i * w1 + j];
float l2 = alpha2[i * w1 + j];
vec3f c = rgb2 * l2 + rgb2 * ((l1!=0 && l2!=0)? l: 0);
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = l2;
}
}
}
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];
vec3f c = rgb2 * l2 + rgb1 * l1;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb1 * l1 - rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb1 * l1 * rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb1 * l1 / (rgb2 * l2) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = abs(rgb1 * l1 - (rgb2 * l2)) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = l1 <= l2 ? rgb1 * l1 : rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = l1 >= l2 ? rgb1 * l1 : rgb2 * l2 ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = rgb3 * (l1+l2) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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];
vec3f c = (((l1 != 0) && (l2 != 0)) ? rgb3 : rgb1 * l1 + rgb2 * l2) ;
image1->verts[i * w1 + j] = zeno::clamp(c, 0, 1);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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) ? zeno::clamp(l1 + l2, 0, 1) : 0);
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(l1 + l2, 0, 1);
}
}
}
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 : zeno::clamp(l1 + l2, 0, 1));
image1->verts.attr<float>("alpha")[i * w1 + j] = zeno::clamp(1 - (l1 + l2), 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" },
});