Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.0 / plugins / whirl / whirl.C
diff --git a/cinelerra-5.0/plugins/whirl/whirl.C b/cinelerra-5.0/plugins/whirl/whirl.C
deleted file mode 100644 (file)
index d1a2043..0000000
+++ /dev/null
@@ -1,835 +0,0 @@
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- */
-
-#include "bcdisplayinfo.h"
-#include "clip.h"
-#include "bchash.h"
-#include "filexml.h"
-#include "guicast.h"
-#include "keyframe.h"
-#include "language.h"
-#include "loadbalance.h"
-#include "pluginvclient.h"
-#include "vframe.h"
-
-
-
-#include <stdint.h>
-#include <string.h>
-
-class WhirlEffect;
-class WhirlWindow;
-class WhirlEngine;
-
-#define MAXRADIUS 100
-#define MAXPINCH 100
-
-
-
-
-
-
-class WhirlConfig
-{
-public:
-       WhirlConfig();
-       
-       void copy_from(WhirlConfig &src);
-       int equivalent(WhirlConfig &src);
-       void interpolate(WhirlConfig &prev, 
-               WhirlConfig &next, 
-               long prev_frame, 
-               long next_frame, 
-               long current_frame);
-       
-       float angle;
-       float pinch;
-       float radius;
-};
-
-
-class WhirlAngle : public BC_FSlider
-{
-public:
-       WhirlAngle(WhirlEffect *plugin, int x, int y);
-       int handle_event();
-       WhirlEffect *plugin;
-};
-
-
-
-class WhirlPinch : public BC_FSlider
-{
-public:
-       WhirlPinch(WhirlEffect *plugin, int x, int y);
-       int handle_event();
-       WhirlEffect *plugin;
-};
-
-
-
-class WhirlRadius : public BC_FSlider
-{
-public:
-       WhirlRadius(WhirlEffect *plugin, int x, int y);
-       int handle_event();
-       WhirlEffect *plugin;
-};
-
-class WhirlWindow : public PluginClientWindow
-{
-public:
-       WhirlWindow(WhirlEffect *plugin);
-       void create_objects();
-       WhirlEffect *plugin;
-       WhirlRadius *radius;
-       WhirlPinch *pinch;
-       WhirlAngle *angle;
-};
-
-
-
-
-
-class WhirlPackage : public LoadPackage
-{
-public:
-       WhirlPackage();
-       int row1, row2;
-};
-
-class WhirlUnit : public LoadClient
-{
-public:
-       WhirlUnit(WhirlEffect *plugin, WhirlEngine *server);
-       void process_package(LoadPackage *package);
-       WhirlEngine *server;
-       WhirlEffect *plugin;
-       
-};
-
-
-class WhirlEngine : public LoadServer
-{
-public:
-       WhirlEngine(WhirlEffect *plugin, int cpus);
-       void init_packages();
-       LoadClient* new_client();
-       LoadPackage* new_package();
-       WhirlEffect *plugin;
-};
-
-
-
-class WhirlEffect : public PluginVClient
-{
-public:
-       WhirlEffect(PluginServer *server);
-       ~WhirlEffect();
-
-       PLUGIN_CLASS_MEMBERS(WhirlConfig)
-       int process_realtime(VFrame *input, VFrame *output);
-       int is_realtime();
-       void update_gui();
-       void save_data(KeyFrame *keyframe);
-       void read_data(KeyFrame *keyframe);
-
-       WhirlEngine *engine;
-       VFrame *temp_frame;
-       VFrame *input, *output;
-       int need_reconfigure;
-};
-
-
-
-
-
-
-REGISTER_PLUGIN(WhirlEffect)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WhirlConfig::WhirlConfig()
-{
-       angle = 0.0;
-       pinch = 0.0;
-       radius = 0.0;
-}
-
-void WhirlConfig::copy_from(WhirlConfig &src)
-{
-       this->angle = src.angle;
-       this->pinch = src.pinch;
-       this->radius = src.radius;
-}
-
-int WhirlConfig::equivalent(WhirlConfig &src)
-{
-       return EQUIV(this->angle, src.angle) &&
-               EQUIV(this->pinch, src.pinch) &&
-               EQUIV(this->radius, src.radius);
-}
-
-void WhirlConfig::interpolate(WhirlConfig &prev, 
-       WhirlConfig &next, 
-       long prev_frame, 
-       long next_frame, 
-       long current_frame)
-{
-       double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
-       double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
-
-       this->angle = prev.angle * prev_scale + next.angle * next_scale;
-       this->pinch = prev.pinch * prev_scale + next.pinch * next_scale;
-       this->radius = prev.radius * prev_scale + next.radius * next_scale;
-}
-
-
-
-
-
-
-
-
-
-
-WhirlWindow::WhirlWindow(WhirlEffect *plugin)
- : PluginClientWindow(plugin, 
-       220, 
-       200, 
-       220, 
-       200, 
-       0)
-{
-       this->plugin = plugin;
-}
-
-
-
-void WhirlWindow::create_objects()
-{
-       int x = 10, y = 10;
-       add_subwindow(new BC_Title(x, y, _("Radius")));
-       y += 20;
-       add_subwindow(radius = new WhirlRadius(plugin, x, y));
-       y += 40;
-       add_subwindow(new BC_Title(x, y, _("Pinch")));
-       y += 20;
-       add_subwindow(pinch = new WhirlPinch(plugin, x, y));
-       y += 40;
-       add_subwindow(new BC_Title(x, y, _("Angle")));
-       y += 20;
-       add_subwindow(angle = new WhirlAngle(plugin, x, y));
-
-       show_window();
-       flush();
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WhirlAngle::WhirlAngle(WhirlEffect *plugin, int x, int y)
- : BC_FSlider(x, 
-               y, 
-               0,
-               200,
-               200, 
-               (float)0, 
-               (float)360,
-               plugin->config.angle)
-{
-       this->plugin = plugin;
-}
-int WhirlAngle::handle_event()
-{
-       plugin->config.angle = get_value();
-       plugin->send_configure_change();
-       return 1;
-}
-
-
-
-
-WhirlPinch::WhirlPinch(WhirlEffect *plugin, int x, int y)
- : BC_FSlider(x, 
-               y, 
-               0,
-               200,
-               200, 
-               (float)0, 
-               (float)MAXPINCH, 
-               plugin->config.pinch)
-{
-       this->plugin = plugin;
-}
-int WhirlPinch::handle_event()
-{
-       plugin->config.pinch = get_value();
-       plugin->send_configure_change();
-       return 1;
-}
-
-
-
-
-WhirlRadius::WhirlRadius(WhirlEffect *plugin, int x, int y)
- : BC_FSlider(x, 
-               y, 
-               0,
-               200,
-               200, 
-               (float)0, 
-               (float)MAXRADIUS, 
-               plugin->config.radius)
-{
-       this->plugin = plugin;
-}
-int WhirlRadius::handle_event()
-{
-       plugin->config.radius = get_value();
-       plugin->send_configure_change();
-       return 1;
-}
-
-
-
-
-
-
-
-
-
-
-
-WhirlEffect::WhirlEffect(PluginServer *server)
- : PluginVClient(server)
-{
-       need_reconfigure = 1;
-       engine = 0;
-       temp_frame = 0;
-       
-}
-
-WhirlEffect::~WhirlEffect()
-{
-       
-       if(engine) delete engine;
-       if(temp_frame) delete temp_frame;
-}
-
-
-
-
-
-
-const char* WhirlEffect::plugin_title() { return _("Whirl"); }
-int WhirlEffect::is_realtime() { return 1; }
-
-
-
-NEW_WINDOW_MACRO(WhirlEffect, WhirlWindow)
-
-
-void WhirlEffect::update_gui()
-{
-       if(thread)
-       {
-               load_configuration();
-               thread->window->lock_window();
-               ((WhirlWindow*)thread->window)->angle->update(config.angle);
-               ((WhirlWindow*)thread->window)->pinch->update(config.pinch);
-               ((WhirlWindow*)thread->window)->radius->update(config.radius);
-               thread->window->unlock_window();
-       }
-}
-
-LOAD_CONFIGURATION_MACRO(WhirlEffect, WhirlConfig)
-
-
-
-
-void WhirlEffect::save_data(KeyFrame *keyframe)
-{
-       FileXML output;
-
-// cause data to be stored directly in text
-       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
-
-       output.tag.set_title("WHIRL");
-       output.tag.set_property("ANGLE", config.angle);
-       output.tag.set_property("PINCH", config.pinch);
-       output.tag.set_property("RADIUS", config.radius);
-       output.append_tag();
-       output.tag.set_title("/WHIRL");
-       output.append_tag();
-       output.append_newline();
-       output.terminate_string();
-// data is now in *text
-}
-
-void WhirlEffect::read_data(KeyFrame *keyframe)
-{
-       FileXML input;
-
-       input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
-
-       int result = 0;
-
-       while(!result)
-       {
-               result = input.read_tag();
-
-               if(!result)
-               {
-                       if(input.tag.title_is("WHIRL"))
-                       {
-                               config.angle = input.tag.get_property("ANGLE", config.angle);
-                               config.pinch = input.tag.get_property("PINCH", config.pinch);
-                               config.radius = input.tag.get_property("RADIUS", config.radius);
-                       }
-               }
-       }
-}
-
-int WhirlEffect::process_realtime(VFrame *input, VFrame *output)
-{
-       need_reconfigure |= load_configuration();
-       this->input = input;
-       this->output = output;
-
-       if(EQUIV(config.angle, 0) || 
-               (EQUIV(config.radius, 0) && EQUIV(config.pinch, 0)))
-       {
-               if(input->get_rows()[0] != output->get_rows()[0])
-                       output->copy_from(input);
-       }
-       else
-       {
-               if(input->get_rows()[0] == output->get_rows()[0])
-               {
-                       if(!temp_frame) temp_frame = new VFrame(0,
-                               -1,
-                               input->get_w(),
-                               input->get_h(),
-                               input->get_color_model(),
-                               -1);
-                       temp_frame->copy_from(input);
-                       this->input = temp_frame;
-               }
-
-               if(!engine) engine = new WhirlEngine(this, PluginClient::smp + 1);
-
-               engine->process_packages();
-       }
-       return 0;
-}
-
-
-
-
-
-
-
-
-WhirlPackage::WhirlPackage()
- : LoadPackage()
-{
-}
-
-
-
-WhirlUnit::WhirlUnit(WhirlEffect *plugin, WhirlEngine *server)
- : LoadClient(server)
-{
-       this->plugin = plugin;
-}
-
-
-
-static int calc_undistorted_coords(double cen_x,
-                       double cen_y,
-                       double scale_x,
-                       double scale_y,
-                       double radius,
-                       double radius2,
-                       double radius3,
-                       double pinch,
-                       double wx,
-                       double wy,
-                       double &whirl,
-                       double &x,
-                       double &y)
-{
-       double dx, dy;
-       double d, factor;
-       double dist;
-       double ang, sina, cosa;
-       int inside;
-
-/* Distances to center, scaled */
-
-       dx = (wx - cen_x) * scale_x;
-       dy = (wy - cen_y) * scale_y;
-
-/* Distance^2 to center of *circle* (scaled ellipse) */
-
-       d = dx * dx + dy * dy;
-
-/*  If we are inside circle, then distort.
- *  Else, just return the same position
- */
-
-       inside = (d < radius2);
-
-       if(inside)
-    {
-       dist = sqrt(d / radius3) / radius;
-
-/* Pinch */
-
-       factor = pow(sin(M_PI / 2 * dist), -pinch);
-
-       dx *= factor;
-       dy *= factor;
-
-/* Whirl */
-
-       factor = 1.0 - dist;
-
-       ang = whirl * factor * factor;
-
-       sina = sin(ang);
-       cosa = cos(ang);
-
-       x = (cosa * dx - sina * dy) / scale_x + cen_x;
-       y = (sina * dx + cosa * dy) / scale_y + cen_y;
-    }
-
-       return inside;
-}
-
-
-
-#define GET_PIXEL(components, x, y, input_rows) \
-       input_rows[CLIP(y, 0, (h - 1))] + components * CLIP(x, 0, (w - 1))
-
-
-
-
-
-
-static float bilinear(double x, double y, double *values)
-{
-       double m0, m1;
-       x = fmod(x, 1.0);
-       y = fmod(y, 1.0);
-
-       if(x < 0.0) x += 1.0;
-       if(y < 0.0) y += 1.0;
-
-       m0 = (double)values[0] + x * ((double)values[1] - values[0]);
-       m1 = (double)values[2] + x * ((double)values[3] - values[2]);
-       return m0 + y * (m1 - m0);
-}
-
-
-
-
-
-#define WHIRL_MACRO(type, max, components) \
-{ \
-       type **input_rows = (type**)plugin->input->get_rows(); \
-/* Compiler error requires separate arrays */ \
-       double top_values[4], bot_values[4]; \
-       for( int i=0; i<4; ++i ) top_values[i] = bot_values[i] = 0; \
-       for(int row = pkg->row1 / 2; row <= (pkg->row2 + pkg->row1) / 2; row++) \
-       { \
-               type *top_row = (type*)plugin->output->get_rows()[row]; \
-               type *bot_row = (type*)plugin->output->get_rows()[h - row - 1]; \
-               type *top_p = top_row; \
-               type *bot_p = bot_row + components * w - components; \
-               type *pixel1; \
-               type *pixel2; \
-               type *pixel3; \
-               type *pixel4; \
- \
-               for(int col = 0; col < w; col++) \
-               { \
-                       if(calc_undistorted_coords(cen_x, \
-                               cen_y, \
-                               scale_x, \
-                               scale_y, \
-                               radius, \
-                               radius2, \
-                               radius3, \
-                               pinch, \
-                               col, \
-                               row, \
-                               whirl, \
-                               cx, \
-                               cy)) \
-                       { \
-/* Inside distortion area */ \
-/* Do top */ \
-                               if(cx >= 0.0) \
-                                       ix = (int)cx; \
-                               else \
-                                       ix = -((int)-cx + 1); \
- \
-                               if(cy >= 0.0) \
-                                       iy = (int)cy; \
-                               else \
-                                       iy = -((int)-cy + 1); \
- \
-                               pixel1 = GET_PIXEL(components, ix,     iy,     input_rows); \
-                               pixel2 = GET_PIXEL(components, ix + 1, iy,     input_rows); \
-                               pixel3 = GET_PIXEL(components, ix,     iy + 1, input_rows); \
-                               pixel4 = GET_PIXEL(components, ix + 1, iy + 1, input_rows); \
- \
-                               top_values[0] = pixel1[0]; \
-                               top_values[1] = pixel2[0]; \
-                               top_values[2] = pixel3[0]; \
-                               top_values[3] = pixel4[0]; \
-                               top_p[0] = (type)bilinear(cx, cy, top_values); \
- \
-                               top_values[0] = pixel1[1]; \
-                               top_values[1] = pixel2[1]; \
-                               top_values[2] = pixel3[1]; \
-                               top_values[3] = pixel4[1]; \
-                               top_p[1] = (type)bilinear(cx, cy, top_values); \
- \
-                               top_values[0] = pixel1[2]; \
-                               top_values[1] = pixel2[2]; \
-                               top_values[2] = pixel3[2]; \
-                               top_values[3] = pixel4[2]; \
-                               top_p[2] = (type)bilinear(cx, cy, top_values); \
- \
-                               if(components == 4) \
-                               { \
-                                       top_values[0] = pixel1[3]; \
-                                       top_values[1] = pixel2[3]; \
-                                       top_values[2] = pixel3[3]; \
-                                       top_values[3] = pixel4[3]; \
-                                       top_p[3] = (type)bilinear(cx, cy, top_values); \
-                               } \
- \
-                               top_p += components; \
- \
-/* Do bottom */ \
-                       cx = cen_x + (cen_x - cx); \
-                       cy = cen_y + (cen_y - cy); \
- \
-                       if(cx >= 0.0) \
-                                       ix = (int)cx; \
-                       else \
-                                       ix = -((int)-cx + 1); \
- \
-                       if(cy >= 0.0) \
-                                       iy = (int)cy; \
-                       else \
-                                       iy = -((int)-cy + 1); \
- \
-                               pixel1 = GET_PIXEL(components, ix,     iy,     input_rows); \
-                               pixel2 = GET_PIXEL(components, ix + 1, iy,     input_rows); \
-                               pixel3 = GET_PIXEL(components, ix,     iy + 1, input_rows); \
-                               pixel4 = GET_PIXEL(components, ix + 1, iy + 1, input_rows); \
- \
- \
- \
-                               bot_values[0] = pixel1[0]; \
-                               bot_values[1] = pixel2[0]; \
-                               bot_values[2] = pixel3[0]; \
-                               bot_values[3] = pixel4[0]; \
-                               bot_p[0] = (type)bilinear(cx, cy, bot_values); \
- \
-                               bot_values[0] = pixel1[1]; \
-                               bot_values[1] = pixel2[1]; \
-                               bot_values[2] = pixel3[1]; \
-                               bot_values[3] = pixel4[1]; \
-                               bot_p[1] = (type)bilinear(cx, cy, bot_values); \
- \
-                               bot_values[0] = pixel1[2]; \
-                               bot_values[1] = pixel2[2]; \
-                               bot_values[2] = pixel3[2]; \
-                               bot_values[3] = pixel4[2]; \
-                               bot_p[2] = (type)bilinear(cx, cy, bot_values); \
- \
-                               if(components == 4) \
-                               { \
-                                       bot_values[0] = pixel1[3]; \
-                                       bot_values[1] = pixel2[3]; \
-                                       bot_values[2] = pixel3[3]; \
-                                       bot_values[3] = pixel4[3]; \
-                                       bot_p[3] = (type)bilinear(cx, cy, bot_values); \
-                               } \
- \
-                               bot_p -= components; \
- \
- \
-                       } \
-                       else \
-                       { \
-/* Outside distortion area */ \
-/* Do top */ \
-                               top_p[0] = input_rows[row][components * col + 0]; \
-                               top_p[1] = input_rows[row][components * col + 1]; \
-                               top_p[2] = input_rows[row][components * col + 2]; \
-                               if(components == 4) top_p[3] = input_rows[row][components * col + 3]; \
- \
- \
-                               top_p += components; \
- \
-/* Do bottom */ \
-                               int bot_offset = w * components - col * components - components; \
-                               int bot_row = h - 1 - row; \
-                               bot_p[0] = input_rows[bot_row][bot_offset + 0]; \
-                               bot_p[1] = input_rows[bot_row][bot_offset + 1]; \
-                               bot_p[2] = input_rows[bot_row][bot_offset + 2]; \
-                               if(components == 4) bot_p[3] = input_rows[bot_row][bot_offset + 3]; \
-                               bot_p -= components; \
-                       } \
-               } \
-       } \
-}
-
-void WhirlUnit::process_package(LoadPackage *package)
-{
-       WhirlPackage *pkg = (WhirlPackage*)package;
-       int w = plugin->input->get_w();
-       int h = plugin->input->get_h();
-       double whirl = plugin->config.angle * M_PI / 180;
-       double pinch = plugin->config.pinch / MAXPINCH;
-       double cx, cy;
-    int ix, iy;
-       double cen_x = (double)(w - 1) / 2.0;
-       double cen_y = (double)(h - 1) / 2.0;
-       double radius = MAX(w, h);
-       double radius3 = plugin->config.radius / MAXRADIUS;
-       double radius2 = radius * radius * radius3;
-       double scale_x;
-       double scale_y;
-
-
-//printf("WhirlUnit::process_package 1 %f %f %f\n", 
-//     plugin->config.angle, plugin->config.pinch, plugin->config.radius);
-       if(w < h)
-       {
-       scale_x = (double)h / w;
-       scale_y = 1.0;
-       }
-       else
-       if(w > h)
-       {
-       scale_x = 1.0;
-       scale_y = (double)w / h;
-       }
-       else
-       {
-       scale_x = 1.0;
-       scale_y = 1.0;
-       }
-
-
-
-       switch(plugin->input->get_color_model())
-       {
-               case BC_RGB_FLOAT:
-                       WHIRL_MACRO(float, 1, 3);
-                       break;
-               case BC_RGB888:
-               case BC_YUV888:
-                       WHIRL_MACRO(unsigned char, 0xff, 3);
-                       break;
-               case BC_RGBA_FLOAT:
-                       WHIRL_MACRO(float, 1, 4);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       WHIRL_MACRO(unsigned char, 0xff, 4);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       WHIRL_MACRO(uint16_t, 0xffff, 3);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       WHIRL_MACRO(uint16_t, 0xffff, 4);
-                       break;
-               
-       }
-}
-
-
-
-
-
-
-
-WhirlEngine::WhirlEngine(WhirlEffect *plugin, int cpus)
-// : LoadServer(1, 1)
- : LoadServer(cpus, cpus)
-{
-       this->plugin = plugin;
-}
-void WhirlEngine::init_packages()
-{
-       for(int i = 0; i < LoadServer::get_total_packages(); i++)
-       {
-               WhirlPackage *pkg = (WhirlPackage*)get_package(i);
-               pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
-               pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
-       }
-       
-}
-
-LoadClient* WhirlEngine::new_client()
-{
-       return new WhirlUnit(plugin, this);
-}
-
-LoadPackage* WhirlEngine::new_package()
-{
-       return new WhirlPackage;
-}
-