Skip to content

Commit

Permalink
falsecolor: Add option to load LUT
Browse files Browse the repository at this point in the history
  • Loading branch information
norihiro committed Jul 15, 2024
1 parent e7cd26f commit c9140e8
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 15 deletions.
16 changes: 14 additions & 2 deletions data/falsecolor.effect
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
uniform float4x4 ViewProj;
uniform texture2d image;
uniform bool use_lut;
uniform texture2d lut;

sampler_state def_sampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};

sampler_state lut_sampler {
Filter = Point;
AddressU = Clamp;
AddressV = Clamp;
};

struct VertInOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
Expand All @@ -25,7 +33,9 @@ float4 PSDrawFalseColor601(VertInOut vert_in) : TARGET
float4 rgba = image.Sample(def_sampler, vert_in.uv);
float y = dot(rgba.xyz, float3(0.299000, 0.587000, 0.114000));

if (y < 0.02)
if (use_lut)
return lut.Sample(lut_sampler, float2(y, 0.5));
else if (y < 0.02)
return float4(0.85, 0.22, 1.0, 1.0); // bright purple
else if (y < 0.10)
return float4(0.0, 0.0, 1.0, 1.0); // blue
Expand Down Expand Up @@ -56,7 +66,9 @@ float4 PSDrawFalseColor709(VertInOut vert_in) : TARGET
float4 rgba = image.Sample(def_sampler, vert_in.uv);
float y = dot(rgba.xyz, float3(0.212600, 0.715200, 0.072200));

if (y < 0.02)
if (use_lut)
return lut.Sample(lut_sampler, float2(y, 0.5));
else if (y < 0.02)
return float4(0.85, 0.22, 1.0, 1.0); // bright purple
else if (y < 0.10)
return float4(0.0, 0.0, 1.0, 1.0); // blue
Expand Down
4 changes: 4 additions & 0 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ Source="Source"
Stack="Stack"
"Threshold (high)"="Threshold (high)"
"Threshold (lower)"="Threshold (lower)"
FalseColor.Prop.LUT="Use LUT"
FalseColor.Prop.LUTFile="LUT file name"
FalseColor.Prop.LUTFile.Filter.Image="All image files"
FalseColor.Prop.LUTFile.Filter.All="All files"
"Top level"="Top level"
Vectorscope="Vectorscope"
Waveform="Waveform"
Expand Down
11 changes: 10 additions & 1 deletion doc/falsecolor.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,19 @@ RGB color `#000000` corresponds to 0&nbsp;IRE `#FFFFFF` corresponds to 100&nbsp;
Selects one of Program, Main view, Preview, Scene, or Source.
The default is Program.

### Use LUT

Enable if you want to customize the color map.

### LUT file name

If 'Use LUT' is enabled, choose an image file for the color map.
The image file should be 1-pixel height and can have any width.
The left most pixel represents the black and the right most pixel represents the white.

### Color space

Choice of color space; Auto, BT.601, or BT.709.
If Auto, the color space is retrieved from the settings of OBS Studio.
Coefficients to convert from RGB to Luminance will be changed.
Default is Auto.

98 changes: 86 additions & 12 deletions src/zebra.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <obs-module.h>
#include <util/platform.h>
#include <util/dstr.h>
#include <graphics/image-file.h>
#include "plugin-macros.generated.h"
#include "common.h"
#include "util.h"
Expand All @@ -19,6 +21,8 @@ struct zb_source
gs_effect_t *effect;
float zebra_th_low, zebra_th_high;
float zebra_tm;
char *falsecolor_lut_filename;
gs_image_file_t falsecolor_lut;
bool is_falsecolor;
};

Expand Down Expand Up @@ -109,24 +113,71 @@ static void *fcf_create(obs_data_t *settings, obs_source_t *source)
return src;
}

static void falsecolor_lut_unload(struct zb_source *src)
{
if (!src->falsecolor_lut.loaded)
return;
obs_enter_graphics();
gs_image_file_free(&src->falsecolor_lut);
obs_leave_graphics();
}

static void zb_destroy(struct zb_source *src)
{
if (src->is_falsecolor) {
falsecolor_lut_unload(src);
bfree(src->falsecolor_lut_filename);
}
}

static void zbs_destroy(void *data)
{
struct zbs_source *src = data;

cm_destroy(&src->cm);
zb_destroy(&src->zb);
bfree(src);
}

static void zbf_destroy(void *data)
{
struct zbf_source *src = data;
zb_destroy(&src->zb);
bfree(src);
}

static void falsecolor_lut_load(struct zb_source *src, const char *lut_filename)
{
falsecolor_lut_unload(src);

blog(LOG_INFO, "Loading LUT file '%s'...", lut_filename);
gs_image_file_init(&src->falsecolor_lut, lut_filename);

obs_enter_graphics();
gs_image_file_init_texture(&src->falsecolor_lut);
obs_leave_graphics();
}

