From daf6f5f81e241484ea8afc5d70ef3027969e5ac1 Mon Sep 17 00:00:00 2001 From: Thomas Beck Date: Mon, 28 Dec 2015 11:55:14 +0100 Subject: 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 --- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/intern/seqmodifier.c | 87 +++++++++++++++++++++- source/blender/blenloader/intern/readfile.c | 1 + source/blender/blenloader/intern/versioning_260.c | 2 +- .../editors/space_sequencer/sequencer_modifier.c | 2 +- source/blender/makesdna/DNA_sequence_types.h | 11 ++- source/blender/makesrna/intern/rna_sequencer.c | 22 +++++- 7 files changed, 121 insertions(+), 6 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 3f2712e0ae1..4582d113941 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -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); diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 07242aa2f6e..f12faacd677 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -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)); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 30faa3709ba..a3bf673d5fa 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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; } } diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 77a4aefb7ac..027c3eb9fbf 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -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; diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index 5d4ea47452e..713e1618e39 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -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); diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index e5c102b1d2d..bb49419b2ac 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -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 }; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 1fb57fc1d11..d9d56adffae 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -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) -- cgit v1.2.3