1 #include "bcdisplayinfo.h"
10 #include "loadbalance.h"
11 #include "picon_png.h"
12 #include "playback3d.h"
13 #include "plugincolors.h"
14 #include "pluginvclient.h"
23 ChromaKeyConfig::ChromaKeyConfig ()
29 min_brightness = 50.0;
30 max_brightness = 100.0;
33 min_saturation = 50.0;
39 spill_threshold = 0.0;
48 ChromaKeyConfig::copy_from (ChromaKeyConfig & src)
53 spill_threshold = src.spill_threshold;
54 spill_amount = src.spill_amount;
55 min_brightness = src.min_brightness;
56 max_brightness = src.max_brightness;
57 saturation = src.saturation;
58 min_saturation = src.min_saturation;
59 tolerance = src.tolerance;
60 in_slope = src.in_slope;
61 out_slope = src.out_slope;
62 alpha_offset = src.alpha_offset;
63 show_mask = src.show_mask;
67 ChromaKeyConfig::equivalent (ChromaKeyConfig & src)
69 return (EQUIV (red, src.red) &&
70 EQUIV (green, src.green) &&
71 EQUIV (blue, src.blue) &&
72 EQUIV (spill_threshold, src.spill_threshold) &&
73 EQUIV (spill_amount, src.spill_amount) &&
74 EQUIV (min_brightness, src.min_brightness) &&
75 EQUIV (max_brightness, src.max_brightness) &&
76 EQUIV (saturation, src.saturation) &&
77 EQUIV (min_saturation, src.min_saturation) &&
78 EQUIV (tolerance, src.tolerance) &&
79 EQUIV (in_slope, src.in_slope) &&
80 EQUIV (out_slope, src.out_slope) &&
81 EQUIV (show_mask, src.show_mask) &&
82 EQUIV (alpha_offset, src.alpha_offset));
86 ChromaKeyConfig::interpolate (ChromaKeyConfig & prev,
87 ChromaKeyConfig & next,
89 int64_t next_frame, int64_t current_frame)
92 (double) (current_frame - prev_frame) / (next_frame - prev_frame);
94 (double) (next_frame - current_frame) / (next_frame - prev_frame);
96 this->red = prev.red * prev_scale + next.red * next_scale;
97 this->green = prev.green * prev_scale + next.green * next_scale;
98 this->blue = prev.blue * prev_scale + next.blue * next_scale;
99 this->spill_threshold =
100 prev.spill_threshold * prev_scale + next.spill_threshold * next_scale;
102 prev.spill_amount * prev_scale + next.tolerance * next_scale;
103 this->min_brightness =
104 prev.min_brightness * prev_scale + next.min_brightness * next_scale;
105 this->max_brightness =
106 prev.max_brightness * prev_scale + next.max_brightness * next_scale;
108 prev.saturation * prev_scale + next.saturation * next_scale;
109 this->min_saturation =
110 prev.min_saturation * prev_scale + next.min_saturation * next_scale;
111 this->tolerance = prev.tolerance * prev_scale + next.tolerance * next_scale;
112 this->in_slope = prev.in_slope * prev_scale + next.in_slope * next_scale;
113 this->out_slope = prev.out_slope * prev_scale + next.out_slope * next_scale;
115 prev.alpha_offset * prev_scale + next.alpha_offset * next_scale;
116 this->show_mask = next.show_mask;
121 ChromaKeyConfig::get_color ()
123 int red = (int) (CLIP (this->red, 0, 1) * 0xff);
124 int green = (int) (CLIP (this->green, 0, 1) * 0xff);
125 int blue = (int) (CLIP (this->blue, 0, 1) * 0xff);
126 return (red << 16) | (green << 8) | blue;
131 ChromaKeyWindow::ChromaKeyWindow (ChromaKeyHSV * plugin, int x, int y):BC_Window (plugin->gui_string,
142 this->plugin = plugin;
146 ChromaKeyWindow::~ChromaKeyWindow ()
152 ChromaKeyWindow::create_objects ()
154 int y = 10, y1, x1 = 0, x2 = 10;
159 int ymargin = get_text_height(MEDIUMFONT) + 5;
160 int ymargin2 = get_text_height(MEDIUMFONT) + 10;
162 add_subwindow (title = new BC_Title (x2, y, _("Color:")));
164 add_subwindow (color = new ChromaKeyColor (plugin, this, x, y + 25));
166 add_subwindow (sample =
167 new BC_SubWindow (x + color->get_w () + 10, y, 100, 50));
168 y += sample->get_h () + 10;
170 add_subwindow (use_colorpicker =
171 new ChromaKeyUseColorPicker (plugin, this, x, y));
172 y += use_colorpicker->get_h() + 10;
173 add_subwindow (show_mask = new ChromaKeyShowMask (plugin, x2, y));
174 y += show_mask->get_h() + 5;
176 add_subwindow(bar = new BC_Bar(x2, y, get_w() - x2 * 2));
177 y += bar->get_h() + 5;
179 add_subwindow (new BC_Title (x2, y, _("Key parameters:")));
181 add_subwindow (title = new BC_Title (x, y, _("Hue Tolerance:")));
182 if(title->get_w() > x1) x1 = title->get_w();
184 add_subwindow (title = new BC_Title (x, y, _("Min. Brightness:")));
185 if(title->get_w() > x1) x1 = title->get_w();
187 add_subwindow (title = new BC_Title (x, y, _("Max. Brightness:")));
188 if(title->get_w() > x1) x1 = title->get_w();
190 add_subwindow (title = new BC_Title (x, y, _("Saturation Offset:")));
191 if(title->get_w() > x1) x1 = title->get_w();
193 add_subwindow (title = new BC_Title (x, y, _("Min Saturation:")));
194 if(title->get_w() > x1) x1 = title->get_w();
197 add_subwindow(bar = new BC_Bar(x2, y, get_w() - x2 * 2));
198 y += bar->get_h() + 5;
199 add_subwindow (title = new BC_Title (x2, y, _("Mask tweaking:")));
201 add_subwindow (title = new BC_Title (x, y, _("In Slope:")));
202 if(title->get_w() > x1) x1 = title->get_w();
204 add_subwindow (title = new BC_Title (x, y, _("Out Slope:")));
205 if(title->get_w() > x1) x1 = title->get_w();
207 add_subwindow (title = new BC_Title (x, y, _("Alpha Offset:")));
208 if(title->get_w() > x1) x1 = title->get_w();
213 add_subwindow(bar = new BC_Bar(x2, y, get_w() - x2 * 2));
214 y += bar->get_h() + 5;
215 add_subwindow (title = new BC_Title (x2, y, _("Spill light control:")));
217 add_subwindow (title = new BC_Title (x, y, _("Spill Threshold:")));
218 if(title->get_w() > x1) x1 = title->get_w();
220 add_subwindow (title = new BC_Title (x, y, _("Spill Compensation:")));
221 if(title->get_w() > x1) x1 = title->get_w();
231 add_subwindow (tolerance = new ChromaKeyTolerance (plugin, x1, y));
233 add_subwindow (min_brightness = new ChromaKeyMinBrightness (plugin, x1, y));
235 add_subwindow (max_brightness = new ChromaKeyMaxBrightness (plugin, x1, y));
237 add_subwindow (saturation = new ChromaKeySaturation (plugin, x1, y));
239 add_subwindow (min_saturation = new ChromaKeyMinSaturation (plugin, x1, y));
242 y += bar->get_h() + 5;
244 add_subwindow (in_slope = new ChromaKeyInSlope (plugin, x1, y));
246 add_subwindow (out_slope = new ChromaKeyOutSlope (plugin, x1, y));
248 add_subwindow (alpha_offset = new ChromaKeyAlphaOffset (plugin, x1, y));
251 y += bar->get_h() + 5;
253 add_subwindow (spill_threshold = new ChromaKeySpillThreshold (plugin, x1, y));
255 add_subwindow (spill_amount = new ChromaKeySpillAmount (plugin, x1, y));
257 color_thread = new ChromaKeyColorThread (plugin, this);
265 ChromaKeyWindow::update_sample ()
267 sample->set_color (plugin->config.get_color ());
268 sample->draw_box (0, 0, sample->get_w (), sample->get_h ());
269 sample->set_color (BLACK);
270 sample->draw_rectangle (0, 0, sample->get_w (), sample->get_h ());
276 WINDOW_CLOSE_EVENT (ChromaKeyWindow)
277 ChromaKeyColor::ChromaKeyColor (ChromaKeyHSV * plugin,
278 ChromaKeyWindow * gui, int x, int y):
279 BC_GenericButton (x, y, _("Color..."))
281 this->plugin = plugin;
286 ChromaKeyColor::handle_event ()
288 gui->color_thread->start_window (plugin->config.get_color (), 0xff);
295 ChromaKeyMinBrightness::ChromaKeyMinBrightness (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
298 200, 200, (float) 0, (float) 100, plugin->config.min_brightness)
300 this->plugin = plugin;
301 set_precision (0.01);
305 ChromaKeyMinBrightness::handle_event ()
307 plugin->config.min_brightness = get_value ();
308 plugin->send_configure_change ();
312 ChromaKeyMaxBrightness::ChromaKeyMaxBrightness (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
315 200, 200, (float) 0, (float) 100, plugin->config.max_brightness)
317 this->plugin = plugin;
318 set_precision (0.01);
322 ChromaKeyMaxBrightness::handle_event ()
324 plugin->config.max_brightness = get_value ();
325 plugin->send_configure_change ();
330 ChromaKeySaturation::ChromaKeySaturation (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
332 0, 200, 200, (float) 0, (float) 100, plugin->config.saturation)
334 this->plugin = plugin;
335 set_precision (0.01);
339 ChromaKeySaturation::handle_event ()
341 plugin->config.saturation = get_value ();
342 plugin->send_configure_change ();
346 ChromaKeyMinSaturation::ChromaKeyMinSaturation (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
349 200, 200, (float) 0, (float) 100, plugin->config.min_saturation)
351 this->plugin = plugin;
352 set_precision (0.01);
356 ChromaKeyMinSaturation::handle_event ()
358 plugin->config.min_saturation = get_value ();
359 plugin->send_configure_change ();
364 ChromaKeyTolerance::ChromaKeyTolerance (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
366 0, 200, 200, (float) 0, (float) 100, plugin->config.tolerance)
368 this->plugin = plugin;
369 set_precision (0.01);
373 ChromaKeyTolerance::handle_event ()
375 plugin->config.tolerance = get_value ();
376 plugin->send_configure_change ();
382 ChromaKeyInSlope::ChromaKeyInSlope (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
384 0, 200, 200, (float) 0, (float) 20, plugin->config.in_slope)
386 this->plugin = plugin;
387 set_precision (0.01);
391 ChromaKeyInSlope::handle_event ()
393 plugin->config.in_slope = get_value ();
394 plugin->send_configure_change ();
399 ChromaKeyOutSlope::ChromaKeyOutSlope (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
401 0, 200, 200, (float) 0, (float) 20, plugin->config.out_slope)
403 this->plugin = plugin;
404 set_precision (0.01);
408 ChromaKeyOutSlope::handle_event ()
410 plugin->config.out_slope = get_value ();
411 plugin->send_configure_change ();
416 ChromaKeyAlphaOffset::ChromaKeyAlphaOffset (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
419 200, 200, (float) -100, (float) 100, plugin->config.alpha_offset)
421 this->plugin = plugin;
422 set_precision (0.01);
426 ChromaKeyAlphaOffset::handle_event ()
428 plugin->config.alpha_offset = get_value ();
429 plugin->send_configure_change ();
433 ChromaKeyShowMask::ChromaKeyShowMask (ChromaKeyHSV * plugin, int x, int y):BC_CheckBox (x, y, plugin->config.show_mask,
437 this->plugin = plugin;
442 ChromaKeyShowMask::handle_event ()
444 plugin->config.show_mask = get_value ();
445 plugin->send_configure_change ();
449 ChromaKeyUseColorPicker::ChromaKeyUseColorPicker (ChromaKeyHSV * plugin, ChromaKeyWindow * gui, int x, int y):BC_GenericButton (x, y,
451 ("Use color picker"))
453 this->plugin = plugin;
458 ChromaKeyUseColorPicker::handle_event ()
460 plugin->config.red = plugin->get_red ();
461 plugin->config.green = plugin->get_green ();
462 plugin->config.blue = plugin->get_blue ();
463 gui->update_sample ();
464 plugin->send_configure_change ();
470 ChromaKeySpillThreshold::ChromaKeySpillThreshold (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
473 200, 200, (float) 0, (float) 100, plugin->config.spill_threshold)
475 this->plugin = plugin;
476 set_precision (0.01);
480 ChromaKeySpillThreshold::handle_event ()
482 plugin->config.spill_threshold = get_value ();
483 plugin->send_configure_change ();
487 ChromaKeySpillAmount::ChromaKeySpillAmount (ChromaKeyHSV * plugin, int x, int y):BC_FSlider (x,
489 0, 200, 200, (float) 0, (float) 100, plugin->config.spill_amount)
491 this->plugin = plugin;
492 set_precision (0.01);
496 ChromaKeySpillAmount::handle_event ()
498 plugin->config.spill_amount = get_value ();
499 plugin->send_configure_change ();
508 ChromaKeyColorThread::ChromaKeyColorThread (ChromaKeyHSV * plugin, ChromaKeyWindow * gui):ColorThread (1,
512 this->plugin = plugin;
517 ChromaKeyColorThread::handle_new_color (int output, int alpha)
519 plugin->config.red = (float) (output & 0xff0000) / 0xff0000;
520 plugin->config.green = (float) (output & 0xff00) / 0xff00;
521 plugin->config.blue = (float) (output & 0xff) / 0xff;
522 gui->update_sample ();
523 plugin->send_configure_change ();
534 PLUGIN_THREAD_OBJECT (ChromaKeyHSV, ChromaKeyThread, ChromaKeyWindow) ChromaKeyServer::ChromaKeyServer (ChromaKeyHSV * plugin):LoadServer (plugin->PluginClient::smp + 1,
535 plugin->PluginClient::smp +
538 this->plugin = plugin;
542 ChromaKeyServer::init_packages ()
544 for (int i = 0; i < get_total_packages (); i++)
546 ChromaKeyPackage *pkg = (ChromaKeyPackage *) get_package (i);
547 pkg->y1 = plugin->input->get_h () * i / get_total_packages ();
548 pkg->y2 = plugin->input->get_h () * (i + 1) / get_total_packages ();
553 ChromaKeyServer::new_client ()
555 return new ChromaKeyUnit (plugin, this);
559 ChromaKeyServer::new_package ()
561 return new ChromaKeyPackage;
566 ChromaKeyPackage::ChromaKeyPackage ():LoadPackage ()
570 ChromaKeyUnit::ChromaKeyUnit (ChromaKeyHSV * plugin, ChromaKeyServer * server):LoadClient
573 this->plugin = plugin;
579 #define ABS(a) ((a<0)?-(a):a)
580 // Reuse as much as possible in the opengl version
581 #define OUTER_VARIABLES \
582 float red = plugin->config.red; \
583 float green = plugin->config.green; \
584 float blue = plugin->config.blue; \
586 float in_slope = plugin->config.in_slope / 100; \
587 float out_slope = plugin->config.out_slope / 100; \
589 float tolerance = plugin->config.tolerance / 100; \
590 float tolerance_in = tolerance - in_slope; \
591 float tolerance_out = tolerance + out_slope; \
593 float sat = plugin->config.saturation / 100; \
594 float min_s = plugin->config.min_saturation / 100; \
595 float min_s_in = min_s + in_slope; \
596 float min_s_out = min_s - out_slope; \
598 float min_v = plugin->config.min_brightness / 100; \
599 float min_v_in = min_v + in_slope; \
600 float min_v_out = min_v - out_slope; \
602 float max_v = plugin->config.max_brightness / 100; \
603 float max_v_in = max_v - in_slope; \
604 float max_v_out = max_v + out_slope; \
606 float spill_threshold = plugin->config.spill_threshold / 100; \
607 float spill_amount = 1.0 - plugin->config.spill_amount / 100; \
609 float alpha_offset = plugin->config.alpha_offset / 100; \
611 /* Convert RGB key to HSV key */ \
612 float hue_key, saturation_key, value_key; \
613 HSV::rgb_to_hsv(red, \
621 template <typename component_type>
622 void ChromaKeyUnit::process_chromakey(int components,
625 ChromaKeyPackage *pkg)
629 int w = plugin->input->get_w();
631 for (int i = pkg->y1; i < pkg->y2; i++)
633 component_type *row = (component_type *) plugin->input->get_rows ()[i];
635 for (int j = 0; j < w; j++)
639 float r = (float) row[0] / max;
640 float g = (float) row[1] / max;
641 float b = (float) row[2] / max;
645 float av = 1, ah = 1, as = 1, avm = 1;
646 bool has_match = true;
650 /* Convert pixel to RGB float */
654 YUV::yuv_to_rgb_f (r, g, b, y, u - 0.5, v - 0.5);
657 HSV::rgb_to_hsv (r, g, b, h, s, v);
659 // First, test if the hue is in range
663 if (ABS (h - hue_key) < tolerance_in * 180)
666 if ((out_slope != 0) && (ABS (h - hue_key) < tolerance * 180))
667 /* we scale alpha between 0 and 1/2 */
668 ah = ABS (h - hue_key) / tolerance / 360;
670 if (ABS (h - hue_key) < tolerance_out * 180)
671 /* we scale alpha between 1/2 and 1 */
672 ah = ABS (h - hue_key) / tolerance_out / 360;
676 // Check if the saturation matches
681 else if (s - sat >= min_s_in)
683 else if ((out_slope != 0) && (s - sat > min_s))
684 as = (s - sat - min_s) / (min_s * 2);
685 else if (s - sat > min_s_out)
686 as = (s - sat - min_s_out) / (min_s_out * 2);
691 // Check if the value is more than the minimun
696 else if (v >= min_v_in)
698 else if ((out_slope != 0) && (v > min_v))
699 av = (v - min_v) / (min_v * 2);
700 else if (v > min_v_out)
701 av = (v - min_v_out) / (min_v_out * 2);
706 // Check if the value is less than the maximum
711 else if (v <= max_v_in)
713 else if ((out_slope != 0) && (v < max_v))
714 avm = (v - max_v) / (max_v * 2);
715 else if (v < max_v_out)
716 avm = (v - max_v_out) / (max_v_out * 2);
721 // If the color is part of the key, update the alpha channel
723 a = MAX (MAX (ah, av), MAX (as, avm));
725 // Spill light processing
726 if ((ABS (h - hue_key) < spill_threshold * 180) ||
727 ((ABS (h - hue_key) > 360)
728 && (ABS (h - hue_key) - 360 < spill_threshold * 180)))
730 s = s * spill_amount * ABS (h - hue_key) / (spill_threshold * 180);
732 HSV::hsv_to_rgb (r, g, b, h, s, v);
739 YUV::rgb_to_yuv_f (r, g, b, y, u, v);
743 row[0] = (component_type) ((float) y * max);
744 row[1] = (component_type) ((float) (u + 0.5) * max);
745 row[2] = (component_type) ((float) (v + 0.5) * max);
752 row[0] = (component_type) ((float) r * max);
753 row[1] = (component_type) ((float) g * max);
754 row[2] = (component_type) ((float) b * max);
761 if (plugin->config.show_mask)
766 row[0] = (component_type) ((float) a * max);
767 row[1] = (component_type) ((float) max / 2);
768 row[2] = (component_type) ((float) max / 2);
772 row[0] = (component_type) ((float) a * max);
773 row[1] = (component_type) ((float) a * max);
774 row[2] = (component_type) ((float) a * max);
778 /* Multiply alpha and put back in frame */
781 row[3] = MIN ((component_type) (a * max), row[3]);
785 row[0] = (component_type) ((float) a * row[0]);
787 (component_type) ((float) a * (row[1] - (max / 2 + 1)) +
790 (component_type) ((float) a * (row[2] - (max / 2 + 1)) +
795 row[0] = (component_type) ((float) a * row[0]);
796 row[1] = (component_type) ((float) a * row[1]);
797 row[2] = (component_type) ((float) a * row[2]);
808 void ChromaKeyUnit::process_package(LoadPackage *package)
810 ChromaKeyPackage *pkg = (ChromaKeyPackage*)package;
813 switch(plugin->input->get_color_model())
816 process_chromakey<float> (3, 1.0, 0, pkg);
819 process_chromakey<float> ( 4, 1.0, 0, pkg);
822 process_chromakey<unsigned char> ( 3, 0xff, 0, pkg);
825 process_chromakey<unsigned char> ( 4, 0xff, 0, pkg);
828 process_chromakey<unsigned char> ( 3, 0xff, 1, pkg);
831 process_chromakey<unsigned char> ( 4, 0xff, 1, pkg);
834 process_chromakey<uint16_t> (3, 0xffff, 1, pkg);
836 case BC_YUVA16161616:
837 process_chromakey<uint16_t> (4, 0xffff, 1, pkg);
847 REGISTER_PLUGIN(ChromaKeyHSV)
851 ChromaKeyHSV::ChromaKeyHSV(PluginServer *server)
852 : PluginVClient(server)
854 PLUGIN_CONSTRUCTOR_MACRO
858 ChromaKeyHSV::~ChromaKeyHSV()
860 PLUGIN_DESTRUCTOR_MACRO
861 if(engine) delete engine;
865 int ChromaKeyHSV::process_buffer(VFrame *frame,
866 int64_t start_position,
869 load_configuration();
871 this->output = frame;
879 if(get_use_opengl()) return run_opengl();
882 if(!engine) engine = new ChromaKeyServer(this);
883 engine->process_packages();
888 char* ChromaKeyHSV::plugin_title() { return N_("Chroma key (HSV)"); }
889 int ChromaKeyHSV::is_realtime() { return 1; }
891 NEW_PICON_MACRO(ChromaKeyHSV)
893 LOAD_CONFIGURATION_MACRO(ChromaKeyHSV, ChromaKeyConfig)
895 int ChromaKeyHSV::load_defaults ()
897 char directory[BCTEXTLEN];
898 // set the default directory
899 sprintf (directory, "%schromakey-hsv.rc", BCASTDIR);
902 defaults = new BC_Hash (directory);
905 config.red = defaults->get ("RED", config.red);
906 config.green = defaults->get ("GREEN", config.green);
907 config.blue = defaults->get ("BLUE", config.blue);
908 config.min_brightness =
909 defaults->get ("MIN_BRIGHTNESS", config.min_brightness);
910 config.max_brightness =
911 defaults->get ("MAX_BRIGHTNESS", config.max_brightness);
912 config.saturation = defaults->get ("SATURATION", config.saturation);
913 config.min_saturation =
914 defaults->get ("MIN_SATURATION", config.min_saturation);
915 config.tolerance = defaults->get ("TOLERANCE", config.tolerance);
916 config.spill_threshold =
917 defaults->get ("SPILL_THRESHOLD", config.spill_threshold);
918 config.spill_amount = defaults->get ("SPILL_AMOUNT", config.spill_amount);
919 config.in_slope = defaults->get ("IN_SLOPE", config.in_slope);
920 config.out_slope = defaults->get ("OUT_SLOPE", config.out_slope);
921 config.alpha_offset = defaults->get ("ALPHA_OFFSET", config.alpha_offset);
922 config.show_mask = defaults->get ("SHOW_MASK", config.show_mask);
927 ChromaKeyHSV::save_defaults ()
929 defaults->update ("RED", config.red);
930 defaults->update ("GREEN", config.green);
931 defaults->update ("BLUE", config.blue);
932 defaults->update ("MIN_BRIGHTNESS", config.min_brightness);
933 defaults->update ("MAX_BRIGHTNESS", config.max_brightness);
934 defaults->update ("SATURATION", config.saturation);
935 defaults->update ("MIN_SATURATION", config.min_saturation);
936 defaults->update ("TOLERANCE", config.tolerance);
937 defaults->update ("IN_SLOPE", config.in_slope);
938 defaults->update ("OUT_SLOPE", config.out_slope);
939 defaults->update ("ALPHA_OFFSET", config.alpha_offset);
940 defaults->update ("SPILL_THRESHOLD", config.spill_threshold);
941 defaults->update ("SPILL_AMOUNT", config.spill_amount);
942 defaults->update ("SHOW_MASK", config.show_mask);
948 ChromaKeyHSV::save_data (KeyFrame * keyframe)
951 output.set_shared_string (keyframe->data, MESSAGESIZE);
952 output.tag.set_title ("CHROMAKEY_HSV");
953 output.tag.set_property ("RED", config.red);
954 output.tag.set_property ("GREEN", config.green);
955 output.tag.set_property ("BLUE", config.blue);
956 output.tag.set_property ("MIN_BRIGHTNESS", config.min_brightness);
957 output.tag.set_property ("MAX_BRIGHTNESS", config.max_brightness);
958 output.tag.set_property ("SATURATION", config.saturation);
959 output.tag.set_property ("MIN_SATURATION", config.min_saturation);
960 output.tag.set_property ("TOLERANCE", config.tolerance);
961 output.tag.set_property ("IN_SLOPE", config.in_slope);
962 output.tag.set_property ("OUT_SLOPE", config.out_slope);
963 output.tag.set_property ("ALPHA_OFFSET", config.alpha_offset);
964 output.tag.set_property ("SPILL_THRESHOLD", config.spill_threshold);
965 output.tag.set_property ("SPILL_AMOUNT", config.spill_amount);
966 output.tag.set_property ("SHOW_MASK", config.show_mask);
967 output.append_tag ();
968 output.terminate_string ();
972 ChromaKeyHSV::read_data (KeyFrame * keyframe)
976 input.set_shared_string (keyframe->data, strlen (keyframe->data));
978 while (!input.read_tag ())
980 if (input.tag.title_is ("CHROMAKEY_HSV"))
982 config.red = input.tag.get_property ("RED", config.red);
983 config.green = input.tag.get_property ("GREEN", config.green);
984 config.blue = input.tag.get_property ("BLUE", config.blue);
985 config.min_brightness =
986 input.tag.get_property ("MIN_BRIGHTNESS", config.min_brightness);
987 config.max_brightness =
988 input.tag.get_property ("MAX_BRIGHTNESS", config.max_brightness);
990 input.tag.get_property ("SATURATION", config.saturation);
991 config.min_saturation =
992 input.tag.get_property ("MIN_SATURATION", config.min_saturation);
994 input.tag.get_property ("TOLERANCE", config.tolerance);
996 input.tag.get_property ("IN_SLOPE", config.in_slope);
998 input.tag.get_property ("OUT_SLOPE", config.out_slope);
999 config.alpha_offset =
1000 input.tag.get_property ("ALPHA_OFFSET", config.alpha_offset);
1001 config.spill_threshold =
1002 input.tag.get_property ("SPILL_THRESHOLD",
1003 config.spill_threshold);
1004 config.spill_amount =
1005 input.tag.get_property ("SPILL_AMOUNT", config.spill_amount);
1007 input.tag.get_property ("SHOW_MASK", config.show_mask);
1013 SHOW_GUI_MACRO(ChromaKeyHSV, ChromaKeyThread)
1015 SET_STRING_MACRO(ChromaKeyHSV)
1017 RAISE_WINDOW_MACRO(ChromaKeyHSV)
1019 void ChromaKeyHSV::update_gui ()
1023 load_configuration ();
1024 thread->window->lock_window ();
1025 thread->window->min_brightness->update (config.min_brightness);
1026 thread->window->max_brightness->update (config.max_brightness);
1027 thread->window->saturation->update (config.saturation);
1028 thread->window->min_saturation->update (config.min_saturation);
1029 thread->window->tolerance->update (config.tolerance);
1030 thread->window->in_slope->update (config.in_slope);
1031 thread->window->out_slope->update (config.out_slope);
1032 thread->window->alpha_offset->update (config.alpha_offset);
1033 thread->window->spill_threshold->update (config.spill_threshold);
1034 thread->window->spill_amount->update (config.spill_amount);
1035 thread->window->show_mask->update (config.show_mask);
1036 thread->window->update_sample ();
1037 thread->window->unlock_window ();
1044 int ChromaKeyHSV::handle_opengl()
1048 ChromaKeyHSV *plugin = this;
1051 static char *yuv_shader =
1052 "const vec3 black = vec3(0.0, 0.5, 0.5);\n"
1054 "vec4 yuv_to_rgb(vec4 color)\n"
1056 YUV_TO_RGB_FRAG("color")
1060 "vec4 rgb_to_yuv(vec4 color)\n"
1062 RGB_TO_YUV_FRAG("color")
1066 static char *rgb_shader =
1067 "const vec3 black = vec3(0.0, 0.0, 0.0);\n"
1069 "vec4 yuv_to_rgb(vec4 color)\n"
1073 "vec4 rgb_to_yuv(vec4 color)\n"
1078 static char *hsv_shader =
1079 "vec4 rgb_to_hsv(vec4 color)\n"
1081 RGB_TO_HSV_FRAG("color")
1085 "vec4 hsv_to_rgb(vec4 color)\n"
1087 HSV_TO_RGB_FRAG("color")
1092 static char *show_rgbmask_shader =
1093 "vec4 show_mask(vec4 color, vec4 color2)\n"
1095 " return vec4(1.0, 1.0, 1.0, min(color.a, color2.a));"
1098 static char *show_yuvmask_shader =
1099 "vec4 show_mask(vec4 color, vec4 color2)\n"
1101 " return vec4(1.0, 0.5, 0.5, min(color.a, color2.a));"
1104 static char *nomask_shader =
1105 "vec4 show_mask(vec4 color, vec4 color2)\n"
1107 " return vec4(color.rgb, min(color.a, color2.a));"
1110 extern unsigned char _binary_chromakey_sl_start[];
1111 static char *shader = (char*)_binary_chromakey_sl_start;
1114 get_output()->to_texture();
1115 get_output()->enable_opengl();
1116 get_output()->init_screen();
1119 char *shader_stack[] = { 0, 0, 0, 0, 0 };
1122 switch(get_output()->get_color_model())
1126 shader_stack[0] = yuv_shader;
1127 shader_stack[1] = hsv_shader;
1128 if(config.show_mask)
1129 shader_stack[2] = show_yuvmask_shader;
1131 shader_stack[2] = nomask_shader;
1132 shader_stack[3] = shader;
1136 shader_stack[0] = rgb_shader;
1137 shader_stack[1] = hsv_shader;
1138 if(config.show_mask)
1139 shader_stack[2] = show_rgbmask_shader;
1141 shader_stack[2] = nomask_shader;
1142 shader_stack[3] = shader;
1148 unsigned int frag = VFrame::make_shader(0,
1159 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
1160 glUniform1f(glGetUniformLocation(frag, "red"), red);
1161 glUniform1f(glGetUniformLocation(frag, "green"), green);
1162 glUniform1f(glGetUniformLocation(frag, "blue"), blue);
1163 glUniform1f(glGetUniformLocation(frag, "in_slope"), in_slope);
1164 glUniform1f(glGetUniformLocation(frag, "out_slope"), out_slope);
1165 glUniform1f(glGetUniformLocation(frag, "tolerance"), tolerance);
1166 glUniform1f(glGetUniformLocation(frag, "tolerance_in"), tolerance_in);
1167 glUniform1f(glGetUniformLocation(frag, "tolerance_out"), tolerance_out);
1168 glUniform1f(glGetUniformLocation(frag, "sat"), sat);
1169 glUniform1f(glGetUniformLocation(frag, "min_s"), min_s);
1170 glUniform1f(glGetUniformLocation(frag, "min_s_in"), min_s_in);
1171 glUniform1f(glGetUniformLocation(frag, "min_s_out"), min_s_out);
1172 glUniform1f(glGetUniformLocation(frag, "min_v"), min_v);
1173 glUniform1f(glGetUniformLocation(frag, "min_v_in"), min_v_in);
1174 glUniform1f(glGetUniformLocation(frag, "min_v_out"), min_v_out);
1175 glUniform1f(glGetUniformLocation(frag, "max_v"), max_v);
1176 glUniform1f(glGetUniformLocation(frag, "max_v_in"), max_v_in);
1177 glUniform1f(glGetUniformLocation(frag, "max_v_out"), max_v_out);
1178 glUniform1f(glGetUniformLocation(frag, "spill_threshold"), spill_threshold);
1179 glUniform1f(glGetUniformLocation(frag, "spill_amount"), spill_amount);
1180 glUniform1f(glGetUniformLocation(frag, "alpha_offset"), alpha_offset);
1181 glUniform1f(glGetUniformLocation(frag, "hue_key"), hue_key);
1182 glUniform1f(glGetUniformLocation(frag, "saturation_key"), saturation_key);
1183 glUniform1f(glGetUniformLocation(frag, "value_key"), value_key);
1188 get_output()->bind_texture(0);
1189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1192 if(cmodel_components(get_output()->get_color_model()) == 3)
1195 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1196 get_output()->clear_pbuffer();
1198 get_output()->draw_texture();
1202 get_output()->set_opengl_state(VFrame::SCREEN);
1203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1205 glDisable(GL_BLEND);