diff --git a/projects/ImgCV/ImageComposite.cpp b/projects/ImgCV/ImageComposite.cpp index 594c847b58..1ca26589ba 100644 --- a/projects/ImgCV/ImageComposite.cpp +++ b/projects/ImgCV/ImageComposite.cpp @@ -568,257 +568,185 @@ ZENDEFNODE(Composite, { {"image"} }, {}, - { "comp" }, + { "deprecated" }, }); -struct Blend: INode { - virtual void apply() override { - auto blend = get_input("Foreground"); - auto base = get_input("Background"); - auto maskopacity = get_input2("Mask Opacity"); - auto compmode = get_input2("Blending Mode"); - auto opacity1 = get_input2("Foreground Opacity"); - auto opacity2 = get_input2("Background Opacity"); - - auto &ud1 = blend->userData(); - int w1 = ud1.get2("w"); - int h1 = ud1.get2("h"); - auto mask = std::make_shared(); - if(has_input("Mask")) { - mask = get_input("Mask"); +template +static T BlendMode(const float &alpha1, const float &alpha2, const T& rgb1, const T& rgb2, const vec3f opacity, std::string compmode) +{ + if(compmode == std::string("Copy")) {//copy and over is different!!! + T value = rgb1 * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - else { - mask->verts.resize(w1*h1); - mask->userData().set2("isImage", 1); - mask->userData().set2("w", w1); - mask->userData().set2("h", h1); - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - mask->verts[i * w1 + j] = {maskopacity,maskopacity,maskopacity}; - } - } + else if(compmode == std::string("Over")) { + T value = (rgb1 + rgb2 * (1 - alpha1)) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - -//就地修改比较快! - -//todo: image1和image2大小不同的情况 - - if(compmode == "Normal") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = rgb1 * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + else if(compmode == std::string("Under")) { + T value = (rgb2 + rgb1 * (1 - alpha2)) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - - else if(compmode == "Add") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = zeno::min(rgb1 + rgb2, vec3f(1.0f))*opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } - } - - else if(compmode == "Subtract") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = zeno::max(rgb2 - rgb1, vec3f(0.0f))*opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + else if(compmode == std::string("Atop")) { + T value = (rgb1 * alpha2 + rgb2 * (1 - alpha1)) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - - else if(compmode == "Multiply") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = rgb1 * rgb2 * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + else if(compmode == std::string("In")) { + T value = rgb1 * alpha2 * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - - else if(compmode == "Max(Lighten)") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = zeno::max(rgb1, rgb2) * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + else if(compmode == std::string("Out")) { + T value = (rgb1 * (1 - alpha2)) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - - else if(compmode == "Min(Darken)") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = zeno::min(rgb1, rgb2) * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + else if(compmode == std::string("Xor")) { + T value = (rgb1 * (1 - alpha2) + rgb2 * (1 - alpha1)) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } -/* - else if(compmode == "AddSub") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f &rgb1 = blend->verts[i * w1 + j] * opacity1; - rgb1 = pow(rgb1, 1.0/2.2); - vec3f &rgb2 = base->verts[i * w1 + j] * opacity2; - rgb2 = pow(rgb2, 1.0/2.2); - vec3f &opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c; + else if(compmode == std::string("Add")) { + T value = zeno::min(rgb1 + rgb2, T(1.0f))*opacity[0] + rgb2 * (1 - opacity[0]);//clamp? + return value; + } + else if(compmode == std::string("Subtract")) { + T value = zeno::max(rgb2 - rgb1, T(0.0f))*opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + else if(compmode == std::string("Multiply")) { + T value = rgb1 * rgb2 * opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + else if(compmode == std::string("Max(Lighten)")) { + T value = zeno::max(rgb1, rgb2) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + else if(compmode == std::string("Min(Darken)")) { + T value = zeno::min(rgb1, rgb2) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + else if(compmode == std::string("Screen")) {//A+B-AB if A and B between 0-1, else A if A>B else B + T value = (1 - (1 - rgb2) * (1 - rgb1)) * opacity[0] + rgb2 * (1 - opacity[0]);//only care 0-1! + return value; + } + else if(compmode == std::string("Difference")) { + T value = zeno::abs(rgb1 - rgb2) * opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + else if(compmode == std::string("Average")) { + T value = (rgb1 + rgb2) / 2 * opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + return T(0); +} + +static zeno::vec3f BlendModeV(const float &alpha1, const float &alpha2, const vec3f& rgb1, const vec3f& rgb2, const vec3f opacity, std::string compmode) +{ + if(compmode == std::string("Overlay")) { + vec3f value; for (int k = 0; k < 3; k++) { - if (rgb1[k] > 0.5) { - c[k] = rgb1[k] + rgb2[k]; + if (rgb2[k] < 0.5) { + value[k] = 2 * rgb1[k] * rgb2[k]; } else { - c[k] = rgb2[k] - rgb1[k]; + value[k] = 1 - 2 * (1 - rgb1[k]) * (1 - rgb2[k]);//screen } } - c = pow(c, 2.2) * opacity + pow(rgb2, 2.2) * (1 - opacity); - //c = c * opacity + rgb2 * (1 - opacity); - //c = pow(c, 2.2); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } - -*/ - else if(compmode == "Overlay") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - //rgb1 = pow(rgb1, 1.0/2.2); - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - //rgb2 = pow(rgb2, 1.0/2.2); - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c; + value = value * opacity[0] + rgb2 * (1 - opacity[0]); + return value; + } + else if(compmode == std::string("SoftLight")) { + vec3f value; for (int k = 0; k < 3; k++) { - if ( rgb2[k] < 0.5) { - c[k] = 2 * rgb1[k] * rgb2[k]; + if (rgb1[k] < 0.5) { + value[k] = 2 * rgb1[k] * rgb2[k] + rgb2[k] * rgb2[k] * (1 - 2 * rgb1[k]); } else { - c[k] = 1 - 2 * (1 - rgb1[k]) * (1 - rgb2[k]); + value[k] = 2 * rgb2[k] * (1 - rgb1[k]) + sqrt(rgb2[k]) * (2 * rgb1[k] - 1); } } - c = c * opacity + rgb2 * (1 - opacity); - //c = pow(c, 2.2); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } - } - - else if(compmode == "Screen") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = (1 - (1 - rgb2) * (1 - rgb1)) * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + value = value * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } - - else if(compmode == "SoftLight") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - //rgb1 = pow(rgb1, 1.0/2.2); - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - //rgb2 = pow(rgb2, 1.0/2.2); - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c; + else if(compmode == std::string("Divide")) { + vec3f value; for (int k = 0; k < 3; k++) { - if (rgb1[k] < 0.5) { - c[k] = 2 * rgb1[k] * rgb2[k] + rgb2[k] * rgb2[k] * (1 - 2 * rgb1[k]); + if (rgb1[k] == 0) { + value[k] = 1; } else { - c[k] = 2 * rgb2[k] * (1 - rgb1[k]) + sqrt(rgb2[k]) * (2 * rgb1[k] - 1); + value[k] = rgb2[k] / rgb1[k]; } } - c = c * opacity + rgb2 * (1 - opacity); - //c = pow(c, 2.2); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } - } + value = value * opacity[0] + rgb2 * (1 - opacity[0]); + return value; } + return zeno::vec3f(0); +} - else if(compmode == "Difference") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = zeno::abs(rgb1 - rgb2) * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); - } +struct Blend: INode { + virtual void apply() override {//todo:: add blend scope RGBA and Premultiplied / Alpha Blending(https://github.com/jamieowen/glsl-blend/issues/6) + auto blend = get_input("Foreground"); + auto base = get_input("Background"); + auto maskopacity = get_input2("Mask Opacity"); + + auto compmode = get_input2("Blending Mode"); + //auto alphablend = get_input2("Alpha Blending"); + auto alphamode = get_input2("Alpha Mode"); + auto opacity1 = get_input2("Foreground Opacity"); + auto opacity2 = get_input2("Background Opacity"); + + auto &ud1 = blend->userData(); + int w1 = ud1.get2("w"); + int h1 = ud1.get2("h"); + int imagesize = w1 * h1; + auto mask = std::make_shared(); + if(has_input("Mask")) { + mask = get_input("Mask"); + + } + else { + mask->verts.resize(w1*h1); + mask->userData().set2("isImage", 1); + mask->userData().set2("w", w1); + mask->userData().set2("h", h1); + for (int i = 0; i < imagesize; i++) { + mask->verts[i] = {maskopacity,maskopacity,maskopacity}; } } - - else if(compmode == "Divide") { -#pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c; - for (int k = 0; k < 3; k++) { - if (rgb1[k] == 0) { - c[k] = 1; - } else { + auto image2 = std::make_shared(); + image2->userData().set2("isImage", 1); + image2->userData().set2("w", w1); + image2->userData().set2("h", h1); + image2->verts.resize(imagesize); + bool alphaoutput = blend->has_attr("alpha")||base->has_attr("alpha"); + auto &image2alpha = image2->add_attr("alpha"); + auto &blendalpha = blend->has_attr("alpha")?blend->attr("alpha"):std::vector(imagesize, 1.0f); + auto &basealpha = base->has_attr("alpha")?base->attr("alpha"):std::vector(imagesize, 1.0f); - c[k] = rgb2[k] / rgb1[k]; - } - } - c = c * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); +//todo: rgb1和rgb2大小不同的情况 +#pragma omp parallel for + for (int i = 0; i < imagesize; i++) { + vec3f rgb1 = zeno::clamp(blend->verts[i], 0, 1) * opacity1; + vec3f rgb2 = zeno::clamp(base->verts[i], 0, 1) * opacity2; + vec3f opacity = zeno::clamp(mask->verts[i], 0, 1) * maskopacity; + if(compmode == "Overlay"||compmode == "Softlight"||compmode == "Divide"){ + vec3f c = BlendModeV(blendalpha[i], basealpha[i], rgb1, rgb2, opacity, compmode); + image2->verts[i] = zeno::clamp(c, 0, 1); + } + else{ + vec3f c = BlendMode(blendalpha[i], basealpha[i], rgb1, rgb2, opacity, compmode); + image2->verts[i] = zeno::clamp(c, 0, 1); } } - } - - else if(compmode == "Average") { + if(alphaoutput) {//如果两个输入 其中一个没有alpha 对于rgb和alpha alpha的默认值不一样 前者为1 后者为0? + auto &blendalpha = blend->has_attr("alpha")?blend->attr("alpha"):blend->add_attr("alpha");//只有blendbase都没有alpha 结果才没有 + auto &basealpha = base->has_attr("alpha")?base->attr("alpha"):base->add_attr("alpha"); #pragma omp parallel for - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb1 = blend->verts[i * w1 + j] * opacity1; - vec3f rgb2 = base->verts[i * w1 + j] * opacity2; - vec3f opacity = mask->verts[i * w1 + j] * maskopacity; - vec3f c = (rgb1 + rgb2) / 2 * opacity + rgb2 * (1 - opacity); - blend->verts[i * w1 + j] = zeno::clamp(c, 0, 1); + for (int i = 0; i < imagesize; i++) { + vec3f opacity = zeno::clamp(mask->verts[i], 0, 1) * maskopacity; + float alpha = BlendMode(blendalpha[i], basealpha[i], blendalpha[i], basealpha[i], opacity, alphamode); + image2alpha[i] = zeno::clamp(alpha, 0, 1); } } - } - - set_output("image", blend); + set_output("image", image2); } }; @@ -827,7 +755,9 @@ ZENDEFNODE(Blend, { {"Foreground"}, {"Background"}, {"Mask"}, - {"enum Normal Add Subtract Multiply Max(Lighten) Min(Darken) Overlay Screen SoftLight Difference Divide Average", "Blending Mode", "Normal"}, + {"enum Over Copy Under Atop In Out Screen Add Subtract Multiply Max(Lighten) Min(Darken) Average Difference Overlay SoftLight Divide Xor", "Blending Mode", "Normal"}, + //{"enum IgnoreAlpha SourceAlpha", "Alpha Blending", "Ignore Alpha"}, SUBSTANCE DESIGNER ALPHA MODE + {"enum Over Under Atop In Out Screen Add Subtract Multiply Max(Lighten) Min(Darken) Average Difference Xor", "Alpha Mode", "Over"}, {"float", "Mask Opacity", "1"}, {"float", "Foreground Opacity", "1"}, {"float", "Background Opacity", "1"}, @@ -839,89 +769,6 @@ ZENDEFNODE(Blend, { { "comp" }, }); - -/* -struct CompositeCV: INode { - virtual void apply() override { - auto image1 = get_input("Foreground"); - auto image2 = get_input("Background"); - auto mode = get_input2("mode"); - auto Alpha1 = get_input2("Alpha1"); - auto Alpha2 = get_input2("Alpha2"); - auto &a1 = image1->verts.attr("alpha"); - auto &a2 = image2->verts.attr("alpha"); - - auto &ud1 = image1->userData(); - int w1 = ud1.get2("w"); - int h1 = ud1.get2("h"); - auto &ud2 = image2->userData(); - int w2 = ud2.get2("w"); - int h2 = ud2.get2("h"); - - cv::Mat imagecvin1(h1, w1, CV_32FC3); - cv::Mat imagecvin2(h2, w2, CV_32FC3); - cv::Mat imagecvadd(h1, w1, CV_32FC3); - cv::Mat imagecvsub(h1, w1, CV_32FC3); - cv::Mat imagecvout(h1, w1, CV_32FC3); - - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - vec3f rgb = image1->verts[i * w1 + j]; - imagecvin1.at(i, j) = {rgb[0], rgb[1], rgb[2]}; - } - } - for (int i = 0; i < h2; i++) { - for (int j = 0; j < w2; j++) { - vec3f rgb = image2->verts[i * w2 + j]; - imagecvin2.at(i, j) = {rgb[0], rgb[1], rgb[2]}; - } - } - cv::resize(imagecvin2, imagecvin2,imagecvin1.size()); - if(mode == "Add"){ - cv::addWeighted(imagecvin1, Alpha1, imagecvin2, Alpha2, 0, imagecvout); - } - if(mode == "Subtract"){ - cv::subtract(imagecvin1*Alpha1, imagecvin2*Alpha2, imagecvout); - } - if(mode == "Multiply"){ - cv::multiply(imagecvin1*Alpha1, imagecvin2*Alpha2, imagecvout); - } - if(mode == "Divide"){ - cv::divide(imagecvin1*Alpha1, imagecvin2*Alpha2, imagecvout, 1, -1); - } - if(mode == "Diff"){ - cv::absdiff(imagecvin1*Alpha1, imagecvin2*Alpha2, imagecvout); - } - - for (int i = 0; i < h1; i++) { - for (int j = 0; j < w1; j++) { - cv::Vec3f rgb = imagecvout.at(i, j); - image1->verts[i * w1 + j] = {rgb[0], rgb[1], rgb[2]}; - } - } - set_output("image", image1); - } -}; - -ZENDEFNODE(CompositeCV, { - { - {"Foreground"}, - {"Background"}, - {"enum Add(Linear Dodge) Subtract Multiply Add Sub Diff", "mode", "Add"}, - {"float", "Alpha1", "1"}, - {"float", "Alpha2", "1"}, - }, - { - {"image"} - }, - {}, - { "comp" }, -}); - -*/ - - - // 自定义卷积核 std::vector> createKernel(float blurValue, float l_blurValue, float r_blurValue, @@ -1010,7 +857,7 @@ ZENDEFNODE(CompBlur, { { "comp" }, }); -struct CompExtractChanel_gray: INode { +/*struct CompExtractChanel_gray: INode { virtual void apply() override { auto image = get_input("image"); auto RGB = get_input2("RGB"); @@ -1087,9 +934,9 @@ ZENDEFNODE(CompExtractChanel_gray, { }, {}, { "deprecated" }, -}); +});*/ -struct CompExtractChanel : INode { +struct ImageExtractChannel : INode {//why so slow... virtual void apply() override { auto image = get_input("image"); auto channel = get_input2("channel"); @@ -1103,50 +950,34 @@ struct CompExtractChanel : INode { image2->verts.resize(image->size()); if(channel == "R") { for (auto i = 0; i < image->verts.size(); i++) { - image2->verts[i][0] = image->verts[i][0]; - image2->verts[i][1] = image->verts[i][0]; - image2->verts[i][2] = image->verts[i][0]; + image2->verts[i] = vec3f(image->verts[i][0]);//为了速度 verts也要提前吗? 试一下 } } - if(channel == "G") { + else if(channel == "G") { for (auto i = 0; i < image->verts.size(); i++) { - image2->verts[i][0] = image->verts[i][1]; - image2->verts[i][1] = image->verts[i][1]; - image2->verts[i][2] = image->verts[i][1]; + image2->verts[i] = vec3f(image->verts[i][1]); } } - if(channel == "B") { + else if(channel == "B") { for (auto i = 0; i < image->verts.size(); i++) { - image2->verts[i][0] = image->verts[i][2]; - image2->verts[i][1] = image->verts[i][2]; - image2->verts[i][2] = image->verts[i][2]; + image2->verts[i] = vec3f(image->verts[i][2]); } } - if(channel == "A") { + else if(channel == "A") { if (image->verts.has_attr("alpha")) { - auto &Alpha = image->verts.attr("alpha"); - image2->verts.add_attr("alpha"); - image2->verts.attr("alpha")=image->verts.attr("alpha"); - for(int i = 0;i < w * h;i++){ - image2->verts[i][0] = image->verts.attr("alpha")[i]; - image2->verts[i][1] = image->verts.attr("alpha")[i]; - image2->verts[i][2] = image->verts.attr("alpha")[i]; + auto &attr = image->verts.attr("alpha"); + for(int i = 0; i < w * h; i++){ + image2->verts[i] = {attr[i], attr[i], attr[i]}; } } else{ - image2->verts.add_attr("alpha"); - for(int i = 0;i < w * h;i++){ - image2->verts.attr("alpha")[i] = 1.0; - image2->verts[i][0] = image->verts.attr("alpha")[i]; - image2->verts[i][1] = image->verts.attr("alpha")[i]; - image2->verts[i][2] = image->verts.attr("alpha")[i]; - } + throw zeno::makeError("image have no alpha channel"); } } set_output("image", image2); } }; -ZENDEFNODE(CompExtractChanel, { +ZENDEFNODE(ImageExtractChannel, { { {"image"}, {"enum R G B A", "channel", "R"}, @@ -1167,8 +998,8 @@ struct CompImport : INode { virtual void apply() override { auto prim = get_input("prim"); auto &ud = prim->userData(); - int nx = ud.get2("nx"); - int ny = ud.get2("ny"); + int nx = ud.has("nx")?ud.get2("nx"):ud.get2("w"); + int ny = ud.has("ny")?ud.get2("ny"):ud.get2("h"); auto attrName = get_input2("attrName"); auto remapRange = get_input2("RemapRange"); auto remap = get_input2("Remap"); @@ -1177,12 +1008,10 @@ struct CompImport : INode { image->userData().set2("isImage", 1); image->userData().set2("w", nx); image->userData().set2("h", ny); - //zeno::PrimitiveObject *prim = prim.get(); if (prim->verts.attr_is(attrName)) { auto &attr = prim->verts.attr(attrName); //calculate max and min attr value and remap it to 0-1 - //minresult = prim_reduce(prim.get(), attr); float minresult = zeno::parallel_reduce_array(attr.size(), attr[0], [&] (size_t i) -> float { return attr[i]; }, [&] (float i, float j) -> float { return zeno::min(i, j); }); float maxresult = zeno::parallel_reduce_array(attr.size(), attr[0], [&] (size_t i) -> float { return attr[i]; }, @@ -1202,7 +1031,7 @@ struct CompImport : INode { } } } - else if (prim->verts.attr_is(attrName)) { + else if (prim->verts.attr_is(attrName)) {//todo::add remap auto &attr = prim->attr(attrName); for (auto i = 0; i < nx * ny; i++) { image->verts[i] = attr[i]; diff --git a/projects/ImgCV/ImageProcessing.cpp b/projects/ImgCV/ImageProcessing.cpp index 8d69b30a85..e7672cb7c2 100644 --- a/projects/ImgCV/ImageProcessing.cpp +++ b/projects/ImgCV/ImageProcessing.cpp @@ -1733,20 +1733,20 @@ ZENDEFNODE(ImageErode, { struct ImageColor : INode { virtual void apply() override { auto image = std::make_shared(); - auto color = get_input2("Color"); + auto color = get_input2("Color"); auto size = get_input2("Size"); - image->verts.resize(size[0] * size[1]); + auto vertsize = size[0] * size[1]; + image->verts.resize(vertsize); image->userData().set2("isImage", 1); image->userData().set2("w", size[0]); image->userData().set2("h", size[1]); + image->verts.add_attr("alpha"); #pragma omp parallel - for (int i = 0; i < size[1]; i++) { - for (int j = 0; j < size[0]; j++) { - image->verts[i * size[0] + j] = {color[0], color[1], color[2]}; - } + for (int i = 0; i < vertsize ; i++) { + image->verts[i ] = {color[0], color[1], color[2]}; + image->verts.attr("alpha")[i] = color[3]; } - set_output("image", image); } @@ -1754,7 +1754,7 @@ struct ImageColor : INode { ZENDEFNODE(ImageColor, { { - {"vec3f", "Color", "1,1,1"}, + {"vec4f", "Color", "1,1,1,1"}, {"vec2i", "Size", "1024,1024"}, }, { @@ -2447,7 +2447,7 @@ ZENDEFNODE(ImageShape, { {"deprecated"}, }); -struct ImageLevels: INode { +struct ImageLevels: INode {//todo :latger than 1 ? void apply() override { std::shared_ptr image = get_input("image"); auto inputLevels = get_input2("Input Levels");