1 #include "bcdisplayinfo.h"
7 #include "loadbalance.h"
9 #include "pluginvclient.h"
17 #define _(String) gettext(String)
18 #define gettext_noop(String) String
19 #define N_(String) gettext_noop (String)
23 // Algorithm by Torsten Martinsen
24 // Ported to Cinelerra by Heroine Virtual Ltd.
37 void copy_from(OilConfig &src);
38 int equivalent(OilConfig &src);
39 void interpolate(OilConfig &prev,
48 class OilRadius : public BC_FSlider
51 OilRadius(OilEffect *plugin, int x, int y);
57 class OilIntensity : public BC_CheckBox
60 OilIntensity(OilEffect *plugin, int x, int y);
65 class OilWindow : public BC_Window
68 OilWindow(OilEffect *plugin, int x, int y);
70 void create_objects();
74 OilIntensity *intensity;
77 PLUGIN_THREAD_HEADER(OilEffect, OilThread, OilWindow)
83 class OilServer : public LoadServer
86 OilServer(OilEffect *plugin, int cpus);
88 LoadClient* new_client();
89 LoadPackage* new_package();
93 class OilPackage : public LoadPackage
100 class OilUnit : public LoadClient
103 OilUnit(OilEffect *plugin, OilServer *server);
104 void process_package(LoadPackage *package);
116 class OilEffect : public PluginVClient
119 OilEffect(PluginServer *server);
122 int process_realtime(VFrame *input, VFrame *output);
124 char* plugin_title();
126 int load_configuration();
129 void save_data(KeyFrame *keyframe);
130 void read_data(KeyFrame *keyframe);
138 VFrame *input, *output;
142 int need_reconfigure;
157 OilConfig::OilConfig()
163 void OilConfig::copy_from(OilConfig &src)
165 this->radius = src.radius;
166 this->use_intensity = src.use_intensity;
169 int OilConfig::equivalent(OilConfig &src)
171 return (EQUIV(this->radius, src.radius) &&
172 this->use_intensity == src.use_intensity);
175 void OilConfig::interpolate(OilConfig &prev,
181 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
182 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
183 this->radius = prev.radius * prev_scale + next.radius * next_scale;
184 this->use_intensity = prev.use_intensity;
185 // printf("OilConfig::interpolate prev_frame=%ld current_frame=%ld next_frame=%ld prev.radius=%f this->radius=%f next.radius=%f\n",
186 // prev_frame, current_frame, next_frame, prev.radius, this->radius, next.radius);
200 OilRadius::OilRadius(OilEffect *plugin, int x, int y)
208 plugin->config.radius)
210 this->plugin = plugin;
212 int OilRadius::handle_event()
214 plugin->config.radius = get_value();
215 plugin->send_configure_change();
225 OilIntensity::OilIntensity(OilEffect *plugin, int x, int y)
226 : BC_CheckBox(x, y, plugin->config.use_intensity, _("Use intensity"))
228 this->plugin = plugin;
230 int OilIntensity::handle_event()
232 plugin->config.use_intensity = get_value();
233 plugin->send_configure_change();
243 OilWindow::OilWindow(OilEffect *plugin, int x, int y)
244 : BC_Window(plugin->gui_string,
255 this->plugin = plugin;
258 OilWindow::~OilWindow()
262 void OilWindow::create_objects()
265 add_subwindow(new BC_Title(x, y, _("Radius:")));
266 add_subwindow(radius = new OilRadius(plugin, x + 70, y));
268 add_subwindow(intensity = new OilIntensity(plugin, x, y));
274 int OilWindow::close_event()
282 PLUGIN_THREAD_OBJECT(OilEffect, OilThread, OilWindow)
287 REGISTER_PLUGIN(OilEffect)
292 OilEffect::OilEffect(PluginServer *server)
293 : PluginVClient(server)
296 need_reconfigure = 1;
298 PLUGIN_CONSTRUCTOR_MACRO
301 OilEffect::~OilEffect()
303 PLUGIN_DESTRUCTOR_MACRO
305 if(temp_frame) delete temp_frame;
306 if(engine) delete engine;
310 int OilEffect::is_realtime()
315 char* OilEffect::plugin_title()
317 return _("Oil painting");
320 NEW_PICON_MACRO(OilEffect)
322 SHOW_GUI_MACRO(OilEffect, OilThread)
324 RAISE_WINDOW_MACRO(OilEffect)
326 SET_STRING_MACRO(OilEffect)
328 void OilEffect::update_gui()
332 thread->window->lock_window();
333 load_configuration();
334 //printf("OilEffect::update_gui 1 %ld %f\n", get_source_position(), config.radius);
336 thread->window->radius->update(config.radius);
337 thread->window->intensity->update(config.use_intensity);
338 thread->window->unlock_window();
343 LOAD_CONFIGURATION_MACRO(OilEffect, OilConfig)
345 int OilEffect::load_defaults()
347 char directory[BCTEXTLEN];
348 // set the default directory
349 sprintf(directory, "%soilpainting.rc", BCASTDIR);
352 defaults = new Defaults(directory);
355 config.radius = defaults->get("RADIUS", config.radius);
356 config.use_intensity = defaults->get("USE_INTENSITY", config.use_intensity);
360 int OilEffect::save_defaults()
362 defaults->update("RADIUS", config.radius);
363 defaults->update("USE_INTENSITY", config.use_intensity);
368 void OilEffect::save_data(KeyFrame *keyframe)
372 // cause data to be stored directly in text
373 output.set_shared_string(keyframe->data, MESSAGESIZE);
374 output.tag.set_title("OIL_PAINTING");
375 output.tag.set_property("RADIUS", config.radius);
376 output.tag.set_property("USE_INTENSITY", config.use_intensity);
378 output.terminate_string();
381 void OilEffect::read_data(KeyFrame *keyframe)
385 input.set_shared_string(keyframe->data, strlen(keyframe->data));
389 while(!input.read_tag())
391 if(input.tag.title_is("OIL_PAINTING"))
393 config.radius = input.tag.get_property("RADIUS", config.radius);
394 config.use_intensity = input.tag.get_property("USE_INTENSITY", config.use_intensity);
400 int OilEffect::process_realtime(VFrame *input, VFrame *output)
402 need_reconfigure |= load_configuration();
406 //printf("OilEffect::process_realtime %f %d\n", config.radius, config.use_intensity);
408 this->output = output;
410 if(EQUIV(config.radius, 0))
412 if(input->get_rows()[0] != output->get_rows()[0])
413 output->copy_from(input);
417 if(input->get_rows()[0] == output->get_rows()[0])
419 if(!temp_frame) temp_frame = new VFrame(0,
422 input->get_color_model());
423 temp_frame->copy_from(input);
424 this->input = temp_frame;
430 engine = new OilServer(this, (PluginClient::smp + 1));
433 engine->process_packages();
446 OilPackage::OilPackage()
456 OilUnit::OilUnit(OilEffect *plugin, OilServer *server)
459 this->plugin = plugin;
463 #define INTENSITY(p) ((unsigned int)(((p)[0]) * 77+ \
468 #define OIL_MACRO(type, max, components) \
471 type Val[components]; \
472 type Cnt[components], Cnt2; \
473 type Hist[components][max + 1], Hist2[max + 1]; \
474 type **src_rows = (type**)plugin->input->get_rows(); \
476 for(int y1 = pkg->row1; y1 < pkg->row2; y1++) \
478 dest = (type*)plugin->output->get_rows()[y1]; \
480 if(!plugin->config.use_intensity) \
482 for(int x1 = 0; x1 < w; x1++) \
484 bzero(Cnt, sizeof(Cnt)); \
485 bzero(Val, sizeof(Val)); \
486 bzero(Hist, sizeof(Hist)); \
488 int x3 = CLIP((x1 - n), 0, w - 1); \
489 int y3 = CLIP((y1 - n), 0, h - 1); \
490 int x4 = CLIP((x1 + n + 1), 0, w - 1); \
491 int y4 = CLIP((y1 + n + 1), 0, h - 1); \
493 for(int y2 = y3; y2 < y4; y2++) \
495 src = src_rows[y2]; \
496 for(int x2 = x3; x2 < x4; x2++) \
499 if((c = ++Hist[0][src[x2 * components + 0]]) > Cnt[0]) \
501 Val[0] = src[x2 * components + 0]; \
505 if((c = ++Hist[1][src[x2 * components + 1]]) > Cnt[1]) \
507 Val[1] = src[x2 * components + 1]; \
511 if((c = ++Hist[2][src[x2 * components + 2]]) > Cnt[2]) \
513 Val[2] = src[x2 * components + 2]; \
517 if(components == 4) \
519 if((c = ++Hist[3][src[x2 * components + 3]]) > Cnt[3]) \
521 Val[3] = src[x2 * components + 3]; \
528 dest[x1 * components + 0] = Val[0]; \
529 dest[x1 * components + 1] = Val[1]; \
530 dest[x1 * components + 2] = Val[2]; \
531 if(components == 4) dest[x1 * components + 3] = Val[3]; \
536 for(int x1 = 0; x1 < w; x1++) \
539 bzero(Val, sizeof(Val)); \
540 bzero(Hist2, sizeof(Hist2)); \
542 int x3 = CLIP((x1 - n), 0, w - 1); \
543 int y3 = CLIP((y1 - n), 0, h - 1); \
544 int x4 = CLIP((x1 + n + 1), 0, w - 1); \
545 int y4 = CLIP((y1 + n + 1), 0, h - 1); \
547 for(int y2 = y3; y2 < y4; y2++) \
549 src = src_rows[y2]; \
550 for(int x2 = x3; x2 < x4; x2++) \
553 if((c = ++Hist2[INTENSITY(src + x2 * components)]) > Cnt2) \
555 Val[0] = src[x2 * components + 0]; \
556 Val[1] = src[x2 * components + 1]; \
557 Val[2] = src[x2 * components + 2]; \
558 if(components == 3) Val[3] = src[x2 * components + 3]; \
564 dest[x1 * components + 0] = Val[0]; \
565 dest[x1 * components + 1] = Val[1]; \
566 dest[x1 * components + 2] = Val[2]; \
567 if(components == 3) dest[x1 * components + 3] = Val[3]; \
576 void OilUnit::process_package(LoadPackage *package)
578 OilPackage *pkg = (OilPackage*)package;
579 int w = plugin->input->get_w();
580 int h = plugin->input->get_h();
581 int n = (int)(plugin->config.radius / 2);
583 switch(plugin->input->get_color_model())
587 OIL_MACRO(unsigned char, 0xff, 3)
591 OIL_MACRO(uint16_t, 0xffff, 3)
595 OIL_MACRO(unsigned char, 0xff, 4)
597 case BC_RGBA16161616:
598 case BC_YUVA16161616:
599 OIL_MACRO(uint16_t, 0xffff, 4)
613 OilServer::OilServer(OilEffect *plugin, int cpus)
614 : LoadServer(cpus, cpus)
616 this->plugin = plugin;
619 void OilServer::init_packages()
621 int increment = plugin->input->get_h() / LoadServer::total_packages + 1;
623 for(int i = 0; i < LoadServer::total_packages; i++)
625 OilPackage *pkg = (OilPackage*)packages[i];
627 pkg->row2 = y + increment;
629 if(pkg->row2 > plugin->input->get_h())
631 y = pkg->row2 = plugin->input->get_h();
637 LoadClient* OilServer::new_client()
639 return new OilUnit(plugin, this);
642 LoadPackage* OilServer::new_package()
644 return new OilPackage;