Fix T51308: Bright/Contrast Doesn't respect Pre-multiplied Alpha

Brightness/contrast node was changing color but did not modify alpha
or ensured colors are premultiplied on the output. This was giving
artifacts later on unless alpha was manually converted.

Compositor is supposed to work in premultiplied alpha (except of
some really corner cases) so it makes sense to ensure premultiplied
alpha after brightness/contrast node.

This is now done as an option enabled by default, so we:

(a) Keep compatibility with old files.
(b) Have correct behavior for newly created files.

Later on we can get rid of this option.
This commit is contained in:
Sergey Sharybin 2017-05-22 17:12:13 +02:00
parent 849e77b1f9
commit 8cc4c3da8c
Notes: blender-bot 2023-02-14 07:02:37 +01:00
Referenced by issue #51308, Bright/Contrast Doesn't respect Pre-multiplied Alpha
7 changed files with 41 additions and 2 deletions

View File

@ -31,7 +31,9 @@ BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode)
void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *bnode = this->getbNode();
BrightnessOperation *operation = new BrightnessOperation();
operation->setUsePremultiply((bnode->custom1 & 1) != 0);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));

View File

@ -29,7 +29,14 @@ BrightnessOperation::BrightnessOperation() : NodeOperation()
this->addInputSocket(COM_DT_VALUE);
this->addOutputSocket(COM_DT_COLOR);
this->m_inputProgram = NULL;
this->m_use_premultiply = false;
}
void BrightnessOperation::setUsePremultiply(bool use_premultiply)
{
this->m_use_premultiply = use_premultiply;
}
void BrightnessOperation::initExecution()
{
this->m_inputProgram = this->getInputSocketReader(0);
@ -64,11 +71,16 @@ void BrightnessOperation::executePixelSampled(float output[4], float x, float y,
delta *= -1;
b = a * (brightness + delta);
}
if (this->m_use_premultiply) {
premul_to_straight_v4(inputValue);
}
output[0] = a * inputValue[0] + b;
output[1] = a * inputValue[1] + b;
output[2] = a * inputValue[2] + b;
output[3] = inputValue[3];
if (this->m_use_premultiply) {
straight_to_premul_v4(output);
}
}
void BrightnessOperation::deinitExecution()

View File

@ -34,6 +34,8 @@ private:
SocketReader *m_inputBrightnessProgram;
SocketReader *m_inputContrastProgram;
bool m_use_premultiply;
public:
BrightnessOperation();
@ -52,5 +54,6 @@ public:
*/
void deinitExecution();
void setUsePremultiply(bool use_premultiply);
};
#endif

View File

@ -2478,6 +2478,11 @@ static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), P
uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE);
}
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@ -2705,6 +2710,8 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_SUNBEAMS:
ntype->draw_buttons = node_composit_buts_sunbeams;
break;
case CMP_NODE_BRIGHTCONTRAST:
ntype->draw_buttons = node_composit_buts_brightcontrast;
}
}

View File

@ -5239,6 +5239,16 @@ static void def_cmp_luma_matte(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_brightcontrast(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
RNA_def_property_ui_text(prop, "Convert Premul", "Keep output image premultiplied alpha");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_chroma_matte(StructRNA *srna)
{
PropertyRNA *prop;

View File

@ -179,7 +179,7 @@ DefNode( CompositorNode, CMP_NODE_DISPLACE, 0, "DISPL
DefNode( CompositorNode, CMP_NODE_COMBHSVA, 0, "COMBHSVA", CombHSVA, "Combine HSVA", "" )
DefNode( CompositorNode, CMP_NODE_MATH, def_math, "MATH", Math, "Math", "" )
DefNode( CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luminance Key", "" )
DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" )
DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, def_cmp_brightcontrast, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" )
DefNode( CompositorNode, CMP_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" )
DefNode( CompositorNode, CMP_NODE_INVERT, def_cmp_invert, "INVERT", Invert, "Invert", "" )
DefNode( CompositorNode, CMP_NODE_NORMALIZE, 0, "NORMALIZE", Normalize, "Normalize", "" )

View File

@ -46,6 +46,10 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = {
{ -1, 0, "" }
};
static void node_composit_init_brightcontrast(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 = 1;
}
void register_node_type_cmp_brightcontrast(void)
{
@ -53,6 +57,7 @@ void register_node_type_cmp_brightcontrast(void)
cmp_node_type_base(&ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out);
node_type_init(&ntype, node_composit_init_brightcontrast);
nodeRegisterType(&ntype);
}