static void zb_update(struct zb_source *src, obs_data_t *settings)
{
src->zebra_th_low = obs_data_get_int(settings, "zebra_th_low") * 1e-2f;
src->zebra_th_high = obs_data_get_int(settings, "zebra_th_high") * 1e-2f;
if (!src->is_falsecolor) {
/* zebra */
src->zebra_th_low = obs_data_get_int(settings, "zebra_th_low") * 1e-2f;
src->zebra_th_high = obs_data_get_int(settings, "zebra_th_high") * 1e-2f;
} else {
/* falsecolor */
bool lut = obs_data_get_bool(settings, "falsecolor_lut");
const char *lut_filename = lut ? obs_data_get_string(settings, "falsecolor_lut_filename") : NULL;
if (!lut_filename) {
falsecolor_lut_unload(src);
bfree(src->falsecolor_lut_filename);
src->falsecolor_lut_filename = NULL;
} else if (!src->falsecolor_lut_filename || strcmp(lut_filename, src->falsecolor_lut_filename) != 0) {
falsecolor_lut_load(src, lut_filename);
bfree(src->falsecolor_lut_filename);
src->falsecolor_lut_filename = bstrdup(lut_filename);
}
}
}

static void zbs_update(void *data, obs_data_t *settings)
Expand Down Expand Up @@ -156,10 +207,22 @@ static void zb_get_properties(obs_properties_t *props, bool is_falsecolor)
obs_property_t *prop;

if (!is_falsecolor) {
/* zebra */
prop = obs_properties_add_int(props, "zebra_th_low", obs_module_text("Threshold (lower)"), 50, 100, 1);
obs_property_int_set_suffix(prop, "%");
prop = obs_properties_add_int(props, "zebra_th_high", obs_module_text("Threshold (high)"), 50, 100, 1);
obs_property_int_set_suffix(prop, "%");
} else {
/* falsecolor */
struct dstr filename_filters = {0};
dstr_copy(&filename_filters, obs_module_text("FalseColor.Prop.LUTFile.Filter.Image"));
dstr_copy(&filename_filters, " (*.bmp *.jpg *.jpeg *.tga *.gif *.png);;");
dstr_copy(&filename_filters, obs_module_text("FalseColor.Prop.LUTFile.Filter.All"));
dstr_copy(&filename_filters, " (*.*)");
obs_properties_add_bool(props, "falsecolor_lut", obs_module_text("FalseColor.Prop.LUT"));
obs_properties_add_path(props, "falsecolor_lut_filename", obs_module_text("FalseColor.Prop.LUTFile"),
OBS_PATH_FILE, filename_filters.array, NULL);
dstr_free(&filename_filters);
}

properties_add_colorspace(props, "colorspace", obs_module_text("Color space"));
Expand Down Expand Up @@ -235,6 +298,25 @@ const char *draw_name(int colorspace, bool is_falsecolor)
return "DrawZebra709";
}

static void set_effect_params(struct zb_source *src)
{
gs_effect_t *e = src->effect;

if (!src->is_falsecolor) {
/* zebra */
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_th_low"), src->zebra_th_low);
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_th_high"), src->zebra_th_high);
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_tm"), src->zebra_tm);
}
else {
/* falsecolor */
gs_texture_t *lut = src->falsecolor_lut.texture;
gs_effect_set_bool(gs_effect_get_param_by_name(e, "use_lut"), !!lut);
if (lut)
gs_effect_set_texture(gs_effect_get_param_by_name(e, "lut"), lut);
}
}

static void zbs_render(void *data, gs_effect_t *effect)
{
UNUSED_PARAMETER(effect);
Expand All @@ -255,11 +337,7 @@ static void zbs_render(void *data, gs_effect_t *effect)
uint32_t cy = cm_bypass_get_height(&src->cm);

gs_effect_set_texture(gs_effect_get_param_by_name(e, "image"), tex);
if (!src->zb.is_falsecolor) {
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_th_low"), src->zb.zebra_th_low);
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_th_high"), src->zb.zebra_th_high);
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_tm"), src->zb.zebra_tm);
}
set_effect_params(&src->zb);
const char *draw = draw_name(src->cm.colorspace, src->zb.is_falsecolor);
while (gs_effect_loop(e, draw))
gs_draw_sprite_subregion(tex, 0, 0, 0, cx, cy);
Expand All @@ -280,11 +358,7 @@ static void zbf_render(void *data, gs_effect_t *effect)
if (!obs_source_process_filter_begin(src->context, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING))
return;

if (!src->zb.is_falsecolor) {
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_th_low"), src->zb.zebra_th_low);
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_th_high"), src->zb.zebra_th_high);
gs_effect_set_float(gs_effect_get_param_by_name(e, "zebra_tm"), src->zb.zebra_tm);
}
set_effect_params(&src->zb);

gs_blend_state_push();
gs_reset_blend_state();
Expand Down

0 comments on commit c9140e8

Please sign in to comment.