4 * Copyright (C) 2012 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcdisplayinfo.h"
23 #include "bcsignals.h"
24 #include "chromakey.h"
31 #include "loadbalance.h"
32 #include "playback3d.h"
34 #include "pluginvclient.h"
43 ChromaKeyConfig::ChromaKeyConfig ()
49 min_brightness = 50.0;
50 max_brightness = 100.0;
53 min_saturation = 50.0;
59 spill_threshold = 0.0;
68 ChromaKeyConfig::copy_from (ChromaKeyConfig & src)
73 spill_threshold = src.spill_threshold;
74 spill_amount = src.spill_amount;
75 min_brightness = src.min_brightness;
76 max_brightness = src.max_brightness;
77 saturation = src.saturation;
78 min_saturation = src.min_saturation;
79 tolerance = src.tolerance;
80 in_slope = src.in_slope;
81 out_slope = src.out_slope;
82 alpha_offset = src.alpha_offset;
83 show_mask = src.show_mask;
87 ChromaKeyConfig::equivalent (ChromaKeyConfig & src)
89 return (EQUIV (red, src.red) &&
90 EQUIV (green, src.green) &&
91 EQUIV (blue, src.blue) &&
92 EQUIV (spill_threshold, src.spill_threshold) &&
93 EQUIV (spill_amount, src.spill_amount) &&
94 EQUIV (min_brightness, src.min_brightness) &&
95 EQUIV (max_brightness, src.max_brightness) &&
96 EQUIV (saturation, src.saturation) &&
97 EQUIV (min_saturation, src.min_saturation) &&
98 EQUIV (tolerance, src.tolerance) &&
99 EQUIV (in_slope, src.in_slope) &&
100 EQUIV (out_slope, src.out_slope) &&
101 EQUIV (show_mask, src.show_mask) &&
102 EQUIV (alpha_offset, src.alpha_offset));
106 ChromaKeyConfig::interpolate (ChromaKeyConfig & prev,
107 ChromaKeyConfig & next,
109 int64_t next_frame, int64_t current_frame)
112 (double) (current_frame - prev_frame) / (next_frame - prev_frame);
114 (double) (next_frame - current_frame) / (next_frame - prev_frame);
116 this->red = prev.red * prev_scale + next.red * next_scale;
117 this->green = prev.green * prev_scale + next.green * next_scale;
118 this->blue = prev.blue * prev_scale + next.blue * next_scale;
119 this->spill_threshold =
120 prev.spill_threshold * prev_scale + next.spill_threshold * next_scale;
122 prev.spill_amount * prev_scale + next.tolerance * next_scale;
123 this->min_brightness =
124 prev.min_brightness * prev_scale + next.min_brightness * next_scale;
125 this->max_brightness =
126 prev.max_brightness * prev_scale + next.max_brightness * next_scale;
128 prev.saturation * prev_scale + next.saturation * next_scale;
129 this->min_saturation =
130 prev.min_saturation * prev_scale + next.min_saturation * next_scale;
131 this->tolerance = prev.tolerance * prev_scale + next.tolerance * next_scale;
132 this->in_slope = prev.in_slope * prev_scale + next.in_slope * next_scale;
133 this->out_slope = prev.out_slope * prev_scale + next.out_slope * next_scale;
135 prev.alpha_offset * prev_scale + next.alpha_offset * next_scale;
136 this->show_mask = next.show_mask;
141 ChromaKeyConfig::get_color ()
143 int red = (int) (CLIP (this->red, 0, 1) * 0xff);
144 int green = (int) (CLIP (this->green, 0, 1) * 0xff);
145 int blue = (int) (CLIP (this->blue, 0, 1) * 0xff);
146 return (red << 16) | (green << 8) | blue;
151 ChromaKeyWindow::ChromaKeyWindow (ChromaKeyHSV * plugin)
152 : PluginClientWindow(plugin,
159 this->plugin = plugin;
163 ChromaKeyWindow::~ChromaKeyWindow ()
169 ChromaKeyWindow::create_objects ()
171 int y = 10, y1, x1 = 0, x2 = 10;
176 int ymargin = get_text_height(MEDIUMFONT) + 5;
177 int ymargin2 = get_text_height(MEDIUMFONT) + 10;
179 add_subwindow (title = new BC_Title (x2, y, _("Color:")));
181 add_subwindow (color = new ChromaKeyColor (plugin, this, x, y + 25));
183 add_subwindow (sample =
184 new BC_SubWindow (x + color->get_w () + 10, y, 100, 50));
185 y += sample->get_h () + 10;
187 add_subwindow (use_colorpicker =
188 new ChromaKeyUseColorPicker (plugin, this, x, y));
189 y += use_colorpicker->get_h() + 10;
190 add_subwindow (show_mask = new ChromaKeyShowMask (plugin, x2, y));
191 y += show_mask->get_h() + 5;
193 add_subwindow(bar = new BC_Bar(x2, y, get_w() - x2 * 2));
194 y += bar->get_h() + 5;
196 add_subwindow (new BC_Title (x2, y, _("Key parameters:")));
198 add_subwindow (title = new BC_Title (x, y, _("Hue Tolerance:")));
199 if(title->get_w() > x1) x1 = title->get_w();
201 add_subwindow (title = new BC_Title (x, y, _("Min. Brightness:")));
202 if(title->get_w() > x1) x1 = title->get_w();
204 add_subwindow (title = new BC_Title (x, y, _("Max. Brightness:")));
205 if(title->get_w() > x1) x1 = title->get_w();
207 add_subwindow (title = new BC_Title (x, y, _("Saturation Offset:")));
208 if(title->get_w() > x1) x1 = title->get_w();
210 add_subwindow (title = new BC_Title (x, y, _("Min Saturation:")));
211 if(title->get_w() > x1) x1 = title->get_w();
214 add_subwindow(bar = new BC_Bar(x2, y, get_w() - x2 * 2));
215 y += bar->get_h() + 5;
216 add_subwindow (title = new BC_Title (x2, y, _("Mask tweaking:")));
218 add_subwindow (title = new BC_Title (x, y, _("In Slope:")));
219 if(title->get_w() > x1) x1 = title->get_w();
221 add_subwindow (title = new BC_Title (x, y, _("Out Slope:")));
222 if(title->get_w() > x1) x1 = title->get_w();
224 add_subwindow (title = new BC_Title (x, y, _("Alpha Offset:")));
225 if(title->get_w() > x1) x1 = title->get_w();
230 add_subwindow(bar = new BC_Bar(x2, y, get_w() - x2 * 2));
231 y += bar->get_h() + 5;
232 add_subwindow (title = new BC_Title (x2, y, _("Spill light control:")));
234 add_subwindow (title = new BC_Title (x, y, _("Spill Threshold:")));
235 if(title->get_w() > x1) x1 = title->get_w();
237 add_subwindow (title = new BC_Title (x, y, _("Spill Compensation:")));
238 if(title->get_w() > x1) x1 = title->get_w();
248 add_subwindow (tolerance = new ChromaKeyTolerance (plugin, x1, y));
250 add_subwindow (min_brightness = new ChromaKeyMinBrightness (plugin, x1, y));
252 add_subwindow (max_brightness = new ChromaKeyMaxBrightness (plugin, x1, y));
254 add_subwindow (saturation = new ChromaKeySaturation (plugin, x1, y));
256 add_subwindow (min_saturation = new ChromaKeyMinSaturation (plugin, x1, y));
259 y += bar->get_h() + 5;
261 add_subwindow (in_slope = new ChromaKeyInSlope (plugin, x1, y));
263 add_subwindow (out_slope = new ChromaKeyOutSlope (plugin, x1, y));
265 add_subwindow (alpha_offset = new ChromaKeyAlphaOffset (plugin, x1, y));
268 y += bar->get_h() + 5;
270 add_subwindow (spill_threshold = new ChromaKeySpillThreshold (plugin, x1, y));
272 add_subwindow (spill_amount = new ChromaKeySpillAmount (plugin, x1, y));
274 color_thread = new ChromaKeyColorThread (plugin, this);
281 ChromaKeyWindow::update_sample ()
283 sample->set_color (plugin->config.get_color ());
284 sample->draw_box (0, 0, sample->get_w (), sample->get_h ());
285 sample->set_color (BLACK);
286 sample->draw_rectangle (0, 0, sample->get_w (), sample->get_h ());
292 ChromaKeyColor::ChromaKeyColor (ChromaKeyHSV * plugin,
293 ChromaKeyWindow * gui, int x, int y):
294 BC_GenericButton (x, y, _("Color..."))
296 this->plugin = plugin;
301 ChromaKeyColor::handle_event ()
303 gui->color_thread->start_window (plugin->config.get_color (), 0xff);
310 ChromaKeyMinBrightness::ChromaKeyMinBrightness (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
313 200, 200, (float) 0, (float) 100, plugin->config.min_brightness)
315 this->plugin = plugin;
316 set_precision (0.01);
320 ChromaKeyMinBrightness::handle_event ()
322 plugin->config.min_brightness = get_value ();
323 plugin->send_configure_change ();
327 ChromaKeyMaxBrightness::ChromaKeyMaxBrightness (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
330 200, 200, (float) 0, (float) 100, plugin->config.max_brightness)
332 this->plugin = plugin;
333 set_precision (0.01);
337 ChromaKeyMaxBrightness::handle_event ()
339 plugin->config.max_brightness = get_value ();
340 plugin->send_configure_change ();
345 ChromaKeySaturation::ChromaKeySaturation (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
347 0, 200, 200, (float) 0, (float) 100, plugin->config.saturation)
349 this->plugin = plugin;
350 set_precision (0.01);
354 ChromaKeySaturation::handle_event ()
356 plugin->config.saturation = get_value ();
357 plugin->send_configure_change ();
361 ChromaKeyMinSaturation::ChromaKeyMinSaturation (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
364 200, 200, (float) 0, (float) 100, plugin->config.min_saturation)
366 this->plugin = plugin;
367 set_precision (0.01);
371 ChromaKeyMinSaturation::handle_event ()
373 plugin->config.min_saturation = get_value ();
374 plugin->send_configure_change ();
379 ChromaKeyTolerance::ChromaKeyTolerance (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
381 0, 200, 200, (float) 0, (float) 100, plugin->config.tolerance)
383 this->plugin = plugin;
384 set_precision (0.01);
388 ChromaKeyTolerance::handle_event ()
390 plugin->config.tolerance = get_value ();
391 plugin->send_configure_change ();
397 ChromaKeyInSlope::ChromaKeyInSlope (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
399 0, 200, 200, (float) 0, (float) 20, plugin->config.in_slope)
401 this->plugin = plugin;
402 set_precision (0.01);
406 ChromaKeyInSlope::handle_event ()
408 plugin->config.in_slope = get_value ();
409 plugin->send_configure_change ();
414 ChromaKeyOutSlope::ChromaKeyOutSlope (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
416 0, 200, 200, (float) 0, (float) 20, plugin->config.out_slope)
418 this->plugin = plugin;
419 set_precision (0.01);
423 ChromaKeyOutSlope::handle_event ()
425 plugin->config.out_slope = get_value ();
426 plugin->send_configure_change ();
431 ChromaKeyAlphaOffset::ChromaKeyAlphaOffset (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
434 200, 200, (float) -100, (float) 100, plugin->config.alpha_offset)
436 this->plugin = plugin;
437 set_precision (0.01);
441 ChromaKeyAlphaOffset::handle_event ()
443 plugin->config.alpha_offset = get_value ();
444 plugin->send_configure_change ();
448 ChromaKeyShowMask::ChromaKeyShowMask (ChromaKeyHSV * plugin, int x, int y):BC_CheckBox (x, y, plugin->config.show_mask,
452 this->plugin = plugin;
457 ChromaKeyShowMask::handle_event ()
459 plugin->config.show_mask = get_value ();
460 plugin->send_configure_change ();
464 ChromaKeyUseColorPicker::ChromaKeyUseColorPicker (ChromaKeyHSV * plugin, ChromaKeyWindow * gui, int x, int y)
465 : BC_GenericButton (x, y,
467 ("Use color picker"))
469 this->plugin = plugin;
474 ChromaKeyUseColorPicker::handle_event ()
476 plugin->config.red = plugin->get_red ();
477 plugin->config.green = plugin->get_green ();
478 plugin->config.blue = plugin->get_blue ();
480 gui->update_sample ();
483 plugin->send_configure_change ();
489 ChromaKeySpillThreshold::ChromaKeySpillThreshold (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
492 200, 200, (float) 0, (float) 100, plugin->config.spill_threshold)
494 this->plugin = plugin;
495 set_precision (0.01);
499 ChromaKeySpillThreshold::handle_event ()
501 plugin->config.spill_threshold = get_value ();
502 plugin->send_configure_change ();
506 ChromaKeySpillAmount::ChromaKeySpillAmount (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
508 0, 200, 200, (float) 0, (float) 100, plugin->config.spill_amount)
510 this->plugin = plugin;
511 set_precision (0.01);
515 ChromaKeySpillAmount::handle_event ()
517 plugin->config.spill_amount = get_value ();
518 plugin->send_configure_change ();
527 ChromaKeyColorThread::ChromaKeyColorThread (ChromaKeyHSV * plugin, ChromaKeyWindow * gui)
528 : ColorThread (1, _("Inner color"))
530 this->plugin = plugin;
535 ChromaKeyColorThread::handle_new_color (int output, int alpha)
537 plugin->config.red = (float) (output & 0xff0000) / 0xff0000;
538 plugin->config.green = (float) (output & 0xff00) / 0xff00;
539 plugin->config.blue = (float) (output & 0xff) / 0xff;
541 get_gui()->unlock_window();
542 gui->lock_window("ChromaKeyColorThread::handle_new_color");
543 gui->update_sample ();
544 gui->unlock_window();
545 get_gui()->lock_window("ChromaKeyColorThread::handle_new_color");
548 plugin->send_configure_change ();
559 ChromaKeyServer::ChromaKeyServer (ChromaKeyHSV * plugin):LoadServer (plugin->PluginClient::smp + 1,
560 plugin->PluginClient::smp +
563 this->plugin = plugin;
567 ChromaKeyServer::init_packages ()
569 for (int i = 0; i < get_total_packages (); i++)
571 ChromaKeyPackage *pkg = (ChromaKeyPackage *) get_package (i);
572 pkg->y1 = plugin->input->get_h () * i / get_total_packages ();
573 pkg->y2 = plugin->input->get_h () * (i + 1) / get_total_packages ();
578 ChromaKeyServer::new_client ()
580 return new ChromaKeyUnit (plugin, this);
584 ChromaKeyServer::new_package ()
586 return new ChromaKeyPackage;
591 ChromaKeyPackage::ChromaKeyPackage ():LoadPackage ()
595 ChromaKeyUnit::ChromaKeyUnit (ChromaKeyHSV * plugin, ChromaKeyServer * server):LoadClient
598 this->plugin = plugin;
604 #define ABS(a) ((a<0)?-(a):a)
605 // Reuse as much as possible in the opengl version
606 #define OUTER_VARIABLES \
607 float red = plugin->config.red; \
608 float green = plugin->config.green; \
609 float blue = plugin->config.blue; \
611 float in_slope = plugin->config.in_slope / 100; \
612 float out_slope = plugin->config.out_slope / 100; \
614 float tolerance = plugin->config.tolerance / 100; \
615 float tolerance_in = tolerance - in_slope; \
616 float tolerance_out = tolerance + out_slope; \
618 float sat = plugin->config.saturation / 100; \
619 float min_s = plugin->config.min_saturation / 100; \
620 float min_s_in = min_s + in_slope; \
621 float min_s_out = min_s - out_slope; \
623 float min_v = plugin->config.min_brightness / 100; \
624 float min_v_in = min_v + in_slope; \
625 float min_v_out = min_v - out_slope; \
627 float max_v = plugin->config.max_brightness / 100; \
628 float max_v_in = max_v - in_slope; \
629 float max_v_out = max_v + out_slope; \
631 float spill_threshold = plugin->config.spill_threshold / 100; \
632 float spill_amount = 1.0 - plugin->config.spill_amount / 100; \
634 float alpha_offset = plugin->config.alpha_offset / 100; \
636 /* Convert RGB key to HSV key */ \
637 float hue_key, saturation_key, value_key; \
638 HSV::rgb_to_hsv(red, \
646 template <typename component_type>
647 void ChromaKeyUnit::process_chromakey(int components,
650 ChromaKeyPackage *pkg)
654 int w = plugin->input->get_w();
656 for (int i = pkg->y1; i < pkg->y2; i++)
658 component_type *row = (component_type *) plugin->input->get_rows ()[i];
660 for (int j = 0; j < w; j++)
664 float r = (float) row[0] / max;
665 float g = (float) row[1] / max;
666 float b = (float) row[2] / max;
670 float av = 1, ah = 1, as = 1, avm = 1;
671 bool has_match = true;
675 /* Convert pixel to RGB float */
679 YUV::yuv_to_rgb_f (r, g, b, y, u - 0.5, v - 0.5);
682 HSV::rgb_to_hsv (r, g, b, h, s, v);
684 // First, test if the hue is in range
687 if(h <= hue_key - tolerance_in * 180.0)
690 if(h >= hue_key + tolerance_in * 180.0)
697 if (ABS (h - hue_key) < tolerance_in * 180)
700 if ((out_slope != 0) && (ABS (h - hue_key) < tolerance * 180))
701 /* we scale alpha between 0 and 1/2 */
702 ah = ABS (h - hue_key) / tolerance / 360;
704 if (ABS (h - hue_key) < tolerance_out * 180)
705 /* we scale alpha between 1/2 and 1 */
706 ah = ABS (h - hue_key) / tolerance_out / 360;
710 // Check if the saturation matches
715 else if (s - sat >= min_s_in)
717 else if ((out_slope != 0) && (s - sat > min_s))
718 as = (s - sat - min_s) / (min_s * 2);
719 else if (s - sat > min_s_out)
720 as = (s - sat - min_s_out) / (min_s_out * 2);
725 // Check if the value is more than the minimun
730 else if (v >= min_v_in)
732 else if ((out_slope != 0) && (v > min_v))
733 av = (v - min_v) / (min_v * 2);
734 else if (v > min_v_out)
735 av = (v - min_v_out) / (min_v_out * 2);
740 // Check if the value is less than the maximum
745 else if (v <= max_v_in)
747 else if ((out_slope != 0) && (v < max_v))
748 avm = (v - max_v) / (max_v * 2);
749 else if (v < max_v_out)
750 avm = (v - max_v_out) / (max_v_out * 2);
755 // If the color is part of the key, update the alpha channel
757 a = MAX (MAX (ah, av), MAX (as, avm));
759 // Spill light processing
760 if ((ABS (h - hue_key) < spill_threshold * 180) ||
761 ((ABS (h - hue_key) > 360)
762 && (ABS (h - hue_key) - 360 < spill_threshold * 180)))
764 s = s * spill_amount * ABS (h - hue_key) / (spill_threshold * 180);
766 HSV::hsv_to_rgb (r, g, b, h, s, v);
773 YUV::rgb_to_yuv_f (r, g, b, y, u, v);
777 row[0] = (component_type) ((float) y * max);
778 row[1] = (component_type) ((float) (u + 0.5) * max);
779 row[2] = (component_type) ((float) (v + 0.5) * max);
786 row[0] = (component_type) ((float) r * max);
787 row[1] = (component_type) ((float) g * max);
788 row[2] = (component_type) ((float) b * max);
795 if (plugin->config.show_mask)
800 row[0] = (component_type) ((float) a * max);
801 row[1] = (component_type) ((float) max / 2);
802 row[2] = (component_type) ((float) max / 2);
806 row[0] = (component_type) ((float) a * max);
807 row[1] = (component_type) ((float) a * max);
808 row[2] = (component_type) ((float) a * max);
812 /* Multiply alpha and put back in frame */
815 row[3] = MIN ((component_type) (a * max), row[3]);
819 row[0] = (component_type) ((float) a * row[0]);
821 (component_type) ((float) a * (row[1] - (max / 2 + 1)) +
824 (component_type) ((float) a * (row[2] - (max / 2 + 1)) +
829 row[0] = (component_type) ((float) a * row[0]);
830 row[1] = (component_type) ((float) a * row[1]);
831 row[2] = (component_type) ((float) a * row[2]);
842 void ChromaKeyUnit::process_package(LoadPackage *package)
844 ChromaKeyPackage *pkg = (ChromaKeyPackage*)package;
847 switch(plugin->input->get_color_model())
850 process_chromakey<float> (3, 1.0, 0, pkg);
853 process_chromakey<float> ( 4, 1.0, 0, pkg);
856 process_chromakey<unsigned char> ( 3, 0xff, 0, pkg);
859 process_chromakey<unsigned char> ( 4, 0xff, 0, pkg);
862 process_chromakey<unsigned char> ( 3, 0xff, 1, pkg);
865 process_chromakey<unsigned char> ( 4, 0xff, 1, pkg);
868 process_chromakey<uint16_t> (3, 0xffff, 1, pkg);
870 case BC_YUVA16161616:
871 process_chromakey<uint16_t> (4, 0xffff, 1, pkg);
881 REGISTER_PLUGIN(ChromaKeyHSV)
885 ChromaKeyHSV::ChromaKeyHSV(PluginServer *server)
886 : PluginVClient(server)
892 ChromaKeyHSV::~ChromaKeyHSV()
895 if(engine) delete engine;
899 int ChromaKeyHSV::process_buffer(VFrame *frame,
900 int64_t start_position,
903 load_configuration();
905 this->output = frame;
913 if(get_use_opengl()) return run_opengl();
916 if(!engine) engine = new ChromaKeyServer(this);
917 engine->process_packages();
922 const char* ChromaKeyHSV::plugin_title() { return _("Chroma key (HSV)"); }
923 int ChromaKeyHSV::is_realtime() { return 1; }
926 LOAD_CONFIGURATION_MACRO(ChromaKeyHSV, ChromaKeyConfig)
929 void ChromaKeyHSV::save_data(KeyFrame * keyframe)
932 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
933 output.tag.set_title("CHROMAKEY_HSV");
934 output.tag.set_property("RED", config.red);
935 output.tag.set_property("GREEN", config.green);
936 output.tag.set_property("BLUE", config.blue);
937 output.tag.set_property("MIN_BRIGHTNESS", config.min_brightness);
938 output.tag.set_property("MAX_BRIGHTNESS", config.max_brightness);
939 output.tag.set_property("SATURATION", config.saturation);
940 output.tag.set_property("MIN_SATURATION", config.min_saturation);
941 output.tag.set_property("TOLERANCE", config.tolerance);
942 output.tag.set_property("IN_SLOPE", config.in_slope);
943 output.tag.set_property("OUT_SLOPE", config.out_slope);
944 output.tag.set_property("ALPHA_OFFSET", config.alpha_offset);
945 output.tag.set_property("SPILL_THRESHOLD", config.spill_threshold);
946 output.tag.set_property("SPILL_AMOUNT", config.spill_amount);
947 output.tag.set_property("SHOW_MASK", config.show_mask);
949 output.tag.set_title("/CHROMAKEY_HSV");
951 output.append_newline();
952 output.terminate_string();
955 void ChromaKeyHSV::read_data(KeyFrame * keyframe)
959 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
961 while( !input.read_tag() ) {
962 if( input.tag.title_is("CHROMAKEY_HSV") ) {
963 config.red = input.tag.get_property("RED", config.red);
964 config.green = input.tag.get_property("GREEN", config.green);
965 config.blue = input.tag.get_property("BLUE", config.blue);
966 config.min_brightness =
967 input.tag.get_property("MIN_BRIGHTNESS", config.min_brightness);
968 config.max_brightness =
969 input.tag.get_property("MAX_BRIGHTNESS", config.max_brightness);
971 input.tag.get_property("SATURATION", config.saturation);
972 config.min_saturation =
973 input.tag.get_property("MIN_SATURATION", config.min_saturation);
975 input.tag.get_property("TOLERANCE", config.tolerance);
977 input.tag.get_property("IN_SLOPE", config.in_slope);
979 input.tag.get_property("OUT_SLOPE", config.out_slope);
980 config.alpha_offset =
981 input.tag.get_property("ALPHA_OFFSET", config.alpha_offset);
982 config.spill_threshold =
983 input.tag.get_property("SPILL_THRESHOLD",
984 config.spill_threshold);
985 config.spill_amount =
986 input.tag.get_property("SPILL_AMOUNT", config.spill_amount);
988 input.tag.get_property("SHOW_MASK", config.show_mask);
994 NEW_WINDOW_MACRO(ChromaKeyHSV, ChromaKeyWindow)
996 void ChromaKeyHSV::update_gui()
999 load_configuration();
1000 ChromaKeyWindow *window = (ChromaKeyWindow*)thread->window;
1001 window->lock_window();
1002 window->min_brightness->update(config.min_brightness);
1003 window->max_brightness->update(config.max_brightness);
1004 window->saturation->update(config.saturation);
1005 window->min_saturation->update(config.min_saturation);
1006 window->tolerance->update(config.tolerance);
1007 window->in_slope->update(config.in_slope);
1008 window->out_slope->update(config.out_slope);
1009 window->alpha_offset->update(config.alpha_offset);
1010 window->spill_threshold->update(config.spill_threshold);
1011 window->spill_amount->update(config.spill_amount);
1012 window->show_mask->update(config.show_mask);
1013 window->update_sample();
1014 window->unlock_window();
1021 int ChromaKeyHSV::handle_opengl()
1025 ChromaKeyHSV *plugin = this;
1028 static const char *yuv_shader =
1029 "const vec3 black = vec3(0.0, 0.5, 0.5);\n"
1031 "vec4 yuv_to_rgb(vec4 color)\n"
1033 YUV_TO_RGB_FRAG("color")
1037 "vec4 rgb_to_yuv(vec4 color)\n"
1039 RGB_TO_YUV_FRAG("color")
1043 static const char *rgb_shader =
1044 "const vec3 black = vec3(0.0, 0.0, 0.0);\n"
1046 "vec4 yuv_to_rgb(vec4 color)\n"
1050 "vec4 rgb_to_yuv(vec4 color)\n"
1055 static const char *hsv_shader =
1056 "vec4 rgb_to_hsv(vec4 color)\n"
1058 RGB_TO_HSV_FRAG("color")
1062 "vec4 hsv_to_rgb(vec4 color)\n"
1064 HSV_TO_RGB_FRAG("color")
1069 static const char *show_rgbmask_shader =
1070 "vec4 show_mask(vec4 color, vec4 color2)\n"
1072 " return vec4(1.0, 1.0, 1.0, min(color.a, color2.a));"
1075 static const char *show_yuvmask_shader =
1076 "vec4 show_mask(vec4 color, vec4 color2)\n"
1078 " return vec4(1.0, 0.5, 0.5, min(color.a, color2.a));"
1081 static const char *nomask_shader =
1082 "vec4 show_mask(vec4 color, vec4 color2)\n"
1084 " return vec4(color.rgb, min(color.a, color2.a));"
1087 extern unsigned char _binary_chromakey_sl_start[];
1088 static const char *shader = (char*)_binary_chromakey_sl_start;
1090 get_output()->to_texture();
1091 get_output()->enable_opengl();
1092 get_output()->init_screen();
1094 const char* shader_stack[] = { 0, 0, 0, 0, 0 };
1096 switch(get_output()->get_color_model())
1100 shader_stack[0] = yuv_shader;
1101 shader_stack[1] = hsv_shader;
1102 if(config.show_mask)
1103 shader_stack[2] = show_yuvmask_shader;
1105 shader_stack[2] = nomask_shader;
1106 shader_stack[3] = shader;
1110 shader_stack[0] = rgb_shader;
1111 shader_stack[1] = hsv_shader;
1112 if(config.show_mask)
1113 shader_stack[2] = show_rgbmask_shader;
1115 shader_stack[2] = nomask_shader;
1116 shader_stack[3] = shader;
1121 unsigned int frag = VFrame::make_shader(0,
1131 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
1132 glUniform1f(glGetUniformLocation(frag, "red"), red);
1133 glUniform1f(glGetUniformLocation(frag, "green"), green);
1134 glUniform1f(glGetUniformLocation(frag, "blue"), blue);
1135 glUniform1f(glGetUniformLocation(frag, "in_slope"), in_slope);
1136 glUniform1f(glGetUniformLocation(frag, "out_slope"), out_slope);
1137 glUniform1f(glGetUniformLocation(frag, "tolerance"), tolerance);
1138 glUniform1f(glGetUniformLocation(frag, "tolerance_in"), tolerance_in);
1139 glUniform1f(glGetUniformLocation(frag, "tolerance_out"), tolerance_out);
1140 glUniform1f(glGetUniformLocation(frag, "sat"), sat);
1141 glUniform1f(glGetUniformLocation(frag, "min_s"), min_s);
1142 glUniform1f(glGetUniformLocation(frag, "min_s_in"), min_s_in);
1143 glUniform1f(glGetUniformLocation(frag, "min_s_out"), min_s_out);
1144 glUniform1f(glGetUniformLocation(frag, "min_v"), min_v);
1145 glUniform1f(glGetUniformLocation(frag, "min_v_in"), min_v_in);
1146 glUniform1f(glGetUniformLocation(frag, "min_v_out"), min_v_out);
1147 glUniform1f(glGetUniformLocation(frag, "max_v"), max_v);
1148 glUniform1f(glGetUniformLocation(frag, "max_v_in"), max_v_in);
1149 glUniform1f(glGetUniformLocation(frag, "max_v_out"), max_v_out);
1150 glUniform1f(glGetUniformLocation(frag, "spill_threshold"), spill_threshold);
1151 glUniform1f(glGetUniformLocation(frag, "spill_amount"), spill_amount);
1152 glUniform1f(glGetUniformLocation(frag, "alpha_offset"), alpha_offset);
1153 glUniform1f(glGetUniformLocation(frag, "hue_key"), hue_key);
1154 glUniform1f(glGetUniformLocation(frag, "saturation_key"), saturation_key);
1155 glUniform1f(glGetUniformLocation(frag, "value_key"), value_key);
1159 get_output()->bind_texture(0);
1160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1163 if(BC_CModels::components(get_output()->get_color_model()) == 3)
1166 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1167 get_output()->clear_pbuffer();
1169 get_output()->draw_texture();
1172 get_output()->set_opengl_state(VFrame::SCREEN);
1173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1175 glDisable(GL_BLEND);