Add "Area" scale filter
This new scale filter computes pixels by weighing the coverage area of source pixels over the target pixel. This algorithm works well for both upsampling and downsampling, but was mainly designed to upscale high-quality low-resolution sources like RGB/HDMI retro consoles. I've heard of people using odd workarounds like scaling up to very high resolutions before scaling back down to preserve pixel shartpness. This algorithm directly addresses this use-case in a much more direct fashion. The Area scale filter does a better job of preserving the thickness of thin features than the Point filter. The Area scale filter does not look at source pixels that lie outside of the target pixel, leading to a much sharper image than Bilinear, Bicubic, and Lanczos filters. This filter should interpolate pixels in linear space, but OBS is not equipped to do that at the moment. libobs: Add GPU effect, and wire up scene serialization. obs-filters: Add Area as an option for scale_filter. UI: Add Area as an option for both scene items, and canvas downscaling.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#define T_SAMPLING_BILINEAR obs_module_text("ScaleFiltering.Bilinear")
|
||||
#define T_SAMPLING_BICUBIC obs_module_text("ScaleFiltering.Bicubic")
|
||||
#define T_SAMPLING_LANCZOS obs_module_text("ScaleFiltering.Lanczos")
|
||||
#define T_SAMPLING_AREA obs_module_text("ScaleFiltering.Area")
|
||||
#define T_UNDISTORT obs_module_text("UndistortCenter")
|
||||
#define T_BASE obs_module_text("Base.Canvas")
|
||||
|
||||
@@ -24,6 +25,7 @@
|
||||
#define S_SAMPLING_BILINEAR "bilinear"
|
||||
#define S_SAMPLING_BICUBIC "bicubic"
|
||||
#define S_SAMPLING_LANCZOS "lanczos"
|
||||
#define S_SAMPLING_AREA "area"
|
||||
|
||||
struct scale_filter_data {
|
||||
obs_source_t *context;
|
||||
@@ -95,6 +97,9 @@ static void scale_filter_update(void *data, obs_data_t *settings)
|
||||
} else if (astrcmpi(sampling, S_SAMPLING_LANCZOS) == 0) {
|
||||
filter->sampling = OBS_SCALE_LANCZOS;
|
||||
|
||||
} else if (astrcmpi(sampling, S_SAMPLING_AREA) == 0) {
|
||||
filter->sampling = OBS_SCALE_AREA;
|
||||
|
||||
} else { /* S_SAMPLING_BICUBIC */
|
||||
filter->sampling = OBS_SCALE_BICUBIC;
|
||||
}
|
||||
@@ -218,6 +223,7 @@ static void scale_filter_tick(void *data, float seconds)
|
||||
case OBS_SCALE_BILINEAR: type = OBS_EFFECT_DEFAULT; break;
|
||||
case OBS_SCALE_BICUBIC: type = OBS_EFFECT_BICUBIC; break;
|
||||
case OBS_SCALE_LANCZOS: type = OBS_EFFECT_LANCZOS; break;
|
||||
case OBS_SCALE_AREA: type = OBS_EFFECT_AREA; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,15 +315,15 @@ static bool sampling_modified(obs_properties_t *props, obs_property_t *p,
|
||||
bool has_undistort;
|
||||
if (astrcmpi(sampling, S_SAMPLING_POINT) == 0) {
|
||||
has_undistort = false;
|
||||
|
||||
}
|
||||
else if (astrcmpi(sampling, S_SAMPLING_BILINEAR) == 0) {
|
||||
has_undistort = false;
|
||||
|
||||
}
|
||||
else if (astrcmpi(sampling, S_SAMPLING_LANCZOS) == 0) {
|
||||
has_undistort = true;
|
||||
|
||||
}
|
||||
else if (astrcmpi(sampling, S_SAMPLING_AREA) == 0) {
|
||||
has_undistort = false;
|
||||
}
|
||||
else { /* S_SAMPLING_BICUBIC */
|
||||
has_undistort = true;
|
||||
@@ -360,6 +366,7 @@ static obs_properties_t *scale_filter_properties(void *data)
|
||||
obs_property_list_add_string(p, T_SAMPLING_BILINEAR, S_SAMPLING_BILINEAR);
|
||||
obs_property_list_add_string(p, T_SAMPLING_BICUBIC, S_SAMPLING_BICUBIC);
|
||||
obs_property_list_add_string(p, T_SAMPLING_LANCZOS, S_SAMPLING_LANCZOS);
|
||||
obs_property_list_add_string(p, T_SAMPLING_AREA, S_SAMPLING_AREA);
|
||||
|
||||
/* ----------------- */
|
||||
|
||||
|
Reference in New Issue
Block a user