1 #include "bcdisplayinfo.h"
8 #include "loadbalance.h"
10 #include "pluginvclient.h"
19 #define SQR(x) ((x) * (x))
20 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
33 void copy_from(PolarConfig &src);
34 int equivalent(PolarConfig &src);
35 void interpolate(PolarConfig &prev,
41 int polar_to_rectangular;
50 class PolarDepth : public BC_FSlider
53 PolarDepth(PolarEffect *plugin, int x, int y);
58 class PolarAngle : public BC_FSlider
61 PolarAngle(PolarEffect *plugin, int x, int y);
66 class PolarWindow : public BC_Window
69 PolarWindow(PolarEffect *plugin, int x, int y);
70 void create_objects();
78 PLUGIN_THREAD_HEADER(PolarEffect, PolarThread, PolarWindow)
81 class PolarPackage : public LoadPackage
88 class PolarUnit : public LoadClient
91 PolarUnit(PolarEffect *plugin, PolarEngine *server);
92 void process_package(LoadPackage *package);
96 class PolarEngine : public LoadServer
99 PolarEngine(PolarEffect *plugin, int cpus);
100 void init_packages();
101 LoadClient* new_client();
102 LoadPackage* new_package();
106 class PolarEffect : public PluginVClient
109 PolarEffect(PluginServer *server);
112 int process_realtime(VFrame *input, VFrame *output);
114 char* plugin_title();
116 int load_configuration();
119 void save_data(KeyFrame *keyframe);
120 void read_data(KeyFrame *keyframe);
131 VFrame *input, *output;
132 int need_reconfigure;
137 REGISTER_PLUGIN(PolarEffect)
141 PolarConfig::PolarConfig()
147 polar_to_rectangular = 1;
151 void PolarConfig::copy_from(PolarConfig &src)
153 this->angle = src.angle;
154 this->depth = src.depth;
155 this->backwards = src.backwards;
156 this->invert = src.invert;
157 this->polar_to_rectangular = src.polar_to_rectangular;
160 int PolarConfig::equivalent(PolarConfig &src)
162 return EQUIV(this->angle, src.angle) && EQUIV(this->depth, src.depth);
165 void PolarConfig::interpolate(PolarConfig &prev,
171 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
172 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
174 this->depth = prev.depth * prev_scale + next.depth * next_scale;
175 this->angle = prev.angle * prev_scale + next.angle * next_scale;
183 PolarWindow::PolarWindow(PolarEffect *plugin, int x, int y)
184 : BC_Window(plugin->gui_string,
195 this->plugin = plugin;
198 void PolarWindow::create_objects()
201 add_subwindow(new BC_Title(x, y, _("Depth:")));
202 add_subwindow(depth = new PolarDepth(plugin, x + 50, y));
204 add_subwindow(new BC_Title(x, y, _("Angle:")));
205 add_subwindow(angle = new PolarAngle(plugin, x + 50, y));
211 WINDOW_CLOSE_EVENT(PolarWindow)
213 PLUGIN_THREAD_OBJECT(PolarEffect, PolarThread, PolarWindow)
216 PolarDepth::PolarDepth(PolarEffect *plugin, int x, int y)
224 plugin->config.depth)
226 this->plugin = plugin;
228 int PolarDepth::handle_event()
230 plugin->config.depth = get_value();
231 plugin->send_configure_change();
239 PolarAngle::PolarAngle(PolarEffect *plugin, int x, int y)
247 plugin->config.angle)
249 this->plugin = plugin;
251 int PolarAngle::handle_event()
253 plugin->config.angle = get_value();
254 plugin->send_configure_change();
262 PolarEffect::PolarEffect(PluginServer *server)
263 : PluginVClient(server)
265 need_reconfigure = 1;
268 PLUGIN_CONSTRUCTOR_MACRO
271 PolarEffect::~PolarEffect()
273 PLUGIN_DESTRUCTOR_MACRO
274 if(temp_frame) delete temp_frame;
275 if(engine) delete engine;
280 char* PolarEffect::plugin_title() { return N_("Polar"); }
281 int PolarEffect::is_realtime() { return 1; }
285 NEW_PICON_MACRO(PolarEffect)
287 SHOW_GUI_MACRO(PolarEffect, PolarThread)
289 RAISE_WINDOW_MACRO(PolarEffect)
291 SET_STRING_MACRO(PolarEffect)
293 void PolarEffect::update_gui()
297 load_configuration();
298 thread->window->lock_window();
299 thread->window->angle->update(config.angle);
300 thread->window->depth->update(config.depth);
301 thread->window->unlock_window();
305 LOAD_CONFIGURATION_MACRO(PolarEffect, PolarConfig)
308 int PolarEffect::load_defaults()
310 char directory[BCTEXTLEN];
311 // set the default directory
312 sprintf(directory, "%spolar.rc", BCASTDIR);
315 defaults = new BC_Hash(directory);
318 config.depth = defaults->get("DEPTH", config.depth);
319 config.angle = defaults->get("ANGLE", config.angle);
323 int PolarEffect::save_defaults()
325 defaults->update("DEPTH", config.depth);
326 defaults->update("ANGLE", config.angle);
331 void PolarEffect::save_data(KeyFrame *keyframe)
335 // cause data to be stored directly in text
336 output.set_shared_string(keyframe->data, MESSAGESIZE);
337 output.tag.set_title("POLAR");
338 output.tag.set_property("DEPTH", config.depth);
339 output.tag.set_property("ANGLE", config.angle);
341 output.terminate_string();
344 void PolarEffect::read_data(KeyFrame *keyframe)
348 input.set_shared_string(keyframe->data, strlen(keyframe->data));
352 while(!input.read_tag())
354 if(input.tag.title_is("POLAR"))
356 config.depth = input.tag.get_property("DEPTH", config.depth);
357 config.angle = input.tag.get_property("ANGLE", config.angle);
362 int PolarEffect::process_realtime(VFrame *input, VFrame *output)
364 need_reconfigure |= load_configuration();
367 this->output = output;
369 if(EQUIV(config.depth, 0) || EQUIV(config.angle, 0))
371 if(input->get_rows()[0] != output->get_rows()[0])
372 output->copy_from(input);
376 if(input->get_rows()[0] == output->get_rows()[0])
378 if(!temp_frame) temp_frame = new VFrame(0,
381 input->get_color_model());
382 temp_frame->copy_from(input);
383 this->input = temp_frame;
387 if(!engine) engine = new PolarEngine(this, PluginClient::smp + 1);
389 engine->process_packages();
398 PolarPackage::PolarPackage()
406 PolarUnit::PolarUnit(PolarEffect *plugin, PolarEngine *server)
409 this->plugin = plugin;
413 static int calc_undistorted_coords(int wx,
419 int polar_to_rectangular,
429 double xx, xm, ym, yy;
433 double xmax, ymax, rmax;
434 double x_calc, y_calc;
436 double circle, angl, t;
454 angl = (double)angle / 180.0 * M_PI;
456 if(polar_to_rectangular)
463 atan(((double)(wx - cen_x)) /
464 ((double)(wy - cen_y)));
465 r = sqrt(SQR(wx - cen_x) +
471 phi = atan(((double)(wx - cen_x)) /
472 ((double)(cen_y - wy)));
473 r = sqrt(SQR(wx - cen_x) +
488 atan(((double)(cen_x -wx)) /
489 ((double)(cen_y - wy)));
490 r = sqrt(SQR(cen_x - wx) +
497 atan(((double)(cen_x - wx)) /
498 ((double)(wy - cen_y)));
499 r = sqrt(SQR(cen_x - wx) +
510 m = fabs(((double)(wy - cen_y)) /
511 ((double)(wx - cen_x)));
518 if(m <= ((double)(y2 - y1) /
538 rmax = sqrt((double)(SQR(xmax) + SQR(ymax)));
540 t = ((cen_y - y1) < (cen_x - x1)) ? (cen_y - y1) : (cen_x - x1);
541 rmax = (rmax - t) / 100 * (100 - circle) + t;
543 phi = fmod(phi + angl, 2 * M_PI);
546 x_calc = x2 - 1 - (x2 - x1 - 1) / (2 * M_PI) * phi;
548 x_calc = (x2 - x1 - 1) / (2 * M_PI) * phi + x1;
551 y_calc = (y2 - y1) / rmax * r + y1;
553 y_calc = y2 - (y2 - y1) / rmax * r;
555 xi = (int)(x_calc + 0.5);
556 yi = (int)(y_calc + 0.5);
558 if(WITHIN(0, xi, w - 1) && WITHIN(0, yi, h - 1))
573 phi = (2 * M_PI) * (x2 - wx) / xdiff;
575 phi = (2 * M_PI) * (wx - x1) / xdiff;
577 phi = fmod (phi + angl, 2 * M_PI);
579 if(phi >= 1.5 * M_PI)
580 phi2 = 2 * M_PI - phi;
585 if(phi >= 0.5 * M_PI)
592 m = (double)1.0 / xx;
596 if(m <= ((double)(ydiff) / (double)(xdiff)))
615 rmax = sqrt((double)(SQR(xmax) + SQR(ymax)));
617 t = ((ym - y1) < (xm - x1)) ? (ym - y1) : (xm - x1);
619 rmax = (rmax - t) / 100.0 * (100 - circle) + t;
622 r = rmax * (double)((wy - y1) / (double)(ydiff));
624 r = rmax * (double)((y2 - wy) / (double)(ydiff));
629 if(phi >= 1.5 * M_PI)
631 x_calc = (double)xm - xx;
632 y_calc = (double)ym - yy;
637 x_calc = (double)xm - xx;
638 y_calc = (double)ym + yy;
641 if(phi >= 0.5 * M_PI)
643 x_calc = (double)xm + xx;
644 y_calc = (double)ym + yy;
648 x_calc = (double)xm + xx;
649 y_calc = (double)ym - yy;
652 xi = (int)(x_calc + 0.5);
653 yi = (int)(y_calc + 0.5);
655 if(WITHIN(0, xi, w - 1) &&
656 WITHIN(0, yi, h - 1))
672 static double bilinear(double x, double y, double *values)
678 if(x < 0.0) x += 1.0;
679 if(y < 0.0) y += 1.0;
681 m0 = values[0] + x * (values[1] - values[0]);
682 m1 = values[2] + x * (values[3] - values[2]);
683 return m0 + y * (m1 - m0);
686 #define GET_PIXEL(x, y, components, input_rows) \
687 input_rows[CLIP((y), 0, ((h) - 1))] + components * CLIP((x), 0, ((w) - 1))
689 #define POLAR_MACRO(type, max, components, chroma_offset) \
691 type **in_rows = (type**)plugin->input->get_rows(); \
692 type **out_rows = (type**)plugin->output->get_rows(); \
695 for(int y = pkg->row1; y < pkg->row2; y++) \
697 type *output_row = out_rows[y]; \
699 for(int x = 0; x < w; x++) \
701 type *output_pixel = output_row + x * components; \
702 if(calc_undistorted_coords(x, \
706 plugin->config.depth, \
707 plugin->config.angle, \
708 plugin->config.polar_to_rectangular, \
709 plugin->config.backwards, \
710 plugin->config.invert, \
716 type *pixel1 = GET_PIXEL((int)cx, (int)cy, components, in_rows); \
717 type *pixel2 = GET_PIXEL((int)cx + 1, (int)cy, components, in_rows); \
718 type *pixel3 = GET_PIXEL((int)cx, (int)cy + 1, components, in_rows); \
719 type *pixel4 = GET_PIXEL((int)cx + 1, (int)cy + 1, components, in_rows); \
721 values[0] = pixel1[0]; \
722 values[1] = pixel2[0]; \
723 values[2] = pixel3[0]; \
724 values[3] = pixel4[0]; \
725 output_pixel[0] = (type)bilinear(cx, cy, values); \
727 values[0] = pixel1[1]; \
728 values[1] = pixel2[1]; \
729 values[2] = pixel3[1]; \
730 values[3] = pixel4[1]; \
731 output_pixel[1] = (type)bilinear(cx, cy, values); \
733 values[0] = pixel1[2]; \
734 values[1] = pixel2[2]; \
735 values[2] = pixel3[2]; \
736 values[3] = pixel4[2]; \
737 output_pixel[2] = (type)bilinear(cx, cy, values); \
739 if(components == 4) \
741 values[0] = pixel1[3]; \
742 values[1] = pixel2[3]; \
743 values[2] = pixel3[3]; \
744 values[3] = pixel4[3]; \
745 output_pixel[3] = (type)bilinear(cx, cy, values); \
750 output_pixel[0] = 0; \
751 output_pixel[1] = chroma_offset; \
752 output_pixel[2] = chroma_offset; \
753 if(components == 4) output_pixel[3] = max; \
760 void PolarUnit::process_package(LoadPackage *package)
762 PolarPackage *pkg = (PolarPackage*)package;
763 int w = plugin->input->get_w();
764 int h = plugin->input->get_h();
767 double cen_x = (double)(w - 1) / 2.0;
768 double cen_y = (double)(h - 1) / 2.0;
770 switch(plugin->input->get_color_model())
773 POLAR_MACRO(float, 1, 3, 0x0)
776 POLAR_MACRO(float, 1, 4, 0x0)
779 POLAR_MACRO(unsigned char, 0xff, 3, 0x0)
782 POLAR_MACRO(unsigned char, 0xff, 4, 0x0)
785 POLAR_MACRO(uint16_t, 0xffff, 3, 0x0)
787 case BC_RGBA16161616:
788 POLAR_MACRO(uint16_t, 0xffff, 4, 0x0)
791 POLAR_MACRO(unsigned char, 0xff, 3, 0x80)
794 POLAR_MACRO(unsigned char, 0xff, 4, 0x80)
797 POLAR_MACRO(uint16_t, 0xffff, 3, 0x8000)
799 case BC_YUVA16161616:
800 POLAR_MACRO(uint16_t, 0xffff, 4, 0x8000)
808 PolarEngine::PolarEngine(PolarEffect *plugin, int cpus)
809 : LoadServer(cpus, cpus)
811 this->plugin = plugin;
814 void PolarEngine::init_packages()
816 for(int i = 0; i < LoadServer::get_total_packages(); i++)
818 PolarPackage *pkg = (PolarPackage*)get_package(i);
819 pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
820 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
824 LoadClient* PolarEngine::new_client()
826 return new PolarUnit(plugin, this);
829 LoadPackage* PolarEngine::new_package()
831 return new PolarPackage;