coefficients was used.\r
o Rewrote the chroma key code to support variable hue, instead of fixed green\r
or blue. Threshold setting was removed in favour of separate hue width,\r
- minimum saturation and minimum brightness constraints.\r
+ minimum saturation and minimum brightness constraints. Also a much more\r
+ effective spill suppression method was implemented.\r
o Fixed bug where glReadPixels() was done from the last drawn to texture\r
instead of always from the target texture. This means that for example a\r
MIXER KEYER layer without a layer above to key, as well as a separate alpha\r
return 1.0 - smoothstep(1.0, chroma_softness, d);
}
- vec4 supress_spill(vec4 c, float d)
- {
- float ds = smoothstep(chroma_spill, clamp(chroma_spill + 0.2, 0, 1), d / chroma_softness);
- float gl = dot(grey_xfer, c);
- return mix(c, vec4(vec3(pow(gl, chroma_spill_darken)), gl), ds);
- }
-
// http://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl
vec3 rgb2hsv(vec3 c)
{
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
+ // From the same page
+ vec3 hsv2rgb(vec3 c)
+ {
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+ }
+
float AngleDiff(float angle1, float angle2)
{
return 0.5 - abs(abs(angle1 - angle2) - 0.5);
}
+ float AngleDiffDirectional(float angle1, float angle2)
+ {
+ float diff = angle1 - angle2;
+
+ return diff < -0.5
+ ? diff + 1.0
+ : (diff > 0.5 ? diff - 1.0 : diff);
+ }
+
float Distance(float actual, float target)
{
return min(0.0, target - actual);
return -hueScore * saturationBrightnessScore;
}
+ vec3 supress_spill(vec3 c)
+ {
+ float hue = c.x;
+ float diff = AngleDiffDirectional(hue, chroma_target_hue);
+ float distance = abs(diff) / chroma_spill_suppress;
+
+ if (distance < 1)
+ {
+ c.x = diff < 0
+ ? chroma_target_hue - chroma_spill_suppress
+ : chroma_target_hue + chroma_spill_suppress;
+ c.y *= min(1.0, distance + chroma_spill_suppress_saturation);
+ }
+
+ return c;
+ }
+
// Key on any color
vec4 ChromaOnCustomColor(vec4 c)
{
vec3 hsv = rgb2hsv(c.rgb);
float distance = ColorDistance(hsv);
float d = distance * -2.0 + 1.0;
- vec4 suppressed = supress_spill(c.rgba, d).rgba;
+ vec4 suppressed = vec4(hsv2rgb(supress_spill(hsv)), 1.0);
float alpha = alpha_map(d);
suppressed *= alpha;
{
shader_->set("chroma", true);
- shader_->set("chroma_show_mask", params.transform.chroma.show_mask);
- shader_->set("chroma_target_hue", params.transform.chroma.target_hue / 360.0);
- shader_->set("chroma_hue_width", params.transform.chroma.hue_width);
- shader_->set("chroma_min_saturation", params.transform.chroma.min_saturation);
- shader_->set("chroma_min_brightness", params.transform.chroma.min_brightness);
- shader_->set("chroma_softness", 1.0 + params.transform.chroma.softness);
- shader_->set("chroma_spill", params.transform.chroma.spill);
- shader_->set("chroma_spill_darken", params.transform.chroma.spill_darken);
+ shader_->set("chroma_show_mask", params.transform.chroma.show_mask);
+ shader_->set("chroma_target_hue", params.transform.chroma.target_hue / 360.0);
+ shader_->set("chroma_hue_width", params.transform.chroma.hue_width);
+ shader_->set("chroma_min_saturation", params.transform.chroma.min_saturation);
+ shader_->set("chroma_min_brightness", params.transform.chroma.min_brightness);
+ shader_->set("chroma_softness", 1.0 + params.transform.chroma.softness);
+ shader_->set("chroma_spill_suppress", params.transform.chroma.spill_suppress / 360.0);
+ shader_->set("chroma_spill_suppress_saturation", params.transform.chroma.spill_suppress_saturation);
}
else
shader_->set("chroma", false);
uniform float chroma_min_saturation;
uniform float chroma_min_brightness;
uniform float chroma_softness;
- uniform float chroma_spill;
- uniform float chroma_spill_darken;
+ uniform float chroma_spill_suppress;
+ uniform float chroma_spill_suppress_saturation;
)shader"
+
transform_rect(crop, other.crop);
transform_corners(perspective, other.perspective);
- levels.min_input = std::max(levels.min_input, other.levels.min_input);
- levels.max_input = std::min(levels.max_input, other.levels.max_input);
- levels.min_output = std::max(levels.min_output, other.levels.min_output);
- levels.max_output = std::min(levels.max_output, other.levels.max_output);
- levels.gamma *= other.levels.gamma;
- chroma.enable |= other.chroma.enable;
- chroma.show_mask |= other.chroma.show_mask;
- chroma.target_hue = std::max(other.chroma.target_hue, chroma.target_hue);
- chroma.min_saturation = std::max(other.chroma.min_saturation, chroma.min_saturation);
- chroma.min_brightness = std::max(other.chroma.min_brightness, chroma.min_brightness);
- chroma.hue_width = std::max(other.chroma.hue_width, chroma.hue_width);
- chroma.softness = std::max(other.chroma.softness, chroma.softness);
- chroma.spill = std::min(other.chroma.spill, chroma.spill);
- chroma.spill_darken = std::max(other.chroma.spill_darken, chroma.spill_darken);
- field_mode = field_mode & other.field_mode;
- is_key |= other.is_key;
- is_mix |= other.is_mix;
- is_still |= other.is_still;
- use_mipmap |= other.use_mipmap;
- blend_mode = std::max(blend_mode, other.blend_mode);
- layer_depth += other.layer_depth;
+ levels.min_input = std::max(levels.min_input, other.levels.min_input);
+ levels.max_input = std::min(levels.max_input, other.levels.max_input);
+ levels.min_output = std::max(levels.min_output, other.levels.min_output);
+ levels.max_output = std::min(levels.max_output, other.levels.max_output);
+ levels.gamma *= other.levels.gamma;
+ chroma.enable |= other.chroma.enable;
+ chroma.show_mask |= other.chroma.show_mask;
+ chroma.target_hue = std::max(other.chroma.target_hue, chroma.target_hue);
+ chroma.min_saturation = std::max(other.chroma.min_saturation, chroma.min_saturation);
+ chroma.min_brightness = std::max(other.chroma.min_brightness, chroma.min_brightness);
+ chroma.hue_width = std::max(other.chroma.hue_width, chroma.hue_width);
+ chroma.softness = std::max(other.chroma.softness, chroma.softness);
+ chroma.spill_suppress = std::max(other.chroma.spill_suppress, chroma.spill_suppress);
+ chroma.spill_suppress_saturation = std::min(other.chroma.spill_suppress_saturation, chroma.spill_suppress_saturation);
+ field_mode = field_mode & other.field_mode;
+ is_key |= other.is_key;
+ is_mix |= other.is_mix;
+ is_still |= other.is_still;
+ use_mipmap |= other.use_mipmap;
+ blend_mode = std::max(blend_mode, other.blend_mode);
+ layer_depth += other.layer_depth;
return *this;
}
{
image_transform result;
- result.brightness = do_tween(time, source.brightness, dest.brightness, duration, tween);
- result.contrast = do_tween(time, source.contrast, dest.contrast, duration, tween);
- result.saturation = do_tween(time, source.saturation, dest.saturation, duration, tween);
- result.opacity = do_tween(time, source.opacity, dest.opacity, duration, tween);
- result.anchor[0] = do_tween(time, source.anchor[0], dest.anchor[0], duration, tween);
- result.anchor[1] = do_tween(time, source.anchor[1], dest.anchor[1], duration, tween);
- result.fill_translation[0] = do_tween(time, source.fill_translation[0], dest.fill_translation[0], duration, tween);
- result.fill_translation[1] = do_tween(time, source.fill_translation[1], dest.fill_translation[1], duration, tween);
- result.fill_scale[0] = do_tween(time, source.fill_scale[0], dest.fill_scale[0], duration, tween);
- result.fill_scale[1] = do_tween(time, source.fill_scale[1], dest.fill_scale[1], duration, tween);
- result.clip_translation[0] = do_tween(time, source.clip_translation[0], dest.clip_translation[0], duration, tween);
- result.clip_translation[1] = do_tween(time, source.clip_translation[1], dest.clip_translation[1], duration, tween);
- result.clip_scale[0] = do_tween(time, source.clip_scale[0], dest.clip_scale[0], duration, tween);
- result.clip_scale[1] = do_tween(time, source.clip_scale[1], dest.clip_scale[1], duration, tween);
- result.angle = do_tween(time, source.angle, dest.angle, duration, tween);
- result.levels.max_input = do_tween(time, source.levels.max_input, dest.levels.max_input, duration, tween);
- result.levels.min_input = do_tween(time, source.levels.min_input, dest.levels.min_input, duration, tween);
- result.levels.max_output = do_tween(time, source.levels.max_output, dest.levels.max_output, duration, tween);
- result.levels.min_output = do_tween(time, source.levels.min_output, dest.levels.min_output, duration, tween);
- result.levels.gamma = do_tween(time, source.levels.gamma, dest.levels.gamma, duration, tween);
- result.chroma.target_hue = do_tween(time, source.chroma.target_hue, dest.chroma.target_hue, duration, tween);
- result.chroma.hue_width = do_tween(time, source.chroma.hue_width, dest.chroma.hue_width, duration, tween);
- result.chroma.min_saturation = do_tween(time, source.chroma.min_saturation, dest.chroma.min_saturation, duration, tween);
- result.chroma.min_brightness = do_tween(time, source.chroma.min_brightness, dest.chroma.min_brightness, duration, tween);
- result.chroma.softness = do_tween(time, source.chroma.softness, dest.chroma.softness, duration, tween);
- result.chroma.spill = do_tween(time, source.chroma.spill, dest.chroma.spill, duration, tween);
- result.chroma.spill_darken = do_tween(time, source.chroma.spill_darken, dest.chroma.spill_darken, duration, tween);
- result.chroma.enable = dest.chroma.enable;
- result.chroma.show_mask = dest.chroma.show_mask;
- result.field_mode = source.field_mode & dest.field_mode;
- result.is_key = source.is_key | dest.is_key;
- result.is_mix = source.is_mix | dest.is_mix;
- result.is_still = source.is_still | dest.is_still;
- result.use_mipmap = source.use_mipmap | dest.use_mipmap;
- result.blend_mode = std::max(source.blend_mode, dest.blend_mode);
- result.layer_depth = dest.layer_depth;
+ result.brightness = do_tween(time, source.brightness, dest.brightness, duration, tween);
+ result.contrast = do_tween(time, source.contrast, dest.contrast, duration, tween);
+ result.saturation = do_tween(time, source.saturation, dest.saturation, duration, tween);
+ result.opacity = do_tween(time, source.opacity, dest.opacity, duration, tween);
+ result.anchor[0] = do_tween(time, source.anchor[0], dest.anchor[0], duration, tween);
+ result.anchor[1] = do_tween(time, source.anchor[1], dest.anchor[1], duration, tween);
+ result.fill_translation[0] = do_tween(time, source.fill_translation[0], dest.fill_translation[0], duration, tween);
+ result.fill_translation[1] = do_tween(time, source.fill_translation[1], dest.fill_translation[1], duration, tween);
+ result.fill_scale[0] = do_tween(time, source.fill_scale[0], dest.fill_scale[0], duration, tween);
+ result.fill_scale[1] = do_tween(time, source.fill_scale[1], dest.fill_scale[1], duration, tween);
+ result.clip_translation[0] = do_tween(time, source.clip_translation[0], dest.clip_translation[0], duration, tween);
+ result.clip_translation[1] = do_tween(time, source.clip_translation[1], dest.clip_translation[1], duration, tween);
+ result.clip_scale[0] = do_tween(time, source.clip_scale[0], dest.clip_scale[0], duration, tween);
+ result.clip_scale[1] = do_tween(time, source.clip_scale[1], dest.clip_scale[1], duration, tween);
+ result.angle = do_tween(time, source.angle, dest.angle, duration, tween);
+ result.levels.max_input = do_tween(time, source.levels.max_input, dest.levels.max_input, duration, tween);
+ result.levels.min_input = do_tween(time, source.levels.min_input, dest.levels.min_input, duration, tween);
+ result.levels.max_output = do_tween(time, source.levels.max_output, dest.levels.max_output, duration, tween);
+ result.levels.min_output = do_tween(time, source.levels.min_output, dest.levels.min_output, duration, tween);
+ result.levels.gamma = do_tween(time, source.levels.gamma, dest.levels.gamma, duration, tween);
+ result.chroma.target_hue = do_tween(time, source.chroma.target_hue, dest.chroma.target_hue, duration, tween);
+ result.chroma.hue_width = do_tween(time, source.chroma.hue_width, dest.chroma.hue_width, duration, tween);
+ result.chroma.min_saturation = do_tween(time, source.chroma.min_saturation, dest.chroma.min_saturation, duration, tween);
+ result.chroma.min_brightness = do_tween(time, source.chroma.min_brightness, dest.chroma.min_brightness, duration, tween);
+ result.chroma.softness = do_tween(time, source.chroma.softness, dest.chroma.softness, duration, tween);
+ result.chroma.spill_suppress = do_tween(time, source.chroma.spill_suppress, dest.chroma.spill_suppress, duration, tween);
+ result.chroma.spill_suppress_saturation = do_tween(time, source.chroma.spill_suppress_saturation, dest.chroma.spill_suppress_saturation, duration, tween);
+ result.chroma.enable = dest.chroma.enable;
+ result.chroma.show_mask = dest.chroma.show_mask;
+ result.field_mode = source.field_mode & dest.field_mode;
+ result.is_key = source.is_key | dest.is_key;
+ result.is_mix = source.is_mix | dest.is_mix;
+ result.is_still = source.is_still | dest.is_still;
+ result.use_mipmap = source.use_mipmap | dest.use_mipmap;
+ result.blend_mode = std::max(source.blend_mode, dest.blend_mode);
+ result.layer_depth = dest.layer_depth;
do_tween_rectangle(source.crop, dest.crop, result.crop, time, duration, tween);
do_tween_corners(source.perspective, dest.perspective, result.perspective, time, duration, tween);
eq(lhs.chroma.min_saturation, rhs.chroma.min_saturation) &&
eq(lhs.chroma.min_brightness, rhs.chroma.min_brightness) &&
eq(lhs.chroma.softness, rhs.chroma.softness) &&
- eq(lhs.chroma.spill, rhs.chroma.spill) &&
- eq(lhs.chroma.spill_darken, rhs.chroma.spill_darken) &&
+ eq(lhs.chroma.spill_suppress, rhs.chroma.spill_suppress) &&
+ eq(lhs.chroma.spill_suppress_saturation, rhs.chroma.spill_suppress_saturation) &&
lhs.crop == rhs.crop &&
lhs.perspective == rhs.perspective;
}
blue
};
- bool enable = false;
- bool show_mask = false;
- double target_hue = 0.0;
- double hue_width = 0.0;
- double min_saturation = 0.0;
- double min_brightness = 0.0;
- double softness = 0.0;
- double spill = 1.0;
- double spill_darken = 0.0;
+ bool enable = false;
+ bool show_mask = false;
+ double target_hue = 0.0;
+ double hue_width = 0.0;
+ double min_saturation = 0.0;
+ double min_brightness = 0.0;
+ double softness = 0.0;
+ double spill_suppress = 0.0;
+ double spill_suppress_saturation = 1.0;
};
struct levels final
<xs:element name="layer" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
- <xs:element type="producer_string" name="producer"> <xs:annotation><xs:documentation>The same syntax as in AMCP after for example PLAY 1-10. Cannot be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="bool_expression" name="hidden" minOccurs="0" default="false"> <xs:annotation><xs:documentation>Hides the layer if true. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="x"> <xs:annotation><xs:documentation>The X coordinate of the layer in the scene coordinate system. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="y"> <xs:annotation><xs:documentation>The Y coordinate of the layer in the scene coordinate system. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="width" minOccurs="0"> <xs:annotation><xs:documentation>The width of the layer. Is by default calculated by the producer itself but can be overridden. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="height" minOccurs="0"> <xs:annotation><xs:documentation>The height of the layer. Is by default calculated by the producer itself but can be overridden. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="anchor_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X anchor within the layer coordinate system where position and rotation are done relative to/around. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="anchor_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y anchor within the layer coordinate system where position and rotation are done relative to/around. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="rotation" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>The rotation of the layer around anchor_x/anchor_y expressed in degrees. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="crop_upper_left_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to crop the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="crop_upper_left_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to crop the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="crop_lower_right_x" minOccurs="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to crop the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="crop_lower_right_y" minOccurs="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to crop the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_upper_left_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_upper_left_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_upper_right_x" minOccurs="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the upper right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_upper_right_y" minOccurs="0" default="0"><xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the upper right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_lower_right_x" minOccurs="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_lower_right_y" minOccurs="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_lower_left_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the lower left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="perspective_lower_left_y" minOccurs="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the lower left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="producer_string" name="producer"> <xs:annotation><xs:documentation>The same syntax as in AMCP after for example PLAY 1-10. Cannot be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="bool_expression" name="hidden" minOccurs="0" default="false"> <xs:annotation><xs:documentation>Hides the layer if true. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="x"> <xs:annotation><xs:documentation>The X coordinate of the layer in the scene coordinate system. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="y"> <xs:annotation><xs:documentation>The Y coordinate of the layer in the scene coordinate system. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="width" minOccurs="0"> <xs:annotation><xs:documentation>The width of the layer. Is by default calculated by the producer itself but can be overridden. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="height" minOccurs="0"> <xs:annotation><xs:documentation>The height of the layer. Is by default calculated by the producer itself but can be overridden. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="anchor_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X anchor within the layer coordinate system where position and rotation are done relative to/around. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="anchor_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y anchor within the layer coordinate system where position and rotation are done relative to/around. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="rotation" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>The rotation of the layer around anchor_x/anchor_y expressed in degrees. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="crop_upper_left_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to crop the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="crop_upper_left_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to crop the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="crop_lower_right_x" minOccurs="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to crop the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="crop_lower_right_y" minOccurs="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to crop the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_upper_left_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_upper_left_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the upper left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_upper_right_x" minOccurs="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the upper right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_upper_right_y" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the upper right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_lower_right_x" minOccurs="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_lower_right_y" minOccurs="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the lower right corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_lower_left_x" minOccurs="0" default="0"> <xs:annotation><xs:documentation>The X position within the layer coordinate system to corner pin the lower left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="perspective_lower_left_y" minOccurs="0"> <xs:annotation><xs:documentation>The Y position within the layer coordinate system to corner pin the lower left corner. Can be an expression.</xs:documentation></xs:annotation></xs:element>
<xs:element name="adjustments" minOccurs="0">
<xs:annotation>
<xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
- <xs:element type="number_expression" name="opacity" minOccurs="0" default="1.0"> <xs:annotation><xs:documentation>The opacity of the layer. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="opacity" minOccurs="0" default="1.0"> <xs:annotation><xs:documentation>The opacity of the layer. Can be an expression.</xs:documentation></xs:annotation></xs:element>
</xs:all>
</xs:complexType>
</xs:element>
- <xs:element type="bool_expression" name="is_key" minOccurs="0" default="false"> <xs:annotation><xs:documentation>If true causes the layer to key the layer above. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="bool_expression" name="use_mipmap" minOccurs="0" default="false"> <xs:annotation><xs:documentation>Whether to enable mipmapping on the layer or not. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="blend_mode" name="blend_mode" minOccurs="0" default="normal"> <xs:annotation><xs:documentation>The blend mode to use. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="bool_expression" name="is_key" minOccurs="0" default="false"> <xs:annotation><xs:documentation>If true causes the layer to key the layer above. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="bool_expression" name="use_mipmap" minOccurs="0" default="false"> <xs:annotation><xs:documentation>Whether to enable mipmapping on the layer or not. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="blend_mode" name="blend_mode" minOccurs="0" default="normal"> <xs:annotation><xs:documentation>The blend mode to use. Can be an expression.</xs:documentation></xs:annotation></xs:element>
<xs:element name="chroma_key" minOccurs="0">
<xs:complexType>
<xs:all>
- <xs:element type="bool_expression" name="enable" minOccurs="0" default="false"> <xs:annotation><xs:documentation>Whether to enable chroma keying on the layer or not. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="target_hue" minOccurs="0" default="120.0"> <xs:annotation><xs:documentation>The degrees within 0-360 of the hue window centrum of the color to key. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="hue_width" minOccurs="0" default="0.1"> <xs:annotation><xs:documentation>How wide within 0.0-1.0 the hue window of the color to key should be. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="min_saturation" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>The minimum saturation within 0.0-1.0 of the color to key. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="min_brightness" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>The minimum brightness within 0.0-1.0 of the color to key. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="softness" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>How soft the chroma key window should be within 0.0-1.0. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="spill" minOccurs="0" default="1.0"> <xs:annotation><xs:documentation>How much of the chroma fringing should be left within 0.0-1.0. Values below 1.0 gradually replaces the fringe with a gray scale and more transparent equivalent. Can be an expression.</xs:documentation></xs:annotation></xs:element>
- <xs:element type="number_expression" name="spill_darken" minOccurs="0" default="2.0"> <xs:annotation><xs:documentation>Defined how dark the spill replacement gray scale should be. The default is 2.0 but can be anywhere between 0.0 and up. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="bool_expression" name="enable" minOccurs="0" default="false"> <xs:annotation><xs:documentation>Whether to enable chroma keying on the layer or not. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="target_hue" minOccurs="0" default="120.0"> <xs:annotation><xs:documentation>The degrees within 0-360 of the hue window centrum of the color to key. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="hue_width" minOccurs="0" default="0.1"> <xs:annotation><xs:documentation>How wide within 0.0-1.0 the hue window of the color to key should be. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="min_saturation" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>The minimum saturation within 0.0-1.0 of the color to key. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="min_brightness" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>The minimum brightness within 0.0-1.0 of the color to key. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="softness" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>How soft the chroma key window should be within 0.0-1.0. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="spill_suppress" minOccurs="0" default="0.0"> <xs:annotation><xs:documentation>How much to suppress spill by within 0.0-180.0. It works by taking all hue values within +- this value from target_hue and clamps it to either target_hue - this value or target_hue + this value depending on which side it is closest to. Can be an expression.</xs:documentation></xs:annotation></xs:element>
+ <xs:element type="number_expression" name="spill_suppress_saturation" minOccurs="0" default="1.0"><xs:annotation><xs:documentation>Controls how much saturation should be kept on colors affected by spill_suppress within 0.0-1.0. Full saturation may not always be desirable to be kept on suppressed colors. Can be an expression.</xs:documentation></xs:annotation></xs:element>
</xs:all>
</xs:complexType>
</xs:element>
angle = layer.rotation.get() * PI / 180.0;
- transform.image_transform.opacity = layer.adjustments.opacity.get();
- transform.image_transform.is_key = layer.is_key.get();
- transform.image_transform.use_mipmap = layer.use_mipmap.get();
- transform.image_transform.blend_mode = layer.blend_mode.get();
- transform.image_transform.chroma.enable = layer.chroma_key.enable.get();
- transform.image_transform.chroma.target_hue = layer.chroma_key.target_hue.get();
- transform.image_transform.chroma.hue_width = layer.chroma_key.hue_width.get();
- transform.image_transform.chroma.min_saturation = layer.chroma_key.min_saturation.get();
- transform.image_transform.chroma.min_brightness = layer.chroma_key.min_brightness.get();
- transform.image_transform.chroma.softness = layer.chroma_key.softness.get();
- transform.image_transform.chroma.spill = layer.chroma_key.spill.get();
- transform.image_transform.chroma.spill_darken = layer.chroma_key.spill_darken.get();
+ transform.image_transform.opacity = layer.adjustments.opacity.get();
+ transform.image_transform.is_key = layer.is_key.get();
+ transform.image_transform.use_mipmap = layer.use_mipmap.get();
+ transform.image_transform.blend_mode = layer.blend_mode.get();
+ transform.image_transform.chroma.enable = layer.chroma_key.enable.get();
+ transform.image_transform.chroma.target_hue = layer.chroma_key.target_hue.get();
+ transform.image_transform.chroma.hue_width = layer.chroma_key.hue_width.get();
+ transform.image_transform.chroma.min_saturation = layer.chroma_key.min_saturation.get();
+ transform.image_transform.chroma.min_brightness = layer.chroma_key.min_brightness.get();
+ transform.image_transform.chroma.softness = layer.chroma_key.softness.get();
+ transform.image_transform.chroma.spill_suppress = layer.chroma_key.spill_suppress.get();
+ transform.image_transform.chroma.spill_suppress_saturation = layer.chroma_key.spill_suppress_saturation.get();
// Mark as sublayer, so it will be composited separately by the mixer.
transform.image_transform.layer_depth = 1;
struct chroma_key
{
- binding<bool> enable;
- binding<double> target_hue;
- binding<double> hue_width;
- binding<double> min_saturation;
- binding<double> min_brightness;
- binding<double> softness;
- binding<double> spill;
- binding<double> spill_darken;
+ binding<bool> enable;
+ binding<double> target_hue;
+ binding<double> hue_width;
+ binding<double> min_saturation;
+ binding<double> min_brightness;
+ binding<double> softness;
+ binding<double> spill_suppress;
+ binding<double> spill_suppress_saturation;
};
struct layer
else
scene->create_variable<double>(variable_prefix + L"height", false) = layer.producer.get()->pixel_constraints().height;
- layer.hidden = scene->create_variable<bool>(variable_prefix + L"hidden", false, elem.second.get(L"hidden", L"false"));
- layer.position.x = scene->create_variable<double>(variable_prefix + L"x", false, ptree_get<std::wstring>(elem.second, L"x"));
- layer.position.y = scene->create_variable<double>(variable_prefix + L"y", false, ptree_get<std::wstring>(elem.second, L"y"));
- layer.anchor.x = scene->create_variable<double>(variable_prefix + L"anchor_x", false, elem.second.get<std::wstring>(L"anchor_x", L"0.0"));
- layer.anchor.y = scene->create_variable<double>(variable_prefix + L"anchor_y", false, elem.second.get<std::wstring>(L"anchor_y", L"0.0"));
- layer.rotation = scene->create_variable<double>(variable_prefix + L"rotation", false, elem.second.get<std::wstring>(L"rotation", L"0.0"));
- layer.crop.upper_left.x = scene->create_variable<double>(variable_prefix + L"crop_upper_left_x", false, elem.second.get<std::wstring>(L"crop_upper_left_x", L"0.0"));
- layer.crop.upper_left.y = scene->create_variable<double>(variable_prefix + L"crop_upper_left_y", false, elem.second.get<std::wstring>(L"crop_upper_left_y", L"0.0"));
- layer.crop.lower_right.x = scene->create_variable<double>(variable_prefix + L"crop_lower_right_x", false, elem.second.get<std::wstring>(L"crop_lower_right_x", L"${" + variable_prefix + L"width}"));
- layer.crop.lower_right.y = scene->create_variable<double>(variable_prefix + L"crop_lower_right_y", false, elem.second.get<std::wstring>(L"crop_lower_right_y", L"${" + variable_prefix + L"height}"));
- layer.perspective.upper_left.x = scene->create_variable<double>(variable_prefix + L"perspective_upper_left_x", false, elem.second.get<std::wstring>(L"perspective_upper_left_x", L"0.0"));
- layer.perspective.upper_left.y = scene->create_variable<double>(variable_prefix + L"perspective_upper_left_y", false, elem.second.get<std::wstring>(L"perspective_upper_left_y", L"0.0"));
- layer.perspective.upper_right.x = scene->create_variable<double>(variable_prefix + L"perspective_upper_right_x", false, elem.second.get<std::wstring>(L"perspective_upper_right_x", L"${" + variable_prefix + L"width}"));
- layer.perspective.upper_right.y = scene->create_variable<double>(variable_prefix + L"perspective_upper_right_y", false, elem.second.get<std::wstring>(L"perspective_upper_right_y", L"0.0"));
- layer.perspective.lower_right.x = scene->create_variable<double>(variable_prefix + L"perspective_lower_right_x", false, elem.second.get<std::wstring>(L"perspective_lower_right_x", L"${" + variable_prefix + L"width}"));
- layer.perspective.lower_right.y = scene->create_variable<double>(variable_prefix + L"perspective_lower_right_y", false, elem.second.get<std::wstring>(L"perspective_lower_right_y", L"${" + variable_prefix + L"height}"));
- layer.perspective.lower_left.x = scene->create_variable<double>(variable_prefix + L"perspective_lower_left_x", false, elem.second.get<std::wstring>(L"perspective_lower_left_x", L"0.0"));
- layer.perspective.lower_left.y = scene->create_variable<double>(variable_prefix + L"perspective_lower_left_y", false, elem.second.get<std::wstring>(L"perspective_lower_left_y", L"${" + variable_prefix + L"height}"));
-
- layer.adjustments.opacity = scene->create_variable<double>(variable_prefix + L"adjustment.opacity", false, elem.second.get(L"adjustments.opacity", L"1.0"));
- layer.is_key = scene->create_variable<bool>(variable_prefix + L"is_key", false, elem.second.get(L"is_key", L"false"));
- layer.use_mipmap = scene->create_variable<bool>(variable_prefix + L"use_mipmap", false, elem.second.get(L"use_mipmap", L"false"));
- layer.blend_mode = scene->create_variable<std::wstring>(variable_prefix + L"blend_mode", false, elem.second.get(L"blend_mode", L"normal")).transformed([](const std::wstring& b) { return get_blend_mode(b); });
- layer.chroma_key.enable = scene->create_variable<bool>(variable_prefix + L"chroma_key.enable", false, elem.second.get(L"chroma_key.enable", L"false"));
- layer.chroma_key.target_hue = scene->create_variable<double>(variable_prefix + L"chroma_key.target_hue", false, elem.second.get(L"chroma_key.target_hue", L"120.0"));
- layer.chroma_key.hue_width = scene->create_variable<double>(variable_prefix + L"chroma_key.hue_width", false, elem.second.get(L"chroma_key.hue_width", L"0.1"));
- layer.chroma_key.min_saturation = scene->create_variable<double>(variable_prefix + L"chroma_key.min_saturation", false, elem.second.get(L"chroma_key.min_saturation", L"0.0"));
- layer.chroma_key.min_brightness = scene->create_variable<double>(variable_prefix + L"chroma_key.min_brightness", false, elem.second.get(L"chroma_key.min_brightness", L"0.0"));
- layer.chroma_key.softness = scene->create_variable<double>(variable_prefix + L"chroma_key.softness", false, elem.second.get(L"chroma_key.softness", L"0.0"));
- layer.chroma_key.spill = scene->create_variable<double>(variable_prefix + L"chroma_key.spill", false, elem.second.get(L"chroma_key.spill", L"1.0"));
- layer.chroma_key.spill_darken = scene->create_variable<double>(variable_prefix + L"chroma_key.spill_darken", false, elem.second.get(L"chroma_key.spill_darken", L"2.0"));
+ layer.hidden = scene->create_variable<bool>(variable_prefix + L"hidden", false, elem.second.get(L"hidden", L"false"));
+ layer.position.x = scene->create_variable<double>(variable_prefix + L"x", false, ptree_get<std::wstring>(elem.second, L"x"));
+ layer.position.y = scene->create_variable<double>(variable_prefix + L"y", false, ptree_get<std::wstring>(elem.second, L"y"));
+ layer.anchor.x = scene->create_variable<double>(variable_prefix + L"anchor_x", false, elem.second.get<std::wstring>(L"anchor_x", L"0.0"));
+ layer.anchor.y = scene->create_variable<double>(variable_prefix + L"anchor_y", false, elem.second.get<std::wstring>(L"anchor_y", L"0.0"));
+ layer.rotation = scene->create_variable<double>(variable_prefix + L"rotation", false, elem.second.get<std::wstring>(L"rotation", L"0.0"));
+ layer.crop.upper_left.x = scene->create_variable<double>(variable_prefix + L"crop_upper_left_x", false, elem.second.get<std::wstring>(L"crop_upper_left_x", L"0.0"));
+ layer.crop.upper_left.y = scene->create_variable<double>(variable_prefix + L"crop_upper_left_y", false, elem.second.get<std::wstring>(L"crop_upper_left_y", L"0.0"));
+ layer.crop.lower_right.x = scene->create_variable<double>(variable_prefix + L"crop_lower_right_x", false, elem.second.get<std::wstring>(L"crop_lower_right_x", L"${" + variable_prefix + L"width}"));
+ layer.crop.lower_right.y = scene->create_variable<double>(variable_prefix + L"crop_lower_right_y", false, elem.second.get<std::wstring>(L"crop_lower_right_y", L"${" + variable_prefix + L"height}"));
+ layer.perspective.upper_left.x = scene->create_variable<double>(variable_prefix + L"perspective_upper_left_x", false, elem.second.get<std::wstring>(L"perspective_upper_left_x", L"0.0"));
+ layer.perspective.upper_left.y = scene->create_variable<double>(variable_prefix + L"perspective_upper_left_y", false, elem.second.get<std::wstring>(L"perspective_upper_left_y", L"0.0"));
+ layer.perspective.upper_right.x = scene->create_variable<double>(variable_prefix + L"perspective_upper_right_x", false, elem.second.get<std::wstring>(L"perspective_upper_right_x", L"${" + variable_prefix + L"width}"));
+ layer.perspective.upper_right.y = scene->create_variable<double>(variable_prefix + L"perspective_upper_right_y", false, elem.second.get<std::wstring>(L"perspective_upper_right_y", L"0.0"));
+ layer.perspective.lower_right.x = scene->create_variable<double>(variable_prefix + L"perspective_lower_right_x", false, elem.second.get<std::wstring>(L"perspective_lower_right_x", L"${" + variable_prefix + L"width}"));
+ layer.perspective.lower_right.y = scene->create_variable<double>(variable_prefix + L"perspective_lower_right_y", false, elem.second.get<std::wstring>(L"perspective_lower_right_y", L"${" + variable_prefix + L"height}"));
+ layer.perspective.lower_left.x = scene->create_variable<double>(variable_prefix + L"perspective_lower_left_x", false, elem.second.get<std::wstring>(L"perspective_lower_left_x", L"0.0"));
+ layer.perspective.lower_left.y = scene->create_variable<double>(variable_prefix + L"perspective_lower_left_y", false, elem.second.get<std::wstring>(L"perspective_lower_left_y", L"${" + variable_prefix + L"height}"));
+
+ layer.adjustments.opacity = scene->create_variable<double>(variable_prefix + L"adjustment.opacity", false, elem.second.get(L"adjustments.opacity", L"1.0"));
+ layer.is_key = scene->create_variable<bool>(variable_prefix + L"is_key", false, elem.second.get(L"is_key", L"false"));
+ layer.use_mipmap = scene->create_variable<bool>(variable_prefix + L"use_mipmap", false, elem.second.get(L"use_mipmap", L"false"));
+ layer.blend_mode = scene->create_variable<std::wstring>(variable_prefix + L"blend_mode", false, elem.second.get(L"blend_mode", L"normal")).transformed([](const std::wstring& b) { return get_blend_mode(b); });
+ layer.chroma_key.enable = scene->create_variable<bool>(variable_prefix + L"chroma_key.enable", false, elem.second.get(L"chroma_key.enable", L"false"));
+ layer.chroma_key.target_hue = scene->create_variable<double>(variable_prefix + L"chroma_key.target_hue", false, elem.second.get(L"chroma_key.target_hue", L"120.0"));
+ layer.chroma_key.hue_width = scene->create_variable<double>(variable_prefix + L"chroma_key.hue_width", false, elem.second.get(L"chroma_key.hue_width", L"0.1"));
+ layer.chroma_key.min_saturation = scene->create_variable<double>(variable_prefix + L"chroma_key.min_saturation", false, elem.second.get(L"chroma_key.min_saturation", L"0.0"));
+ layer.chroma_key.min_brightness = scene->create_variable<double>(variable_prefix + L"chroma_key.min_brightness", false, elem.second.get(L"chroma_key.min_brightness", L"0.0"));
+ layer.chroma_key.softness = scene->create_variable<double>(variable_prefix + L"chroma_key.softness", false, elem.second.get(L"chroma_key.softness", L"0.0"));
+ layer.chroma_key.spill_suppress = scene->create_variable<double>(variable_prefix + L"chroma_key.spill_suppress", false, elem.second.get(L"chroma_key.spill_suppress", L"0.0"));
+ layer.chroma_key.spill_suppress_saturation = scene->create_variable<double>(variable_prefix + L"chroma_key.spill_suppress_saturation", false, elem.second.get(L"chroma_key.spill_suppress_saturation", L"1.0"));
for (auto& var_name : producer->get_variables())
{
void mixer_chroma_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Enable chroma keying on a layer.");
- sink.syntax(L"MIXER [video_channel:int]{-[layer:int]|-0} CHROMA {[enable:0,1] {[target_hue:float] [hue_width:float] [min_saturation:float] [min_brightness:float] [softness:float] [spill:float] [spill_darken:float] [show_mask:0,1]}}" + ANIMATION_SYNTAX);
+ sink.syntax(L"MIXER [video_channel:int]{-[layer:int]|-0} CHROMA {[enable:0,1] {[target_hue:float] [hue_width:float] [min_saturation:float] [min_brightness:float] [softness:float] [spill_suppress:float] [spill_suppress_saturation:float] [show_mask:0,1]}}" + ANIMATION_SYNTAX);
sink.para()
->text(L"Enables or disables chroma keying on the specified video layer. Giving no parameters returns the current chroma settings.");
sink.para()->text(L"The chroma keying is done in the HSB/HSV color space.");
sink.para()->text(L"Parameters:");
sink.definitions()
- ->item(L"enable", L"0 to disable chroma keying on layer. The rest of the parameters should not be given when disabling.")
- ->item(L"target_hue", L"The hue in degrees between 0-360 where the center of the hue window will open up.")
- ->item(L"hue_width", L"The width of the hue window within 0.0-1.0 where 1.0 means 100% of 360 degrees around target_hue.")
- ->item(L"min_saturation", L"The minimum saturation within 0.0-1.0 required for a color to be within the chroma window.")
- ->item(L"min_brightness", L"The minimum brightness within 0.0-1.0 required for a color to be within the chroma window.")
- ->item(L"softness", L"The softness of the chroma keying window.")
- ->item(L"spill", L"Controls the amount of spill. A value of 1.0 does not suppress any spill. A lower value gradually turns the spill into grayscale and more transparent.")
- ->item(L"spill_darken", L"Controls the shade of gray that the spill suppression is done towards. Lower values goes towards white and higher values goes towards black.")
- ->item(L"show_mask", L"If enabled, only shows the mask. Useful while editing the chroma key settings.")
+ ->item(L"enable", L"0 to disable chroma keying on layer. The rest of the parameters should not be given when disabling.")
+ ->item(L"target_hue", L"The hue in degrees between 0-360 where the center of the hue window will open up.")
+ ->item(L"hue_width", L"The width of the hue window within 0.0-1.0 where 1.0 means 100% of 360 degrees around target_hue.")
+ ->item(L"min_saturation", L"The minimum saturation within 0.0-1.0 required for a color to be within the chroma window.")
+ ->item(L"min_brightness", L"The minimum brightness within 0.0-1.0 required for a color to be within the chroma window.")
+ ->item(L"softness", L"The softness of the chroma keying window.")
+ ->item(L"spill_suppress", L"How much to suppress spill by within 0.0-180.0. It works by taking all hue values within +- this value from target_hue and clamps it to either target_hue - this value or target_hue + this value depending on which side it is closest to.")
+ ->item(L"spill_suppress_saturation", L"Controls how much saturation should be kept on colors affected by spill_suppress within 0.0-1.0. Full saturation may not always be desirable to be kept on suppressed colors.")
+ ->item(L"show_mask", L"If enabled, only shows the mask. Useful while editing the chroma key settings.")
;
- sink.example(L">> MIXER 1-1 CHROMA 1 120 0.1 0 0 0.1 1 2 0", L"for enabling chroma keying centered around a hue of 120 degrees (green) and with a 10% hue width");
+ sink.example(L">> MIXER 1-1 CHROMA 1 120 0.1 0 0 0.1 0.1 0.7 0", L"for enabling chroma keying centered around a hue of 120 degrees (green) and with a 10% hue width");
sink.example(L">> MIXER 1-1 CHROMA 0", L"for disabling chroma keying");
sink.example(
L">> MIXER 1-1 CHROMA 0\n"
L"<< 202 MIXER OK\n"
- L"<< 1 120 0.1 0 0 0.1 1 2 0", L"for getting the current chroma key mode");
+ L"<< 1 120 0.1 0 0 0.1 0 1 0", L"for getting the current chroma key mode");
sink.para()->text(L"Deprecated legacy syntax:");
sink.syntax(L"MIXER [video_channel:int]{-[layer:int]|-0} CHROMA {[color:none,green,blue] {[threshold:float] [softness:float] [spill:float]}}" + ANIMATION_SYNTAX);
sink.para()->text(L"Deprecated legacy examples:");
+ boost::lexical_cast<std::wstring>(chroma.min_saturation) + L" "
+ boost::lexical_cast<std::wstring>(chroma.min_brightness) + L" "
+ boost::lexical_cast<std::wstring>(chroma.softness) + L" "
- + boost::lexical_cast<std::wstring>(chroma.spill) + L" "
- + boost::lexical_cast<std::wstring>(chroma.spill_darken) + L" "
+ + boost::lexical_cast<std::wstring>(chroma.spill_suppress) + L" "
+ + boost::lexical_cast<std::wstring>(chroma.spill_suppress_saturation) + L" "
+ std::wstring(chroma.show_mask ? L"1" : L"0") + L"\r\n";
}
}
else
{
- chroma.enable = true;
- chroma.hue_width = 0.5 - boost::lexical_cast<double>(ctx.parameters.at(1)) * 0.5;
- chroma.min_brightness = boost::lexical_cast<double>(ctx.parameters.at(1));
- chroma.min_saturation = boost::lexical_cast<double>(ctx.parameters.at(1));
- chroma.softness = boost::lexical_cast<double>(ctx.parameters.at(2)) - boost::lexical_cast<double>(ctx.parameters.at(1));
- chroma.spill = boost::lexical_cast<double>(ctx.parameters.at(3));
- chroma.spill_darken = 2;
+ chroma.enable = true;
+ chroma.hue_width = 0.5 - boost::lexical_cast<double>(ctx.parameters.at(1)) * 0.5;
+ chroma.min_brightness = boost::lexical_cast<double>(ctx.parameters.at(1));
+ chroma.min_saturation = boost::lexical_cast<double>(ctx.parameters.at(1));
+ chroma.softness = boost::lexical_cast<double>(ctx.parameters.at(2)) - boost::lexical_cast<double>(ctx.parameters.at(1));
+ chroma.spill_suppress = 180.0 - boost::lexical_cast<double>(ctx.parameters.at(3)) * 180.0;
+ chroma.spill_suppress_saturation = 1;
if (*legacy_mode == chroma::legacy_type::green)
chroma.target_hue = 120;
if (chroma.enable)
{
- chroma.target_hue = boost::lexical_cast<double>(ctx.parameters.at(1));
- chroma.hue_width = boost::lexical_cast<double>(ctx.parameters.at(2));
- chroma.min_saturation = boost::lexical_cast<double>(ctx.parameters.at(3));
- chroma.min_brightness = boost::lexical_cast<double>(ctx.parameters.at(4));
- chroma.softness = boost::lexical_cast<double>(ctx.parameters.at(5));
- chroma.spill = boost::lexical_cast<double>(ctx.parameters.at(6));
- chroma.spill_darken = boost::lexical_cast<double>(ctx.parameters.at(7));
- chroma.show_mask = boost::lexical_cast<double>(ctx.parameters.at(8));
+ chroma.target_hue = boost::lexical_cast<double>(ctx.parameters.at(1));
+ chroma.hue_width = boost::lexical_cast<double>(ctx.parameters.at(2));
+ chroma.min_saturation = boost::lexical_cast<double>(ctx.parameters.at(3));
+ chroma.min_brightness = boost::lexical_cast<double>(ctx.parameters.at(4));
+ chroma.softness = boost::lexical_cast<double>(ctx.parameters.at(5));
+ chroma.spill_suppress = boost::lexical_cast<double>(ctx.parameters.at(6));
+ chroma.spill_suppress_saturation = boost::lexical_cast<double>(ctx.parameters.at(7));
+ chroma.show_mask = boost::lexical_cast<double>(ctx.parameters.at(8));
}
}