White Balance modifier for the VSE

This snippet creates a white balance modifier for the video sequence editor. It is useful for everyone who likes to set a new white point in the video source (easily via the eyedropper). Just select a point in the source file where you know that it should be white. The algorithm will then shift the colors towards your new white point.

See attached the image for a quick demo.

{F270576}

Reviewers: psy-fi

Reviewed By: psy-fi

Subscribers: Blendify

Projects: #bf_blender

Differential Revision: https://developer.blender.org/D1698
This commit is contained in:
Thomas Beck 2015-12-28 11:55:14 +01:00
parent 225b02fcd6
commit daf6f5f81e
8 changed files with 124 additions and 7 deletions

View File

@ -1125,7 +1125,9 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
col = box.column()
col.prop(mod, "bright")
col.prop(mod, "contrast")
elif mod.type == 'WHITE_BALANCE':
col = box.column()
col.prop(mod, "white_value")
class SEQUENCER_PT_grease_pencil(GreasePencilDataPanel, SequencerButtonsPanel_Output, Panel):
bl_space_type = 'SEQUENCE_EDITOR'

View File

@ -458,7 +458,7 @@ typedef struct SequenceModifierTypeInfo {
const struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type);
struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, const char *name, int type);
struct SequenceModifierData *BKE_sequence_modifier_new(struct Sequence *seq, const char *name, int type, struct Scene *scene);
bool BKE_sequence_modifier_remove(struct Sequence *seq, struct SequenceModifierData *smd);
void BKE_sequence_modifier_clear(struct Sequence *seq);
void BKE_sequence_modifier_free(struct SequenceModifierData *smd);

View File

@ -42,12 +42,14 @@
#include "BLT_translation.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
#include "BKE_colortools.h"
#include "BKE_sequencer.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES];
static bool modifierTypesInit = false;
@ -173,6 +175,87 @@ static SequenceModifierTypeInfo seqModifier_ColorBalance = {
colorBalance_apply /* apply */
};
/* **** White Balance Modifier **** */
static void whiteBalance_init_data(SequenceModifierData *smd)
{
WhiteBalanceModifierData *cbmd = (WhiteBalanceModifierData *) smd;
copy_v3_fl(cbmd->white_value, 1.0f);
}
typedef struct WhiteBalanceThreadData {
struct ColorSpace* colorspace;
float white[3];
} WhiteBalanceThreadData;
static void whiteBalance_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
int x, y;
float multiplier[3];
WhiteBalanceThreadData *data = (WhiteBalanceThreadData *) data_v;
multiplier[0] = 1.0f/data->white[0];
multiplier[1] = 1.0f/data->white[1];
multiplier[2] = 1.0f/data->white[2];
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int pixel_index = (y * width + x) * 4;
float result[3], mask[3] = {1.0f, 1.0f, 1.0f};
if (rect_float)
copy_v3_v3(result, rect_float + pixel_index);
else
{
straight_uchar_to_premul_float(result, rect + pixel_index);
IMB_colormanagement_colorspace_to_scene_linear_v3(result, data->colorspace);
}
mul_v3_v3(result, multiplier);
if (mask_rect_float)
copy_v3_v3(mask, mask_rect_float + pixel_index);
else if (mask_rect)
rgb_uchar_to_float(mask, mask_rect + pixel_index);
result[0] = result[0] * (1.0f - mask[0]) + result[0] * mask[0];
result[1] = result[1] * (1.0f - mask[1]) + result[1] * mask[1];
result[2] = result[2] * (1.0f - mask[2]) + result[2] * mask[2];
if (rect_float)
copy_v3_v3(rect_float + pixel_index, result);
else
IMB_colormanagement_scene_linear_to_colorspace_v3(result, data->colorspace);
premul_float_to_straight_uchar(rect + pixel_index, result);
}
}
}
static void whiteBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
{
WhiteBalanceThreadData data;
WhiteBalanceModifierData *wbmd = (WhiteBalanceModifierData *) smd;
copy_v3_v3(data.white, wbmd->white_value);
IMB_colormanagement_display_to_scene_linear_v3(data.white,
IMB_colormanagement_display_get_named(wbmd->modifier.scene->display_settings.display_device));
data.colorspace = ibuf->rect_colorspace;
modifier_apply_threaded(ibuf, mask, whiteBalance_apply_threaded, &data);
}
static SequenceModifierTypeInfo seqModifier_WhiteBalance = {
CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "White Balance"), /* name */
"WhiteBalanceModifierData", /* struct_name */
sizeof(WhiteBalanceModifierData), /* struct_size */
whiteBalance_init_data, /* init_data */
NULL, /* free_data */
NULL, /* copy_data */
whiteBalance_apply /* apply */
};
/* **** Curves Modifier **** */
static void curves_init_data(SequenceModifierData *smd)
@ -559,6 +642,7 @@ static void sequence_modifier_type_info_init(void)
INIT_TYPE(HueCorrect);
INIT_TYPE(BrightContrast);
INIT_TYPE(Mask);
INIT_TYPE(WhiteBalance);
#undef INIT_TYPE
}
@ -573,7 +657,7 @@ const SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
return modifiersTypes[type];
}
SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type)
SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type, struct Scene *scene)
{
SequenceModifierData *smd;
const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type);
@ -582,6 +666,7 @@ SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name,
smd->type = type;
smd->flag |= SEQUENCE_MODIFIER_EXPANDED;
smd->scene = scene;
if (!name || !name[0])
BLI_strncpy(smd->name, smti->name, sizeof(smd->name));

