128 if (ibuf ==
nullptr) {
132 "Sequencer only supports 4 channel images");
134 "Sequencer only supports 4 channel images");
137 uchar *image_byte = ibuf->byte_buffer.data;
138 float *image_float = ibuf->float_buffer.data;
139 const uchar *mask_byte = mask ? mask->byte_buffer.data : nullptr;
140 const float *mask_float = mask ? mask->float_buffer.data : nullptr;
141 const void *mask_none = nullptr;
142 int64_t offset = range.first() * 4;
148 op.apply(image_byte + offset, mask_byte + offset, range);
150 else if (mask_float) {
151 op.apply(image_byte + offset, mask_float + offset, range);
154 op.apply(image_byte + offset, mask_none, range);
157 else if (image_float) {
159 op.apply(image_float + offset, mask_byte + offset, range);
161 else if (mask_float) {
162 op.apply(image_float + offset, mask_float + offset, range);
165 op.apply(image_float + offset, mask_none, range);
181 ImBuf *mask_input =
nullptr;
194 mask_input =
seq_render_mask(context, mask_id, timeline_frame - fra_offset,
false);
215 float in,
const float lift,
const float gain,
const float gamma,
const float mul)
217 float x = (((
in - 1.0f) * lift) + 1.0f) * gain;
220 x = std::max(
x, 0.0f);
229 float in,
const float slope,
const float offset,
const float power,
float mul)
231 float x =
in * slope + offset;
234 x = std::max(
x, 0.0f);
249 float lift,
float gain,
float gamma,
float mul,
float r_table[
CB_TABLE_SIZE])
283 result.x = this->lut[0][p0];
284 result.y = this->lut[1][p1];
285 result.z = this->lut[2][p2];
346 for (
int c = 0; c < 3; c++) {
349 if (this->lift[c] > 1.0f) {
350 this->lift[c] =
powf(this->lift[c] - 1.0f, 2.0f) + 1.0f;
352 this->lift[c] = 2.0f - this->lift[c];
378 this->offset = -this->offset;
389 this->multiplier =
data.color_multiply;
390 this->method =
data.color_balance.method;
395 for (
int c = 0; c < 3; c++) {
397 this->lift[c], this->gain[c], this->gamma[c], this->multiplier, this->lut[c]);
404 for (
int c = 0; c < 3; c++) {
406 this->slope[c], this->offset[c], this->power[c], this->multiplier, this->lut[c]);
423 for (
int c = 0; c < 3; c++) {
460 template<
typename ImageT,
typename MaskT>
472 for (
int i = 0;
i < 3;
i++) {
533 template<
typename ImageT,
typename MaskT>
557 const float black[3] = {0.0f, 0.0f, 0.0f};
558 const float white[3] = {1.0f, 1.0f, 1.0f};
586 for (c = 0; c < 3; c++) {
615 template<
typename ImageT,
typename MaskT>
641 hsv.x = hsv.x -
floorf(hsv.x);
678 template<
typename ImageT,
typename MaskT>
709 const float brightness = bcmd->
bright / 100.0f;
710 const float contrast = bcmd->
contrast;
711 float delta = contrast / 200.0f;
714 op.
mul = 1.0f - delta * 2.0f;
716 op.
add = op.
mul * (brightness - delta);
720 op.
mul =
max_ff(1.0f - delta * 2.0f, 0.0f);
721 op.
add = op.
mul * brightness + delta;
751 template<
typename ImageT,
typename MaskT>
757 if constexpr (std::is_same_v<ImageT, uchar>) {
760 image[3] =
uchar(image[3] * m);
762 else if constexpr (std::is_same_v<ImageT, float>) {
767 *
reinterpret_cast<float4 *
>(image) = pix;
779 if (
mask ==
nullptr || (
mask->byte_buffer.data ==
nullptr &&
mask->float_buffer.data ==
nullptr))
826 (
float *)(pixels),
int(
count), 1, 4, colorspace,
false);
835 const uchar *bptr = pixels;
843 (
float *)dst,
int(
count), 1, 4, colorspace,
false);
851 (
float *)(fptr + range.
first()),
int(range.
size()), 1, 4, colorspace);
858 (
float *)src,
int(range.
size()), 1, 4, colorspace);
859 const float4 *src_ptr = src;
861 for (
const int64_t idx : range) {
876 for (
const int64_t pixel_index : range) {
882 pixel.x /= (d.x == 0.0f) ? 1.0f : d.x;
883 pixel.y /= (d.y == 0.0f) ? 1.0f : d.y;
884 pixel.z /= (d.z == 0.0f) ? 1.0f : d.z;
885 const float igm = avg.
igm;
893 if (
mask !=
nullptr) {
895 if (mask_byte !=
nullptr) {
898 else if (mask_float !=
nullptr) {
899 msk = mask_float[pixel_index].
xyz();
904 scene_linear[index] =
float4(pixel.x, pixel.y, pixel.z,
input.w);
923 for (
const int64_t pixel_index : range) {
929 float I_l = pixel.x + ic * (
L - pixel.x);
930 float I_g = avg.
cav.x + ic * (avg.
lav - avg.
cav.x);
931 float I_a = I_l + ia * (I_g - I_l);
932 pixel.x /= std::max(pixel.x +
powf(f * I_a, m), 1.0e-30f);
933 I_l = pixel.y + ic * (
L - pixel.y);
934 I_g = avg.
cav.y + ic * (avg.
lav - avg.
cav.y);
935 I_a = I_l + ia * (I_g - I_l);
936 pixel.y /= std::max(pixel.y +
powf(f * I_a, m), 1.0e-30f);
937 I_l = pixel.z + ic * (
L - pixel.z);
938 I_g = avg.
cav.z + ic * (avg.
lav - avg.
cav.z);
939 I_a = I_l + ia * (I_g - I_l);
940 pixel.z /= std::max(pixel.z +
powf(f * I_a, m), 1.0e-30f);
943 if (
mask !=
nullptr) {
945 if (mask_byte !=
nullptr) {
948 else if (mask_float !=
nullptr) {
949 msk = mask_float[pixel_index].
xyz();
954 scene_linear[index] =
float4(pixel.x, pixel.y, pixel.z,
input.w);
975 const bool all_pixels_inside_quad,
978 const float4 *scene_linear,
981 for (
const int y : y_range) {
982 for (
int x = 0;
x < width;
x++) {
984 float4 pixel = *scene_linear;
1016 AreaLuminance lum = init;
1017 const int64_t chunk_size = y_range.size() * ibuf->x;
1020 if (ibuf->float_buffer.data != nullptr) {
1021 float4 *fptr = reinterpret_cast<float4 *>(ibuf->float_buffer.data);
1022 fptr += y_range.first() * ibuf->x;
1023 pixels_to_scene_linear_float(ibuf->float_buffer.colorspace, fptr, chunk_size);
1024 tonemap_calc_chunk_luminance(quad, all_pixels_inside_quad, ibuf->x, y_range, fptr, lum);
1027 const uchar *bptr = ibuf->byte_buffer.data + y_range.first() * ibuf->x * 4;
1028 Array<float4> scene_linear(chunk_size);
1029 pixels_to_scene_linear_byte(
1030 ibuf->byte_buffer.colorspace, bptr, scene_linear.data(), chunk_size);
1031 tonemap_calc_chunk_luminance(
1032 quad, all_pixels_inside_quad, ibuf->x, y_range, scene_linear.data(), lum);
1037 [&](
const AreaLuminance &a,
const AreaLuminance &
b) {
1039 res.pixel_count = a.pixel_count +
b.pixel_count;
1040 res.sum = a.sum +
b.sum;
1041 res.color_sum = a.color_sum +
b.color_sum;
1042 res.log_sum = a.log_sum +
b.log_sum;
1068 float maxl =
log(
double(lum.
max) + 1e-5f);
1069 float minl =
log(
double(lum.
min) + 1e-5f);
1071 data.auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.0f;
1072 float al =
exp(
double(avl));
1073 data.al = (al == 0.0f) ? 0.0f : (tmmd->
key / al);
1078 if (ibuf->float_buffer.data != nullptr) {
1081 float4 *pixels = (float4 *)(ibuf->float_buffer.data) + range.first();
1082 if (tmmd->type == SEQ_TONEMAP_RD_PHOTORECEPTOR) {
1083 tonemap_rd_photoreceptor(pixels, mask, range, data);
1086 BLI_assert(tmmd->type == SEQ_TONEMAP_RH_SIMPLE);
1087 tonemap_simple(pixels, mask, range, data);
1089 scene_linear_to_image_chunk_float(ibuf, range);
1093 Array<float4> scene_linear(range.size());
1094 pixels_to_scene_linear_byte(ibuf->byte_buffer.colorspace,
1095 ibuf->byte_buffer.data + range.first() * 4,
1096 scene_linear.data(),
1098 if (tmmd->type == SEQ_TONEMAP_RD_PHOTORECEPTOR) {
1099 tonemap_rd_photoreceptor(scene_linear.data(), mask, range, data);
1102 BLI_assert(tmmd->type == SEQ_TONEMAP_RH_SIMPLE);
1103 tonemap_simple(scene_linear.data(), mask, range, data);
1120 "ColorBalanceModifierData",
1129 "CurvesModifierData",
1138 "HueCorrectModifierData",
1147 "BrightContrastModifierData",
1156 "SequencerMaskModifierData",
1165 "WhiteBalanceModifierData",
1174 "SequencerTonemapModifierData",
1183 "SoundEqualizerModifierData",
1210 if (!name || !name[0]) {
1245 smd_next = smd->
next;
1295 return strip_has_ended_skip || missing_data_skip;
1325 frame_offset = strip->
start;
1328 frame_offset = smd->mask_id ? ((
Mask *)smd->mask_id)->sfra : 0;
1414 if (smd->mask_strip) {
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE int min_iii(int a, int b, int c)
MINLINE float min_fff(float a, float b, float c)
MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
int isect_point_quad_v2(const float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
char * STRNCPY(char(&dst)[N], const char *src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define CTX_N_(context, msgid)
#define BLT_I18NCONTEXT_ID_SEQUENCE
#define CTX_DATA_(context, msgid)
@ SEQUENCE_MODIFIER_EXPANDED
@ SEQUENCE_MASK_INPUT_STRIP
@ NUM_SEQUENCE_MODIFIER_TYPES
@ seqModifierType_SoundEqualizer
@ seqModifierType_HueCorrect
@ SEQ_TONEMAP_RD_PHOTORECEPTOR
@ SEQ_COLOR_BALANCE_METHOD_LIFTGAMMAGAIN
@ SEQ_COLOR_BALANCE_METHOD_SLOPEOFFSETPOWER
@ SEQ_USE_LINEAR_MODIFIERS
@ SEQ_COLOR_BALANCE_INVERSE_GAIN
@ SEQ_COLOR_BALANCE_INVERSE_LIFT
@ SEQ_COLOR_BALANCE_INVERSE_SLOPE
@ SEQ_COLOR_BALANCE_INVERSE_POWER
@ SEQ_COLOR_BALANCE_INVERSE_OFFSET
@ SEQ_COLOR_BALANCE_INVERSE_GAMMA
@ SEQUENCE_MASK_TIME_RELATIVE
void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, const ColorSpace *colorspace, bool predivide)
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
void IMB_colormanagement_scene_linear_to_colorspace(float *buffer, int width, int height, int channels, const ColorSpace *colorspace)
blender::ocio::ColorSpace ColorSpace
void IMB_freeImBuf(ImBuf *ibuf)
static void curves_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
static void curves_init_data(ID *id)
static void curves_free_data(ID *id)
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static void mul(btAlignedObjectArray< T > &items, const Q &value)
constexpr int64_t first() const
constexpr int64_t size() const
blender::gpu::Batch * quad
VecBase< float, 4 > float4
VecBase< float, 3 > float3
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 power(const float2 v, const float e)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
T clamp(const T &a, const T &min, const T &max)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
static void scene_linear_to_image_chunk_float(ImBuf *ibuf, IndexRange range)
static void tonemap_simple(float4 *scene_linear, ImBuf *mask, IndexRange range, const AvgLogLum &avg)
static float load_mask_min(const uchar *&mask)
void seq_imbuf_to_sequencer_space(const Scene *scene, ImBuf *ibuf, bool make_float)
static void whiteBalance_init_data(StripModifierData *smd)
static void colorBalance_init_data(StripModifierData *smd)
static void tonemap_calc_chunk_luminance(const StripScreenQuad &quad, const bool all_pixels_inside_quad, const int width, const IndexRange y_range, const float4 *scene_linear, AreaLuminance &r_lum)
static void colorBalance_apply(const StripScreenQuad &, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
void sound_equalizermodifier_init_data(StripModifierData *smd)
bool media_presence_is_missing(Scene *scene, const Strip *strip)
static void hue_correct_apply(const StripScreenQuad &, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
static constexpr int CB_TABLE_SIZE
static void brightcontrast_apply(const StripScreenQuad &, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
static float color_balance_lgg(float in, const float lift, const float gain, const float gamma, const float mul)
static void tonemapmodifier_init_data(StripModifierData *smd)
static void curves_apply(const StripScreenQuad &, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
static float color_balance_sop(float in, const float slope, const float offset, const float power, float mul)
static void store_pixel_raw(float4 pix, uchar *ptr)
static void store_pixel_premul(float4 pix, uchar *ptr)
void modifier_unique_name(Strip *strip, StripModifierData *smd)
static void hue_correct_init_data(StripModifierData *smd)
StripModifierData * modifier_find_by_name(Strip *strip, const char *name)
static void make_cb_table_sop(float slope, float offset, float power, float mul, float r_table[CB_TABLE_SIZE])
static void whiteBalance_apply(const StripScreenQuad &, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
static void curves_free_data(StripModifierData *smd)
int sequence_supports_modifiers(Strip *strip)
static float4 load_pixel_raw(const uchar *ptr)
static void make_cb_table_lgg(float lift, float gain, float gamma, float mul, float r_table[CB_TABLE_SIZE])
void sound_equalizermodifier_free(StripModifierData *smd)
static StripModifierTypeInfo modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES]
bool strip_has_valid_data(const Strip *strip)
static ImBuf * modifier_mask_get(StripModifierData *smd, const RenderData *context, int timeline_frame, int fra_offset)
void modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
static void maskmodifier_apply(const StripScreenQuad &, StripModifierData *, ImBuf *ibuf, ImBuf *mask)
bool time_strip_intersects_frame(const Scene *scene, const Strip *strip, const int timeline_frame)
void modifier_free(StripModifierData *smd)
bool modifier_remove(Strip *strip, StripModifierData *smd)
const StripModifierTypeInfo * modifier_type_info_get(int type)
StripScreenQuad get_strip_screen_quad(const RenderData *context, const Strip *strip)
static void curves_copy_data(StripModifierData *target, StripModifierData *smd)
void modifier_clear(Strip *strip)
static void pixels_to_scene_linear_float(const ColorSpace *colorspace, float4 *pixels, int64_t count)
void sound_equalizermodifier_copy_data(StripModifierData *target, StripModifierData *smd)
static void tonemapmodifier_apply(const StripScreenQuad &quad, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
static void hue_correct_free_data(StripModifierData *smd)
static void apply_and_advance_mask(float4 input, float4 &result, const uchar *&mask)
StripModifierData * modifier_new(Strip *strip, const char *name, int type)
ImBuf * seq_render_mask(const RenderData *context, Mask *mask, float frame_index, bool make_float)
static float4 load_pixel_premul(const uchar *ptr)
static void curves_init_data(StripModifierData *smd)
static bool is_point_inside_quad(const StripScreenQuad &quad, int x, int y)
static bool skip_modifier(Scene *scene, const StripModifierData *smd, int timeline_frame)
static AreaLuminance tonemap_calc_input_luminance(const StripScreenQuad &quad, const ImBuf *ibuf)
void modifier_list_copy(Strip *strip_new, Strip *strip)
void render_imbuf_from_sequencer_space(const Scene *scene, ImBuf *ibuf)
static void tonemap_rd_photoreceptor(float4 *scene_linear, ImBuf *mask, IndexRange range, const AvgLogLum &avg)
static void hue_correct_copy_data(StripModifierData *target, StripModifierData *smd)
static void pixels_to_scene_linear_byte(const ColorSpace *colorspace, const uchar *pixels, float4 *dst, int64_t count)
static void apply_modifier_op(T &op, ImBuf *ibuf, const ImBuf *mask)
static void scene_linear_to_image_chunk_byte(float4 *src, ImBuf *ibuf, IndexRange range)
void modifier_apply_stack(const RenderData *context, const Strip *strip, ImBuf *ibuf, int timeline_frame)
ImBuf * seq_render_strip(const RenderData *context, SeqRenderState *state, Strip *strip, float timeline_frame)
static ImBuf * modifier_render_mask_input(const RenderData *context, int mask_input_type, Strip *mask_strip, Mask *mask_id, int timeline_frame, int fra_offset)
void modifier_blend_write(BlendWriter *writer, ListBase *modbase)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
static void init(bNodeTree *, bNode *node)
StripColorBalance color_balance
struct CurveMapping curve_mapping
struct CurveMapping curve_mapping
const ColorSpace * colorspace
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
struct StripModifierData * next
struct Strip * mask_strip
VecBase< T, 3 > xyz() const
const SequencerTonemapModifierData * tmmd
void apply(ImageT *image, const MaskT *mask, IndexRange size)
void init_sop(const StripColorBalance &data)
void init_lgg(const StripColorBalance &data)
void apply(uchar *image, const MaskT *mask, IndexRange size)
void apply(float *image, const MaskT *mask, IndexRange size)
float lut[3][CB_TABLE_SIZE]
void init(const ColorBalanceModifierData &data, bool byte_image)
const CurveMapping * curve_mapping
void apply(ImageT *image, const MaskT *mask, IndexRange size)
const CurveMapping * curve_mapping
void apply(ImageT *image, const MaskT *mask, IndexRange size)
void apply(ImageT *image, const MaskT *mask, IndexRange size)
void(* free_data)(StripModifierData *smd)
void(* init_data)(StripModifierData *smd)
void(* copy_data)(StripModifierData *smd, StripModifierData *target)
void(* apply)(const StripScreenQuad &quad, StripModifierData *smd, ImBuf *ibuf, ImBuf *mask)
void apply(ImageT *image, const MaskT *mask, IndexRange size)