diff --git a/app/node/color/CMakeLists.txt b/app/node/color/CMakeLists.txt index 96bd0db4f2..a0a4cf7046 100644 --- a/app/node/color/CMakeLists.txt +++ b/app/node/color/CMakeLists.txt @@ -18,6 +18,7 @@ add_subdirectory(colormanager) add_subdirectory(displaytransform) add_subdirectory(ociobase) add_subdirectory(ociogradingtransformlinear) +add_subdirectory(rgbtobw) set(OLIVE_SOURCES ${OLIVE_SOURCES} diff --git a/app/node/color/rgbtobw/CMakeLists.txt b/app/node/color/rgbtobw/CMakeLists.txt new file mode 100644 index 0000000000..8b8a573fee --- /dev/null +++ b/app/node/color/rgbtobw/CMakeLists.txt @@ -0,0 +1,22 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2021 Olive Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + node/color/rgbtobw/rgbtobw.cpp + node/color/rgbtobw/rgbtobw.h + PARENT_SCOPE +) diff --git a/app/node/color/rgbtobw/rgbtobw.cpp b/app/node/color/rgbtobw/rgbtobw.cpp new file mode 100644 index 0000000000..1d47aa7c1d --- /dev/null +++ b/app/node/color/rgbtobw/rgbtobw.cpp @@ -0,0 +1,131 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "rgbtobw.h" + +#include "node/project/project.h" + +namespace olive { + +const QString RGBToBWNode::kTextureInput = QStringLiteral("tex_in"); +const QString RGBToBWNode::kCustomWeightsEnableInput = QStringLiteral("custom_weights_enable_in"); +const QString RGBToBWNode::kCustomWeightsInput = QStringLiteral("custom_weights_in"); + +#define super Node + +RGBToBWNode::RGBToBWNode() : + weights_edited_(false) +{ + AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable)); + + AddInput(kCustomWeightsEnableInput, NodeValue::kBoolean, false); + + AddInput(kCustomWeightsInput, NodeValue::kVec3, QVector3D{0.33f, 0.33f, 0.33f}); //TEMP + + SetInputProperty(kCustomWeightsInput, QStringLiteral("color0"), QColor(255, 0, 0).name()); + SetInputProperty(kCustomWeightsInput, QStringLiteral("color1"), QColor(0, 255, 0).name()); + SetInputProperty(kCustomWeightsInput, QStringLiteral("color2"), QColor(0, 0, 255).name()); + + UpdateInputs(false); + + SetFlags(kVideoEffect); + SetEffectInput(kTextureInput); +} + +QString RGBToBWNode::Name() const +{ + return tr("RGB to B&W"); +} + +QString RGBToBWNode::id() const +{ + return QStringLiteral("org.olivevideoeditor.Olive.rgbtobw"); +} + +QVector RGBToBWNode::Category() const +{ + return {kCategoryColor}; +} + +QString RGBToBWNode::Description() const +{ + return tr("Converts a color image to black and white"); +} + +void RGBToBWNode::Retranslate() +{ + super::Retranslate(); + + SetInputName(kTextureInput, tr("Input")); + SetInputName(kCustomWeightsEnableInput, tr("Use Custom Weights")); + SetInputName(kCustomWeightsInput, tr("Weights")); + + // Only set custom weights to their default value if they haven't been edited yet + if (!weights_edited_) { + if (project()) { + project()->color_manager()->GetDefaultLumaCoefs(luma_coeffs_); + SetStandardValue(kCustomWeightsInput, QVector3D(luma_coeffs_[0], luma_coeffs_[1], luma_coeffs_[2])); + } + } +} + +void RGBToBWNode::InputValueChangedEvent(const QString &input, int element) +{ + Q_UNUSED(element); + + if (input == kCustomWeightsEnableInput) { + UpdateInputs(GetStandardValue(kCustomWeightsEnableInput).toBool()); + } + if (input == kCustomWeightsInput) { + weights_edited_ = true; + } + } +ShaderCode RGBToBWNode::GetShaderCode(const ShaderRequest &request) const +{ + Q_UNUSED(request) + return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/rgbtobw.frag")); +} + +void RGBToBWNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +{ + ShaderJob job(value); + + + // Set luma coefficients + double luma_coeffs[3] = {0.0f, 0.0f, 0.0f}; // Can this use the cached values? + project()->color_manager()->GetDefaultLumaCoefs(luma_coeffs); + job.Insert(QStringLiteral("luma_coeffs"), + NodeValue(NodeValue::kVec3, QVector3D(luma_coeffs[0], luma_coeffs[1], luma_coeffs[2]))); + + // If there's no texture, no need to run an operation + if (TexturePtr tex = value[kTextureInput].toTexture()) { + table->Push(NodeValue::kTexture, tex->toJob(job), this); + } else { + table->Push(value[kTextureInput]); + } +} + +void RGBToBWNode::UpdateInputs(bool custom_coefficients) +{ + SetInputFlags(kCustomWeightsInput, custom_coefficients ? InputFlags() : InputFlags(kInputFlagHidden)); +} + +} + diff --git a/app/node/color/rgbtobw/rgbtobw.h b/app/node/color/rgbtobw/rgbtobw.h new file mode 100644 index 0000000000..6e9f61e9d7 --- /dev/null +++ b/app/node/color/rgbtobw/rgbtobw.h @@ -0,0 +1,60 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef RGBTOBWNODE_H +#define RGBTOBWNODE_H + +#include "node/node.h" + +namespace olive { + +class RGBToBWNode : public Node +{ + Q_OBJECT + public: + RGBToBWNode(); + + NODE_DEFAULT_FUNCTIONS(RGBToBWNode) + + virtual QString Name() const override; + virtual QString id() const override; + virtual QVector Category() const override; + virtual QString Description() const override; + + virtual void Retranslate() override; + virtual void InputValueChangedEvent(const QString &input, int element) override; + + virtual ShaderCode GetShaderCode(const ShaderRequest &request) const override; + virtual void Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const override; + + static const QString kTextureInput; + static const QString kCustomWeightsEnableInput; + static const QString kCustomWeightsInput; + + double luma_coeffs_[3]; + bool weights_edited_; + + private: + void UpdateInputs(bool cutsom_coefficients); +}; + +} // namespace olive + +#endif // RGBTOBWNODE_H diff --git a/app/node/factory.cpp b/app/node/factory.cpp index 1839d8f080..be14d19c68 100644 --- a/app/node/factory.cpp +++ b/app/node/factory.cpp @@ -31,6 +31,7 @@ #include "block/transition/diptocolor/diptocolortransition.h" #include "color/displaytransform/displaytransform.h" #include "color/ociogradingtransformlinear/ociogradingtransformlinear.h" +#include "color/rgbtobw/rgbtobw.h" #include "distort/cornerpin/cornerpindistortnode.h" #include "distort/crop/cropdistortnode.h" #include "distort/flip/flipdistortnode.h" @@ -309,6 +310,8 @@ Node *NodeFactory::CreateFromFactoryIndex(const NodeFactory::InternalID &id) return new RippleDistortNode(); case kMulticamNode: return new MultiCamNode(); + case kRGBToBW: + return new RGBToBWNode(); case kInternalNodeCount: break; diff --git a/app/node/factory.h b/app/node/factory.h index fbf3535514..255e0f8789 100644 --- a/app/node/factory.h +++ b/app/node/factory.h @@ -81,6 +81,7 @@ class NodeFactory kTileDistort, kSwirlDistort, kMulticamNode, + kRGBToBW, // Count value kInternalNodeCount diff --git a/app/shaders/rgbtobw.frag b/app/shaders/rgbtobw.frag new file mode 100644 index 0000000000..af60377773 --- /dev/null +++ b/app/shaders/rgbtobw.frag @@ -0,0 +1,18 @@ +// Input texture +uniform sampler2D tex_in; +uniform vec3 custom_weights_in; +uniform bool custom_weights_enable_in; +uniform vec3 luma_coeffs; + +// Input texture coordinate +in vec2 ove_texcoord; +out vec4 frag_color; + +void main() { + vec4 color = texture(tex_in, ove_texcoord); + if (!custom_weights_enable_in){ + frag_color = vec4(vec3(dot(color.rgb, luma_coeffs)), color.w); + } else { + frag_color = vec4(vec3(dot(color.rgb, custom_weights_in)), color.w); + } +}