View File

@ -5486,6 +5486,7 @@ static void lib_link_sequence_modifiers(FileData *fd, Scene *scene, ListBase *lb
for (smd = lb->first; smd; smd = smd->next) {
if (smd->mask_id)
smd->mask_id = newlibadr_us(fd, scene->id.lib, smd->mask_id);
smd->scene = scene;
}
}

View File

@ -1503,7 +1503,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
SequenceModifierData *smd;
ColorBalanceModifierData *cbmd;
smd = BKE_sequence_modifier_new(seq, NULL, seqModifierType_ColorBalance);
smd = BKE_sequence_modifier_new(seq, NULL, seqModifierType_ColorBalance, scene);
cbmd = (ColorBalanceModifierData *) smd;
cbmd->color_balance = *strip->color_balance;

View File

@ -71,7 +71,7 @@ static int strip_modifier_add_exec(bContext *C, wmOperator *op)
Sequence *seq = BKE_sequencer_active_get(scene);
int type = RNA_enum_get(op->ptr, "type");
BKE_sequence_modifier_new(seq, NULL, type);
BKE_sequence_modifier_new(seq, NULL, type, scene);
BKE_sequence_invalidate_cache(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);

View File

@ -307,11 +307,12 @@ typedef struct SequenceModifierData {
int type, flag;
char name[64]; /* MAX_NAME */
/* mask input, either sequence or maks ID */
/* mask input, either sequence or mask ID */
int mask_input_type, pad;
struct Sequence *mask_sequence;
struct Mask *mask_id;
struct Scene *scene;
} SequenceModifierData;
typedef struct ColorBalanceModifierData {
@ -344,6 +345,13 @@ typedef struct SequencerMaskModifierData {
SequenceModifierData modifier;
} SequencerMaskModifierData;
typedef struct WhiteBalanceModifierData {
SequenceModifierData modifier;
float white_value[3];
float pad;
} WhiteBalanceModifierData;
/* ***************** Scopes ****************** */
typedef struct SequencerScopes {
@ -519,6 +527,7 @@ enum {
seqModifierType_HueCorrect = 3,
seqModifierType_BrightContrast = 4,
seqModifierType_Mask = 5,
seqModifierType_WhiteBalance = 6,
NUM_SEQUENCE_MODIFIER_TYPES
};

View File

@ -66,6 +66,7 @@ EnumPropertyItem rna_enum_sequence_modifier_type_items[] = {
{seqModifierType_HueCorrect, "HUE_CORRECT", ICON_NONE, "Hue Correct", ""},
{seqModifierType_BrightContrast, "BRIGHT_CONTRAST", ICON_NONE, "Bright/Contrast", ""},
{seqModifierType_Mask, "MASK", ICON_NONE, "Mask", ""},
{seqModifierType_WhiteBalance, "WHITE_BALANCE", ICON_NONE, "White Balance", ""},
{0, NULL, 0, NULL, NULL}
};
@ -955,6 +956,8 @@ static StructRNA *rna_SequenceModifier_refine(struct PointerRNA *ptr)
return &RNA_HueCorrectModifier;
case seqModifierType_BrightContrast:
return &RNA_BrightContrastModifier;
case seqModifierType_WhiteBalance:
return &RNA_WhiteBalanceModifier;
default:
return &RNA_SequenceModifier;
}
@ -1043,7 +1046,7 @@ static SequenceModifierData *rna_Sequence_modifier_new(Sequence *seq, bContext *
Scene *scene = CTX_data_scene(C);
SequenceModifierData *smd;
smd = BKE_sequence_modifier_new(seq, name, type);
smd = BKE_sequence_modifier_new(seq, name, type, scene);
BKE_sequence_invalidate_cache_for_modifier(scene, seq);
@ -2496,6 +2499,22 @@ static void rna_def_colorbalance_modifier(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
}
static void rna_def_whitebalance_modifier(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "WhiteBalanceModifier", "SequenceModifier");
RNA_def_struct_sdna(srna, "WhiteBalanceModifierData");
RNA_def_struct_ui_text(srna, "WhiteBalanceModifier", "White balance modifier for sequence strip");
prop = RNA_def_property(srna, "white_value", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "white_value");
RNA_def_property_ui_text(prop, "White value", "This color defines white in the strip");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
}
static void rna_def_curves_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@ -2558,6 +2577,7 @@ static void rna_def_modifiers(BlenderRNA *brna)
rna_def_curves_modifier(brna);
rna_def_hue_modifier(brna);
rna_def_brightcontrast_modifier(brna);
rna_def_whitebalance_modifier(brna);
}
void RNA_def_sequencer(BlenderRNA *brna)