r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / plugins / invertvideo / invert.C
blob8b7ab5f448c3b75d59aed0abf90f4bb024fc2fc4
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "language.h"
7 #include "picon_png.h"
8 #include "../colors/plugincolors.h"
9 #include "pluginvclient.h"
10 #include "vframe.h"
12 #include <stdint.h>
13 #include <string.h>
17 class InvertVideoEffect;
20 class InvertVideoConfig
22 public:
23         InvertVideoConfig();
25         void copy_from(InvertVideoConfig &src);
26         int equivalent(InvertVideoConfig &src);
27         void interpolate(InvertVideoConfig &prev, 
28                 InvertVideoConfig &next, 
29                 long prev_frame, 
30                 long next_frame, 
31                 long current_frame);
33         int r, g, b, a;
36 class InvertVideoEnable : public BC_CheckBox
38 public:
39         InvertVideoEnable(InvertVideoEffect *plugin, int *output, int x, int y, char *text);
40         int handle_event();
41         InvertVideoEffect *plugin;
42         int *output;
45 class InvertVideoWindow : public BC_Window
47 public:
48         InvertVideoWindow(InvertVideoEffect *plugin, int x, int y);
49         void create_objects();
50         int close_event();
51         InvertVideoEnable *r, *g, *b, *a;
52         InvertVideoEffect *plugin;
55 PLUGIN_THREAD_HEADER(InvertVideoEffect, InvertVideoThread, InvertVideoWindow)
57 class InvertVideoEffect : public PluginVClient
59 public:
60         InvertVideoEffect(PluginServer *server);
61         ~InvertVideoEffect();
62         int process_realtime(VFrame *input, VFrame *output);
63         int is_realtime();
64         char* plugin_title();
65         VFrame* new_picon();
66         int load_defaults();
67         int save_defaults();
68         void save_data(KeyFrame *keyframe);
69         void read_data(KeyFrame *keyframe);
70         void update_gui();
71         int show_gui();
72         void raise_window();
73         int set_string();
74         int load_configuration();
76         InvertVideoConfig config;
77         InvertVideoThread *thread;
78         Defaults *defaults;
85 REGISTER_PLUGIN(InvertVideoEffect)
93 InvertVideoConfig::InvertVideoConfig()
95         r = 1;
96         g = 1;
97         b = 1;
98         a = 1;
101 void InvertVideoConfig::copy_from(InvertVideoConfig &src)
103         r = src.r;
104         g = src.g;
105         b = src.b;
106         a = src.a;
109 int InvertVideoConfig::equivalent(InvertVideoConfig &src)
111         return r == src.r && 
112                 g == src.g && 
113                 b == src.b && 
114                 a == src.a;
117 void InvertVideoConfig::interpolate(InvertVideoConfig &prev, 
118         InvertVideoConfig &next, 
119         long prev_frame, 
120         long next_frame, 
121         long current_frame)
123         r = prev.r;
124         g = prev.g;
125         b = prev.b;
126         a = prev.a;
132 InvertVideoEnable::InvertVideoEnable(InvertVideoEffect *plugin, int *output, int x, int y, char *text)
133  : BC_CheckBox(x, y, *output, text)
135         this->plugin = plugin;
136         this->output = output;
138 int InvertVideoEnable::handle_event()
140         *output = get_value();
141         plugin->send_configure_change();
142         return 1;
149 InvertVideoWindow::InvertVideoWindow(InvertVideoEffect *plugin, int x, int y)
150  : BC_Window(plugin->gui_string, 
151         x, 
152         y, 
153         260, 
154         130, 
155         260, 
156         130, 
157         0, 
158         0,
159         1)
161         this->plugin = plugin;
164 void InvertVideoWindow::create_objects()
166         int x = 10, y = 10;
167         add_subwindow(r = new InvertVideoEnable(plugin, &plugin->config.r, x, y, _("Invert R")));
168         y += 30;
169         add_subwindow(g = new InvertVideoEnable(plugin, &plugin->config.g, x, y, _("Invert G")));
170         y += 30;
171         add_subwindow(b = new InvertVideoEnable(plugin, &plugin->config.b, x, y, _("Invert B")));
172         y += 30;
173         add_subwindow(a = new InvertVideoEnable(plugin, &plugin->config.a, x, y, _("Invert A")));
175         show_window();
176         flush();
179 WINDOW_CLOSE_EVENT(InvertVideoWindow)
185 PLUGIN_THREAD_OBJECT(InvertVideoEffect, InvertVideoThread, InvertVideoWindow)
192 InvertVideoEffect::InvertVideoEffect(PluginServer *server)
193  : PluginVClient(server)
195         PLUGIN_CONSTRUCTOR_MACRO
197 InvertVideoEffect::~InvertVideoEffect()
199         PLUGIN_DESTRUCTOR_MACRO
202 char* InvertVideoEffect::plugin_title() { return N_("Invert Video"); }
203 int InvertVideoEffect::is_realtime() { return 1; }
205 NEW_PICON_MACRO(InvertVideoEffect)
206 SHOW_GUI_MACRO(InvertVideoEffect, InvertVideoThread)
207 RAISE_WINDOW_MACRO(InvertVideoEffect)
208 SET_STRING_MACRO(InvertVideoEffect)
209 LOAD_CONFIGURATION_MACRO(InvertVideoEffect, InvertVideoConfig)
211 void InvertVideoEffect::update_gui()
213         if(thread)
214         {
215                 thread->window->lock_window();
216                 load_configuration();
217                 thread->window->r->update(config.r);
218                 thread->window->g->update(config.g);
219                 thread->window->b->update(config.b);
220                 thread->window->a->update(config.a);
221                 thread->window->unlock_window();
222         }
225 int InvertVideoEffect::load_defaults()
227         char directory[BCTEXTLEN];
228         sprintf(directory, "%sinvertvideo.rc", BCASTDIR);
229         defaults = new Defaults(directory);
230         defaults->load();
231         config.r = defaults->get("R", config.r);
232         config.g = defaults->get("G", config.g);
233         config.b = defaults->get("B", config.b);
234         config.a = defaults->get("A", config.a);
235         return 0;
238 int InvertVideoEffect::save_defaults()
240         defaults->update("R", config.r);
241         defaults->update("G", config.g);
242         defaults->update("B", config.b);
243         defaults->update("A", config.a);
244         defaults->save();
245         return 0;
248 void InvertVideoEffect::save_data(KeyFrame *keyframe)
250         FileXML output;
251         output.set_shared_string(keyframe->data, MESSAGESIZE);
252         output.tag.set_title("INVERTVIDEO");
253         output.tag.set_property("R", config.r);
254         output.tag.set_property("G", config.g);
255         output.tag.set_property("B", config.b);
256         output.tag.set_property("A", config.a);
257         output.append_tag();
258         output.terminate_string();
261 void InvertVideoEffect::read_data(KeyFrame *keyframe)
263         FileXML input;
264         input.set_shared_string(keyframe->data, strlen(keyframe->data));
265         while(!input.read_tag())
266         {
267                 if(input.tag.title_is("INVERTVIDEO"))
268                 {
269                         config.r = input.tag.get_property("R", config.r);
270                         config.g = input.tag.get_property("G", config.g);
271                         config.b = input.tag.get_property("B", config.b);
272                         config.a = input.tag.get_property("A", config.a);
273                 }
274         }
278 #define INVERT_MACRO(type, components, max) \
279 { \
280         for(int i = 0; i < input->get_h(); i++) \
281         { \
282                 type *in_row = (type*)input->get_rows()[i]; \
283                 type *out_row = (type*)output->get_rows()[i]; \
285                 for(int j = 0; j < w; j++) \
286                 { \
287                         if(config.r) out_row[0] = max - in_row[0]; \
288                         if(config.g) out_row[1] = max - in_row[1]; \
289                         if(config.b) out_row[2] = max - in_row[2]; \
290                         if(components == 4) \
291                                 if(config.a) out_row[3] = max - in_row[3]; \
293                         in_row += components; \
294                         out_row += components; \
295                 } \
296         } \
299 int InvertVideoEffect::process_realtime(VFrame *input, VFrame *output)
301         load_configuration();
303         if(!config.r && !config.g && !config.b && !config.a)
304         {
305                 if(input->get_rows()[0] != output->get_rows()[0])
306                         output->copy_from(input);
307         }
308         else
309         {
310                 int w = input->get_w();
312                 switch(input->get_color_model())
313                 {
314                         case BC_RGB_FLOAT:
315                                 INVERT_MACRO(float, 3, 1.0)
316                                 break;
317                         case BC_RGB888:
318                         case BC_YUV888:
319                                 INVERT_MACRO(unsigned char, 3, 0xff)
320                                 break;
321                         case BC_RGBA_FLOAT:
322                                 INVERT_MACRO(float, 4, 1.0)
323                                 break;
324                         case BC_RGBA8888:
325                         case BC_YUVA8888:
326                                 INVERT_MACRO(unsigned char, 4, 0xff)
327                                 break;
328                         case BC_RGB161616:
329                         case BC_YUV161616:
330                                 INVERT_MACRO(uint16_t, 3, 0xffff)
331                                 break;
332                         case BC_RGBA16161616:
333                         case BC_YUVA16161616:
334                                 INVERT_MACRO(uint16_t, 4, 0xffff)
335                                 break;
336                 }
337         }
339         return 0;