void ZenoImagePanel::setPrim(std::string primid) {
primid = primid.substr(0, primid.find(":"));
pPrimName->setText(primid.c_str());
zenovis::Scene* scene = nullptr;
auto mainWin = zenoApp->getMainWindow();
ZASSERT_EXIT(mainWin);
QVector<DisplayWidget*> wids = mainWin->viewports();
if (!wids.isEmpty())
{
auto session = wids[0]->getZenoVis()->getSession();
ZASSERT_EXIT(session);
scene = session->get_scene();
}
if (!scene)
return;
bool found = false;
for (auto const &[key, ptr]: scene->objectsMan->pairs()) {
if ((key.substr(0, key.find(":"))) != primid) {
continue;
}
auto &ud = ptr->userData();
if (ud.get2<int>("isImage", 0) == 0) {
continue;
}
found = true;
if (auto obj = dynamic_cast<zeno::PrimitiveObject *>(ptr)) {
int width = ud.get2<int>("w");
int height = ud.get2<int>("h");
if (image_view) {
QImage img(width, height, QImage::Format_RGB32);
int gridSize = 50;
if (obj->verts.has_attr("alpha")) {
auto &alpha = obj->verts.attr<float>("alpha");
for (auto i = 0; i < obj->verts.size(); i++) {
int h = i / width;
int w = i % width;
auto foreground = obj->verts[i];
foreground = zeno::pow(foreground, 1.0f / 2.2f);
zeno::vec3f background;
if ((h / gridSize) % 2 == (w / gridSize) % 2) {
background = {1, 1, 1};
}
else {
background = {0.86, 0.86, 0.86};
}
zeno::vec3f c = zeno::mix(background, foreground, alpha[i]);
int r = glm::clamp(int(c[0] * 255.99), 0, 255);
int g = glm::clamp(int(c[1] * 255.99), 0, 255);
int b = glm::clamp(int(c[2] * 255.99), 0, 255);
img.setPixel(w, height - 1 - h, qRgb(r, g, b));
}
}
else{
for (auto i = 0; i < obj->verts.size(); i++) {
int h = i / width;
int w = i % width;
auto c = obj->verts[i];
c = zeno::pow(c, 1.0f / 2.2f);
int r = glm::clamp(int(c[0] * 255.99), 0, 255);
int g = glm::clamp(int(c[1] * 255.99), 0, 255);
int b = glm::clamp(int(c[2] * 255.99), 0, 255);
img.setPixel(w, height - 1 - h, qRgb(r, g, b));
}
}
image_view->setImage(img);
}
QString statusInfo = QString(zeno::format("width: {}, height: {}", width, height).c_str());
pStatusBar->setText(statusInfo);
}
}
if (found == false) {
clear();
}
}
#include "zenoimagepanel.h"
#include "PrimAttrTableModel.h"
#include "viewport/zenovis.h"
#include "zenovis/ObjectsManager.h"
#include "zeno/utils/format.h"
#include <zeno/types/UserData.h>
#include <zeno/types/PrimitiveObject.h>
#include <zenoui/comctrl/zcombobox.h>
#include "zeno/utils/log.h"
#include "zenoapplication.h"
#include "zassert.h"
#include "viewport/viewportwidget.h"
#include "zenomainwindow.h"
#include "viewport/displaywidget.h"
const float ziv_wheelZoomFactor = 1.25;
class ZenoImageView: public QGraphicsView {
public:
QGraphicsPixmapItem *_image = nullptr;
QGraphicsScene *scene = nullptr;
explicit ZenoImageView(QWidget *parent) : QGraphicsView(parent) {
scene = new QGraphicsScene;
this->setScene(scene);
setBackgroundBrush(QColor(37, 37, 37));
this->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
this->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
}
bool hasImage() {
return _image != nullptr;
}
void clearImage() {
if (hasImage()) {
scene->removeItem(_image);
_image = nullptr;
}
}
void setImage(const QImage &image) {
QPixmap pm = QPixmap::fromImage(image);
if (hasImage()) {
_image->setPixmap(pm);
}
else {
_image = this->scene->addPixmap(pm);
}
setSceneRect(QRectF(pm.rect())); // Set scene size to image size.
updateImageView();
}
void updateImageView() {
if (!hasImage()) {
return;
}
fitInView(sceneRect(), Qt::AspectRatioMode::KeepAspectRatio);
}
void resizeEvent(QResizeEvent *event) override {
updateImageView();
}
};
void ZenoImagePanel::clear() {
if (image_view) {
image_view->clearImage();
}
pPrimName->clear();
pStatusBar->clear();
}
void ZenoImagePanel::setPrim(std::string primid) {
primid = primid.substr(0, primid.find(":"));
pPrimName->setText(primid.c_str());
zenovis::Scene* scene = nullptr;
auto mainWin = zenoApp->getMainWindow();
ZASSERT_EXIT(mainWin);
QVector<DisplayWidget*> wids = mainWin->viewports();
if (!wids.isEmpty())
{
auto session = wids[0]->getZenoVis()->getSession();
ZASSERT_EXIT(session);
scene = session->get_scene();
}
if (!scene)
return;
bool found = false;
for (auto const &[key, ptr]: scene->objectsMan->pairs()) {
if ((key.substr(0, key.find(":"))) != primid) {
continue;
}
auto &ud = ptr->userData();
if (ud.get2<int>("isImage", 0) == 0) {
continue;
}
found = true;
if (auto obj = dynamic_cast<zeno::PrimitiveObject *>(ptr)) {
int width = ud.get2<int>("w");
int height = ud.get2<int>("h");
if (image_view) {
QImage img(width, height, QImage::Format_RGB32);
int gridSize = 50;
std::vector<zeno::vec3f> rgb;
if (obj->verts.has_attr("alpha")) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
if(obj->verts.attr<float>("alpha")[i * width + j]==0){
if ((i / gridSize) % 2 == (j / gridSize) % 2) {
rgb.push_back(zeno::vec3f(220,220,220));
} else {
rgb.push_back(zeno::vec3f(255, 255, 255));
// img.setPixel(j, height-1-i, qRgba(255, 255, 255, 255)); // 白色格子
}
}
else if(obj->verts.attr<float>("alpha")[i * width + j]!=0 && obj->verts.attr<float>("alpha")[i * width + j]!=1){
auto a1 = obj->verts.attr<float>("alpha")[i * width + j];
auto c = obj->verts[i * width + j];
if ((i / gridSize) % 2 == (j / gridSize) % 2) {
c = zeno::pow(c, 1.0f / 2.2f);
rgb.push_back(zeno::vec3f(glm::clamp(int(c[0] * 255.99 * a1 + 220 * (1-a1)), 0, 255),
glm::clamp(int(c[1] * 255.99 * a1 + 220 * (1-a1)), 0, 255),
glm::clamp(int(c[2] * 255.99 * a1 + 220 * (1-a1)), 0, 255)));
} else {
c = zeno::pow(c, 1.0f / 2.2f);
rgb.push_back(zeno::vec3f(glm::clamp(int(c[0] * 255.99 * a1 + 255 * (1-a1)), 0, 255),
glm::clamp(int(c[1] * 255.99 * a1 + 255 * (1-a1)), 0, 255),
glm::clamp(int(c[2] * 255.99 * a1 + 255 * (1-a1)), 0, 255)));
}
}
else{
auto c = obj->verts[i * width + j];
c = zeno::pow(c, 1.0f / 2.2f);
rgb.push_back(zeno::vec3f(glm::clamp(int(c[0] * 255.99), 0, 255),
glm::clamp(int(c[1] * 255.99), 0, 255),
glm::clamp(int(c[2] * 255.99), 0, 255)));
}
}
}
}
else{
for (auto i = 0; i < obj->verts.size(); i++) {
auto c = obj->verts[i];
c = zeno::pow(c, 1.0f / 2.2f);
rgb.push_back(zeno::vec3f(glm::clamp(int(c[0] * 255.99), 0, 255),
glm::clamp(int(c[1] * 255.99), 0, 255),
glm::clamp(int(c[2] * 255.99), 0, 255)));
}
}
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
img.setPixel(j, height - 1 - i, qRgba(rgb[i * width + j][0], rgb[i * width + j][1], rgb[i * width + j][2] ,255));
}
}
image_view->setImage(img);
}
QString statusInfo = QString(zeno::format("width: {}, height: {}", width, height).c_str());
pStatusBar->setText(statusInfo);
}
}
if (found == false) {
clear();
}
}
ZenoImagePanel::ZenoImagePanel(QWidget *parent) : QWidget(parent) {
QVBoxLayout* pMainLayout = new QVBoxLayout;
pMainLayout->setContentsMargins(QMargins(0, 0, 0, 0));
setLayout(pMainLayout);
setFocusPolicy(Qt::ClickFocus);
QPalette palette = this->palette();
palette.setBrush(QPalette::Window, QColor(37, 37, 38));
setPalette(palette);
setAutoFillBackground(true);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
QHBoxLayout* pTitleLayout = new QHBoxLayout;
QLabel* pPrim = new QLabel(tr("Prim: "));
pPrim->setProperty("cssClass", "proppanel");
pTitleLayout->addWidget(pPrim);
pPrimName->setProperty("cssClass", "proppanel");
pTitleLayout->addWidget(pPrimName);
// ZComboBox* pMode = new ZComboBox();
// pMode->addItem("RGB");
// pMode->addItem("RGBA");
// pMode->addItem("R");
// pMode->addItem("G");
// pMode->addItem("B");
// pMode->setProperty("cssClass", "proppanel");
// pTitleLayout->addWidget(pMode);
pMainLayout->addLayout(pTitleLayout);
image_view = new ZenoImageView(this);
image_view->setProperty("cssClass", "proppanel");
pMainLayout->addWidget(image_view);
pStatusBar->setProperty("cssClass", "proppanel");
pStatusBar->setText("PlaceHolder");
pMainLayout->addWidget(pStatusBar);
auto mainWin = zenoApp->getMainWindow();
ZASSERT_EXIT(mainWin);
QVector<DisplayWidget*> wids = mainWin->viewports();
if (wids.isEmpty())
return;
Zenovis* zenovis = wids[0]->getZenoVis();
if (!zenovis)
return;
connect(zenovis, &Zenovis::objectsUpdated, this, [=](int frame) {
std::string prim_name = pPrimName->text().toStdString();
Zenovis* zenovis = wids[0]->getZenoVis();
ZASSERT_EXIT(zenovis);
auto session = zenovis->getSession();
ZASSERT_EXIT(session);
auto scene = session->get_scene();
ZASSERT_EXIT(scene);
for (auto const &[key, ptr]: scene->objectsMan->pairs()) {
if (key.find(prim_name) == 0 && key.find(zeno::format(":{}:", frame)) != std::string::npos) {
setPrim(key);
}
}
});
}
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 (auto a = 0; a < h1 * w1; a++){
// int i = a / w1;
// int j = a % w1;
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" },
});
(220, 220, 220); // 黑色格子
(255, 255, 255); // 白色格子
#2D3239 light
#121416 darkColor 1 (RGB): 45,50,57
Color 2 (RGB): 18,20,22