From da7eff42d9a5892ae0e75af5559f94b66eb948be Mon Sep 17 00:00:00 2001 From: YingQ Date: Wed, 20 Sep 2023 17:41:14 +0800 Subject: [PATCH] levelAlpha --- projects/ImgCV/ImageComposite.cpp | 19 +- projects/ImgCV/ImageProcessing.cpp | 304 +++++------------------------ 2 files changed, 67 insertions(+), 256 deletions(-) diff --git a/projects/ImgCV/ImageComposite.cpp b/projects/ImgCV/ImageComposite.cpp index 1ca26589ba..5667ee8feb 100644 --- a/projects/ImgCV/ImageComposite.cpp +++ b/projects/ImgCV/ImageComposite.cpp @@ -605,11 +605,11 @@ static T BlendMode(const float &alpha1, const float &alpha2, const T& rgb1, cons return value; } else if(compmode == std::string("Add")) { - T value = zeno::min(rgb1 + rgb2, T(1.0f))*opacity[0] + rgb2 * (1 - opacity[0]);//clamp? + T value = (rgb1 + rgb2) * 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]); + T value = (rgb2 - rgb1) * opacity[0] + rgb2 * (1 - opacity[0]); return value; } else if(compmode == std::string("Multiply")) { @@ -662,6 +662,13 @@ static zeno::vec3f BlendModeV(const float &alpha1, const float &alpha2, const ve value[k] = 2 * rgb2[k] * (1 - rgb1[k]) + sqrt(rgb2[k]) * (2 * rgb1[k] - 1); } } + /*for (int k = 0; k < 3; k++) { Nuke method + if (rgb1[k] * rgb2[k] < 1) { + value[k] = rgb2[k] * (2 * rgb1[k] + (rgb2[k] * (1-rgb1[k] * rgb2[k]))); + } else { + value[k] = 2 * rgb2[k] * rgb1[k]; + } + }*/ value = value * opacity[0] + rgb2 * (1 - opacity[0]); return value; } @@ -726,7 +733,7 @@ struct Blend: INode { 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"){ + 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); } @@ -738,6 +745,7 @@ struct Blend: INode { 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"); + //std::string alphablendmode = alphamode == "SameWithBlend" ? compmode : alphamode; #pragma omp parallel for for (int i = 0; i < imagesize; i++) { vec3f opacity = zeno::clamp(mask->verts[i], 0, 1) * maskopacity; @@ -757,6 +765,7 @@ ZENDEFNODE(Blend, { {"Mask"}, {"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 SameWithBlend Over Under Atop In Out Screen Add Subtract Multiply Max(Lighten) Min(Darken) Average Difference Xor", "Alpha Mode", "SameWithBlend"}, {"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"}, @@ -936,7 +945,7 @@ ZENDEFNODE(CompExtractChanel_gray, { { "deprecated" }, });*/ -struct ImageExtractChannel : INode {//why so slow... +struct ImageExtractChannel : INode { virtual void apply() override { auto image = get_input("image"); auto channel = get_input2("channel"); @@ -950,7 +959,7 @@ struct ImageExtractChannel : INode {//why so slow... image2->verts.resize(image->size()); if(channel == "R") { for (auto i = 0; i < image->verts.size(); i++) { - image2->verts[i] = vec3f(image->verts[i][0]);//为了速度 verts也要提前吗? 试一下 + image2->verts[i] = vec3f(image->verts[i][0]); } } else if(channel == "G") { diff --git a/projects/ImgCV/ImageProcessing.cpp b/projects/ImgCV/ImageProcessing.cpp index e7672cb7c2..e52cf97a3d 100644 --- a/projects/ImgCV/ImageProcessing.cpp +++ b/projects/ImgCV/ImageProcessing.cpp @@ -1225,36 +1225,6 @@ ZENDEFNODE(ImageBilateralBlur, { { "image" }, }); -struct CreateImage : INode { - virtual void apply() override { - auto RGB = get_input2("RGB"); - auto x = get_input2("width"); - auto y = get_input2("height"); - - auto image = std::make_shared(); - image->verts.resize(x * y); - image->userData().set2("h", y); - image->userData().set2("w", x); - image->userData().set2("isImage", 1); - for (int i = 0; i < x * y; i++){ - image->verts[i] = {zeno::clamp(RGB[0]/255, 0, 255),zeno::clamp(RGB[1]/255, 0, 255),zeno::clamp(RGB[2]/255, 0, 255)}; - } - set_output("image", image); - } -}; - -ZENDEFNODE(CreateImage, { - { - {"vec3f", "RGB", "255,255,255"}, - {"int", "width", "1024"}, - {"int", "height", "1024"}, - }, - { - {"image"} - }, - {}, - { "create" }, -}); struct ImageEditContrast : INode { virtual void apply() override { @@ -1408,7 +1378,7 @@ ZENDEFNODE(ImageToNormalMap, { { "image" }, }); -struct ImageGray : INode { +struct ImageGray : INode {//todo void apply() override { auto image = get_input("image"); auto mode = get_input2("mode"); @@ -1441,28 +1411,6 @@ ZENDEFNODE(ImageGray, { { "image" }, }); -struct ImageGetSize : INode { - void apply() override { - auto image = get_input("image"); - auto &ud = image->userData(); - int w = ud.get2("w"); - int h = ud.get2("h"); - set_output2("width", w); - set_output2("height", h); - } -}; -ZENDEFNODE(ImageGetSize, { - { - {"image"}, - }, - { - {"int", "width"}, - {"int", "height"}, - }, - {}, - {"image"}, -}); - static std::shared_ptr normal_tiling(std::shared_ptr &image1, std::shared_ptr &image2, int rows, int cols) { int width = image1->userData().get2("w"); int height = image1->userData().get2("h"); @@ -1735,17 +1683,23 @@ struct ImageColor : INode { auto image = std::make_shared(); auto color = get_input2("Color"); auto size = get_input2("Size"); + auto balpha = get_input2("alpha"); 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 < vertsize ; i++) { - image->verts[i ] = {color[0], color[1], color[2]}; - image->verts.attr("alpha")[i] = color[3]; + if(balpha){ + auto &alphaAttr = image->verts.add_attr("alpha"); + for (int i = 0; i < vertsize ; i++) { + image->verts[i] = {zeno::clamp(color[0], 0.0f, 1.0f), zeno::clamp(color[1], 0.0f, 1.0f), zeno::clamp(color[2], 0.0f, 1.0f)}; + alphaAttr[i] = zeno::clamp(color[3], 0.0f, 1.0f); + } + } + else{ + for (int i = 0; i < vertsize ; i++) { + image->verts[i] = {zeno::clamp(color[0], 0.0f, 1.0f), zeno::clamp(color[1], 0.0f, 1.0f), zeno::clamp(color[2], 0.0f, 1.0f)}; + } } set_output("image", image); @@ -1756,6 +1710,7 @@ ZENDEFNODE(ImageColor, { { {"vec4f", "Color", "1,1,1,1"}, {"vec2i", "Size", "1024,1024"}, + {"bool", "alpha", "1"}, }, { {"image"}, @@ -2247,155 +2202,6 @@ ZENDEFNODE(ImageMatting, { { "image" }, }); -struct ImageDelAlpha: INode { - virtual void apply() override { - auto image = get_input("image"); - auto &ud = image->userData(); - int w = ud.get2("w"); - int h = ud.get2("h"); - - if(image->verts.has_attr("alpha")){ - image->verts.erase_attr("alpha"); - } - set_output("image", image); - } -}; - -ZENDEFNODE(ImageDelAlpha, { - { - {"image"}, - }, - { - {"image"} - }, - {}, - { "image" }, -}); - -struct ImageAddAlpha: INode { - virtual void apply() override { - auto image = get_input("image"); - auto &ud = image->userData(); - int w = ud.get2("w"); - int h = ud.get2("h"); - auto maskmode = get_input2("maskmode"); - image->verts.add_attr("alpha"); - for(int i = 0;i < image->size();i++){ - image->verts.attr("alpha")[i] = 1; - } - if (has_input("mask")) { - auto gimage = get_input2("mask"); - auto &gud = gimage->userData(); - int wg = gud.get2("w"); - int hg = gud.get2("h"); - if (wg == w && hg == h) { - if (maskmode == "gray_black") { - if (gimage->verts.has_attr("alpha")) { - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - if (gimage->verts.attr("alpha")[i * w + j] != 0 && - image->verts.attr("alpha")[i * w + j] != 0) { - image->verts.attr("alpha")[i * w + j] = 1 - gimage->verts[i * w + j][0]; - } else { - image->verts.attr("alpha")[i * w + j] = 0; - } - } - } - } else { - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - if (image->verts.attr("alpha")[i * w + j] != 0) { - image->verts.attr("alpha")[i * w + j] = 1 - gimage->verts[i * w + j][0]; - } - } - } - } - } else if (maskmode == "gray_white") { - if (gimage->verts.has_attr("alpha")) { - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - if (gimage->verts.attr("alpha")[i * w + j] != 0 && - image->verts.attr("alpha")[i * w + j] != 0) { - image->verts.attr("alpha")[i * w + j] = gimage->verts[i * w + j][0]; - } else { - image->verts.attr("alpha")[i * w + j] = 0; - } - } - } - } else { - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - if (image->verts.attr("alpha")[i * w + j] != 0) { - image->verts.attr("alpha")[i * w + j] = gimage->verts[i * w + j][0]; - } - } - } - } - } - else if (maskmode == "alpha") { - if (gimage->verts.has_attr("alpha")) { - image->verts.attr("alpha") = gimage->verts.attr("alpha"); - } else { - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - if (image->verts.attr("alpha")[i * w + j] != 0) { - image->verts.attr("alpha")[i * w + j] = 1; - } - } - } - } - } - } - } - set_output("image", image); - } -}; -ZENDEFNODE(ImageAddAlpha, { - { - {"image"}, - {"mask"}, - {"enum alpha gray_black gray_white", "maskmode", "alpha"}, - }, - { - {"image"} - }, - {}, - { "image" }, -}); - -struct ImageCut: INode { - void apply() override { - std::shared_ptr image = get_input("image"); - auto tilemode = get_input2("tilemode"); - auto rows = get_input2("rows"); - auto cols = get_input2("cols"); - UserData &ud = image->userData(); - int w = ud.get2("w"); - int h = ud.get2("h"); - int w1 = w * cols; - int h1 = h * rows; - auto image2 = std::make_shared(); - image2->resize(w1 * h1); - image2->userData().set2("isImage", 1); - image2->userData().set2("w", w1); - image2->userData().set2("h", h1); - set_output("image", image2); - } -}; -ZENDEFNODE(ImageCut, { - { - {"image"}, - {"enum normal mirror", "tilemode", "normal"}, - {"int", "rows", "2"}, - {"int", "cols", "2"}, - }, - { - {"deprecated"}, - }, - {}, - {"image"}, -}); - //根据灰度进行上色 struct MaskEdit: INode { void apply() override { @@ -2423,37 +2229,15 @@ ZENDEFNODE(MaskEdit, { {"deprecated"}, }); -struct ImageShape: INode { - void apply() override { - std::shared_ptr image = get_input("image"); - auto rows = get_input2("rows"); - auto cols = get_input2("cols"); - UserData &ud = image->userData(); - int w = ud.get2("w"); - int h = ud.get2("h"); - set_output("image", image); - } -}; -ZENDEFNODE(ImageShape, { - { - {"image"}, - {"int", "rows", "2"}, - {"int", "cols", "2"}, - }, - { - {"image"}, - }, - {}, - {"deprecated"}, -}); -struct ImageLevels: INode {//todo :latger than 1 ? +struct ImageLevels: INode { void apply() override { std::shared_ptr image = get_input("image"); auto inputLevels = get_input2("Input Levels"); auto outputLevels = get_input2("Output Levels"); auto gamma = get_input2("gamma");//range 0.01 - 9.99 auto channel = get_input2("channel"); + auto clamp = get_input2("Clamp Output"); UserData &ud = image->userData(); int w = ud.get2("w"); int h = ud.get2("h"); @@ -2463,60 +2247,77 @@ struct ImageLevels: INode {//todo :latger than 1 ? float outputMin = outputLevels[0]; float gammaCorrection = 1.0f / gamma; - if (channel == "RGB") { + if (channel == "All") { #pragma omp parallel for - for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { - vec3f &v = image->verts[i * w + j]; + for (int i = 0; i < w * h; i++) { + vec3f &v = image->verts[i]; v[0] = (v[0] < inputMin) ? inputMin : v[0]; v[1] = (v[1] < inputMin) ? inputMin : v[1]; v[2] = (v[2] < inputMin) ? inputMin : v[2]; v = (v - inputMin) / inputRange; v = pow(v, gammaCorrection); - v = v * outputRange + outputMin; + v = clamp ? zeno::clamp((v * outputRange + outputMin), 0, 1) : (v * outputRange + outputMin); + } + if(image->has_attr("alpha")){ + auto &alphaAttr = image->verts.attr("alpha"); +#pragma omp parallel for + for (int i = 0; i < w * h; i++) { + alphaAttr[i] = (alphaAttr[i] < inputMin) ? inputMin : alphaAttr[i]; + alphaAttr[i] = (alphaAttr[i] - inputMin) / inputRange; + alphaAttr[i] = pow(alphaAttr[i], gammaCorrection) * outputRange + outputMin; + alphaAttr[i] = clamp ? zeno::clamp(alphaAttr[i], 0, 1) : alphaAttr[i]; + } } - } } else if (channel == "R") { #pragma omp parallel for for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { - float &v = image->verts[i * w + j][0]; + float &v = image->verts[i][0]; if (v < inputMin) v = inputMin; v = (v - inputMin) / inputRange; v = pow(v, gammaCorrection); - v = v * outputRange + outputMin; + v = clamp ? zeno::clamp((v * outputRange + outputMin), 0, 1) : (v * outputRange + outputMin); } } - } else if (channel == "G") { #pragma omp parallel for for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { - float &v = image->verts[i * w + j][1]; + float &v = image->verts[i][1]; if (v < inputMin) v = inputMin; v = (v - inputMin) / inputRange; v = pow(v, gammaCorrection); - v = v * outputRange + outputMin; + v = clamp ? zeno::clamp((v * outputRange + outputMin), 0, 1) : (v * outputRange + outputMin); } } - } else if (channel == "B") { #pragma omp parallel for for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { - float &v = image->verts[i * w + j][2]; + float &v = image->verts[i][2]; if (v < inputMin) v = inputMin; v = (v - inputMin) / inputRange; v = pow(v, gammaCorrection); - v = v * outputRange + outputMin; + v = clamp ? zeno::clamp((v * outputRange + outputMin), 0, 1) : (v * outputRange + outputMin); } } + + else if (channel == "A") { + if(image->has_attr("alpha")){ + auto &alphaAttr = image->verts.attr("alpha"); +#pragma omp parallel for + for (int i = 0; i < w * h; i++) { + alphaAttr[i] = (alphaAttr[i] < inputMin) ? inputMin : alphaAttr[i]; + alphaAttr[i] = (alphaAttr[i] - inputMin) / inputRange; + alphaAttr[i] = pow(alphaAttr[i], gammaCorrection) * outputRange + outputMin; + alphaAttr[i] = clamp ? zeno::clamp(alphaAttr[i], 0, 1) : alphaAttr[i]; + } + } + else{ + zeno::log_error("no alpha channel"); + } } - set_output("image", image); } }; @@ -2527,7 +2328,8 @@ ZENDEFNODE(ImageLevels, { {"float", "gamma", "1"}, {"vec2f", "Output Levels", "0, 1"}, //{"bool", "auto level", "false"}, //auto level - {"enum RGB R G B", "channel", "RGB"}, + {"enum All R G B A", "channel", "RGB"}, + {"bool", "Clamp Output", "1"}, }, { {"image"},