2 #include "colormodels.h"
6 #include "holowindow.h"
9 #include "plugincolors.h"
16 REGISTER_PLUGIN(HoloMain)
27 HoloConfig::HoloConfig()
37 HoloMain::HoloMain(PluginServer *server)
38 : PluginVClient(server)
44 PLUGIN_CONSTRUCTOR_MACRO
49 PLUGIN_DESTRUCTOR_MACRO
63 char* HoloMain::plugin_title() { return N_("HolographicTV"); }
64 int HoloMain::is_realtime() { return 1; }
66 VFrame* HoloMain::new_picon()
68 return new VFrame(picon_png);
71 int HoloMain::load_defaults()
76 int HoloMain::save_defaults()
81 void HoloMain::load_configuration()
86 void HoloMain::save_data(KeyFrame *keyframe)
90 void HoloMain::read_data(KeyFrame *keyframe)
94 void HoloMain::reconfigure()
98 effecttv->image_set_threshold_y(config.threshold);
102 #define ADD_FRAMES(type, components) \
104 type **input_rows = (type**)input->get_rows(); \
105 type **output_rows = (type**)output->get_rows(); \
106 int w = input->get_w(); \
107 int h = input->get_h(); \
109 for(int i = 0; i < h; i++) \
111 type *output_row = (type*)output_rows[i]; \
112 type *input_row = (type*)input_rows[i]; \
114 for(int j = 0; j < w; j++) \
116 for(int k = 0; k < 3; k++) \
118 if(sizeof(type) == 4) \
120 int in_temp = (int)(*input_row * 0xffff); \
121 int out_temp = (int)(*output_row * 0xffff); \
122 int temp = (in_temp & out_temp) + \
123 ((in_temp ^ out_temp) >> 1); \
124 *output_row = (type)temp / 0xffff; \
128 *output_row = ((uint16_t)*input_row & (uint16_t)*output_row) + \
129 (((uint16_t)*input_row ^ (uint16_t)*output_row) >> 1); \
135 if(components == 4) \
145 // Add input to output and store result in output
146 void HoloMain::add_frames(VFrame *output, VFrame *input)
148 switch(output->get_color_model())
152 ADD_FRAMES(uint8_t, 3);
155 ADD_FRAMES(float, 3);
158 ADD_FRAMES(float, 4);
162 ADD_FRAMES(uint8_t, 4);
166 ADD_FRAMES(uint16_t, 3);
168 case BC_RGBA16161616:
169 case BC_YUVA16161616:
170 ADD_FRAMES(uint16_t, 4);
175 void HoloMain::set_background()
178 * grab 4 frames and composite them to get a quality background image
181 * For Cinelerra, we make every frame a holograph and expect the user to
189 /* step 1: grab frame-1 to buffer-1 */
190 // tmp = new VFrame(0,
191 // input_ptr->get_w(),
192 // input_ptr->get_h(),
193 // project_color_model);
194 bgimage->copy_from(input_ptr);
198 /* step 2: add frame-2 to buffer-1 */
199 add_frames(bgimage, input_ptr);
203 /* step 3: grab frame-3 to buffer-2 */
204 tmp->copy_from(input_ptr);
208 /* step 4: add frame-4 to buffer-2 */
209 add_frames(tmp, input_ptr);
213 /* step 5: add buffer-3 to buffer-1 */
214 add_frames(bgimage, tmp);
216 effecttv->image_bgset_y(bgimage);
225 int HoloMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
227 this->input_ptr = input_ptr;
228 this->output_ptr = output_ptr;
233 load_configuration();
241 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
242 bgimage = new VFrame(0,
245 input_ptr->get_color_model());
247 for(int i = 0; i < 256; i++)
249 noisepattern[i] = (i * i * i / 40000)* i / 256;
252 holo_server = new HoloServer(this, 1, 1);
260 holo_server->process_packages();
263 if(total >= config.recycle * project_frame_rate)
269 int HoloMain::show_gui()
271 load_configuration();
272 thread = new HoloThread(this);
277 int HoloMain::set_string()
279 if(thread) thread->window->set_title(gui_string);
283 void HoloMain::raise_window()
287 thread->window->raise_window();
288 thread->window->flush();
295 HoloServer::HoloServer(HoloMain *plugin, int total_clients, int total_packages)
296 : LoadServer(total_clients, total_packages)
298 this->plugin = plugin;
302 LoadClient* HoloServer::new_client()
304 return new HoloClient(this);
310 LoadPackage* HoloServer::new_package()
312 return new HoloPackage;
317 void HoloServer::init_packages()
319 for(int i = 0; i < get_total_packages(); i++)
321 HoloPackage *package = (HoloPackage*)get_package(i);
322 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
323 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
334 HoloClient::HoloClient(HoloServer *server)
337 this->plugin = server->plugin;
342 void HoloClient::process_package(LoadPackage *package)
346 HoloPackage *local_package = (HoloPackage*)package;
347 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
348 unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
349 int width = plugin->input_ptr->get_w();
350 int height = local_package->row2 - local_package->row1;
355 diff = plugin->effecttv->image_diff_filter(plugin->effecttv->image_bgsubtract_y(input_rows,
356 plugin->input_ptr->get_color_model()));
363 // Convert discrete channels to a single 24 bit number
364 #define STORE_PIXEL(type, components, dest, src, is_yuv) \
365 if(sizeof(type) == 4) \
367 int r = (int)(src[0] * 0xff); \
368 int g = (int)(src[1] * 0xff); \
369 int b = (int)(src[2] * 0xff); \
373 dest = (r << 16) | (g << 8) | b; \
376 if(sizeof(type) == 2) \
380 int r = (int)src[0] >> 8; \
381 int g = (int)src[1] >> 8; \
382 int b = (int)src[2] >> 8; \
383 plugin->yuv->yuv_to_rgb_8(r, g, b); \
384 dest = (r << 16) | (g << 8) | b; \
388 dest = (((uint32_t)src[0] << 8) & 0xff0000) | \
389 ((uint32_t)src[1] & 0xff00) | \
390 ((uint32_t)src[2]) >> 8; \
397 int r = (int)src[0]; \
398 int g = (int)src[1]; \
399 int b = (int)src[2]; \
400 plugin->yuv->yuv_to_rgb_8(r, g, b); \
401 dest = (r << 16) | (g << 8) | b; \
405 dest = ((uint32_t)src[0] << 16) | \
406 ((uint32_t)src[1] << 8) | \
414 #define HOLO_CORE(type, components, is_yuv) \
415 for(y = 1; y < height - 1; y++) \
417 type *src = (type*)input_rows[y]; \
418 type *bg = (type*)plugin->bgimage->get_rows()[y]; \
419 type *dest = (type*)output_rows[y]; \
423 if(((y + phase) & 0x7f) < 0x58) \
425 for(x = 0 ; x < width; x++) \
429 STORE_PIXEL(type, components, s, src, is_yuv); \
432 ((s & 0xff00) >> 7) + \
433 ((s & 0xff0000) >> 16); \
434 t += plugin->noisepattern[EffectTV::fastrand() >> 24]; \
436 r = ((s & 0xff0000) >> 17) + t; \
437 g = ((s & 0xff00) >> 8) + t; \
438 b = (s & 0xff) + t; \
440 r = (r >> 1) - 100; \
441 g = (g >> 1) - 100; \
447 STORE_PIXEL(type, components, s, bg, is_yuv); \
449 r += (s & 0xff0000) >> 17; \
450 g += (s & 0xff00) >> 9; \
451 b += ((s & 0xff) >> 1) + 40; \
453 if(r > 255) r = 255; \
454 if(g > 255) g = 255; \
455 if(b > 255) b = 255; \
457 if(is_yuv) plugin->yuv->rgb_to_yuv_8(r, g, b); \
458 if(sizeof(type) == 4) \
460 dest[0] = (type)r / 0xff; \
461 dest[1] = (type)g / 0xff; \
462 dest[2] = (type)b / 0xff; \
465 if(sizeof(type) == 2) \
467 dest[0] = (r << 8) | r; \
468 dest[1] = (g << 8) | g; \
469 dest[2] = (b << 8) | b; \
487 dest += components; \
493 for(x = 0; x < width; x++) \
497 STORE_PIXEL(type, components, s, src, is_yuv); \
500 t = (s & 0xff) + ((s & 0xff00) >> 6) + ((s & 0xff0000) >> 16); \
501 t += plugin->noisepattern[EffectTV::fastrand() >> 24]; \
503 r = ((s & 0xff0000) >> 16) + t; \
504 g = ((s & 0xff00) >> 8) + t; \
505 b = (s & 0xff) + t; \
507 r = (r >> 1) - 100; \
508 g = (g >> 1) - 100; \
514 STORE_PIXEL(type, components, s, bg, is_yuv); \
516 r += ((s & 0xff0000) >> 17) + 10; \
517 g += ((s & 0xff00) >> 9) + 10; \
518 b += ((s & 0xff) >> 1) + 40; \
520 if(r > 255) r = 255; \
521 if(g > 255) g = 255; \
522 if(b > 255) b = 255; \
524 if(is_yuv) plugin->yuv->rgb_to_yuv_8(r, g, b); \
525 if(sizeof(type) == 4) \
527 dest[0] = (type)r / 0xff; \
528 dest[1] = (type)g / 0xff; \
529 dest[2] = (type)b / 0xff; \
532 if(sizeof(type) == 2) \
534 dest[0] = (r << 8) | r; \
535 dest[1] = (g << 8) | g; \
536 dest[2] = (b << 8) | b; \
554 dest += components; \
563 switch(plugin->input_ptr->get_color_model())
566 HOLO_CORE(uint8_t, 3, 0);
569 HOLO_CORE(float, 3, 0);
572 HOLO_CORE(uint8_t, 3, 1);
575 HOLO_CORE(float, 4, 0);
578 HOLO_CORE(uint8_t, 4, 0);
581 HOLO_CORE(uint8_t, 4, 1);
584 HOLO_CORE(uint16_t, 3, 0);
587 HOLO_CORE(uint16_t, 3, 1);
589 case BC_RGBA16161616:
590 HOLO_CORE(uint16_t, 4, 0);
592 case BC_YUVA16161616:
593 HOLO_CORE(uint16_t, 4, 1);
604 HoloPackage::HoloPackage()