Files
test2/source/blender/sequencer/intern/modifiers/MOD_brightness_contrast.cc
Falk David 8571dfa881 Cleanup: VSE: Add read/write callbacks to strip modifiers
This replaces the hardcoded function with modifier type callbacks
to make it easier to customize the reading/writing
for custom modifier data.
No functional changes.

Pull Request: https://projects.blender.org/blender/blender/pulls/145737
2025-09-04 17:27:42 +02:00

118 lines
3.2 KiB
C++

/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup sequencer
*/
#include <cfloat>
#include "BLI_math_base.h"
#include "BLI_math_vector.hh"
#include "BLT_translation.hh"
#include "DNA_sequence_types.h"
#include "SEQ_modifier.hh"
#include "SEQ_modifiertypes.hh"
#include "UI_interface.hh"
#include "UI_interface_layout.hh"
#include "modifier.hh"
namespace blender::seq {
struct BrightContrastApplyOp {
float mul;
float add;
template<typename ImageT, typename MaskT>
void apply(ImageT *image, const MaskT *mask, IndexRange size)
{
for ([[maybe_unused]] int64_t i : size) {
/* NOTE: arguably incorrect usage of "raw" values, should be un-premultiplied.
* Not changing behavior for now, but would be good to fix someday. */
float4 input = load_pixel_raw(image);
float4 result;
result = input * this->mul + this->add;
result.w = input.w;
apply_and_advance_mask(input, result, mask);
store_pixel_raw(result, image);
image += 4;
}
}
};
static void brightcontrast_apply(const StripScreenQuad & /*quad*/,
StripModifierData *smd,
ImBuf *ibuf,
ImBuf *mask)
{
const BrightContrastModifierData *bcmd = (BrightContrastModifierData *)smd;
BrightContrastApplyOp op;
/* The algorithm is by Werner D. Streidt
* (http://visca.com/ffactory/archives/5-99/msg00021.html)
* Extracted from OpenCV `demhist.cpp`. */
const float brightness = bcmd->bright / 100.0f;
const float contrast = bcmd->contrast;
float delta = contrast / 200.0f;
if (contrast > 0) {
op.mul = 1.0f - delta * 2.0f;
op.mul = 1.0f / max_ff(op.mul, FLT_EPSILON);
op.add = op.mul * (brightness - delta);
}
else {
delta *= -1;
op.mul = max_ff(1.0f - delta * 2.0f, 0.0f);
op.add = op.mul * brightness + delta;
}
apply_modifier_op(op, ibuf, mask);
}
static void brightcontrast_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA *ptr = UI_panel_custom_data_get(panel);
layout->use_property_split_set(true);
layout->prop(ptr, "bright", UI_ITEM_NONE, std::nullopt, ICON_NONE);
layout->prop(ptr, "contrast", UI_ITEM_NONE, std::nullopt, ICON_NONE);
if (uiLayout *mask_input_layout = layout->panel_prop(
C, ptr, "open_mask_input_panel", IFACE_("Mask Input")))
{
draw_mask_input_type_settings(C, mask_input_layout, ptr);
}
}
static void brightcontrast_register(ARegionType *region_type)
{
modifier_panel_register(region_type, eSeqModifierType_BrightContrast, brightcontrast_panel_draw);
}
StripModifierTypeInfo seqModifierType_BrightContrast = {
/*idname*/ "BrightContrast",
/*name*/ CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Brightness/Contrast"),
/*struct_name*/ "BrightContrastModifierData",
/*struct_size*/ sizeof(BrightContrastModifierData),
/*init_data*/ nullptr,
/*free_data*/ nullptr,
/*copy_data*/ nullptr,
/*apply*/ brightcontrast_apply,
/*panel_register*/ brightcontrast_register,
/*blend_write*/ nullptr,
/*blend_read*/ nullptr,
};
}; // namespace blender::seq