r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / plugins / invertvideo / invert.C
blob2743c67b7ec99429dbbf64dae256b3db7c1ef48d
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "picon_png.h"
7 #include "plugincolors.h"
8 #include "pluginvclient.h"
9 #include "vframe.h"
11 #include <stdint.h>
12 #include <string.h>
14 #include <libintl.h>
15 #define _(String) gettext(String)
16 #define gettext_noop(String) String
17 #define N_(String) gettext_noop (String)
20 class InvertVideoEffect;
23 class InvertVideoConfig
25 public:
26         InvertVideoConfig();
28         void copy_from(InvertVideoConfig &src);
29         int equivalent(InvertVideoConfig &src);
30         void interpolate(InvertVideoConfig &prev, 
31                 InvertVideoConfig &next, 
32                 long prev_frame, 
33                 long next_frame, 
34                 long current_frame);
36         int r, g, b, a;
39 class InvertVideoEnable : public BC_CheckBox
41 public:
42         InvertVideoEnable(InvertVideoEffect *plugin, int *output, int x, int y, char *text);
43         int handle_event();
44         InvertVideoEffect *plugin;
45         int *output;
48 class InvertVideoWindow : public BC_Window
50 public:
51         InvertVideoWindow(InvertVideoEffect *plugin, int x, int y);
52         void create_objects();
53         int close_event();
54         InvertVideoEnable *r, *g, *b, *a;
55         InvertVideoEffect *plugin;
58 PLUGIN_THREAD_HEADER(InvertVideoEffect, InvertVideoThread, InvertVideoWindow)
60 class InvertVideoEffect : public PluginVClient
62 public:
63         InvertVideoEffect(PluginServer *server);
64         ~InvertVideoEffect();
65         int process_realtime(VFrame *input, VFrame *output);
66         int is_realtime();
67         char* plugin_title();
68         VFrame* new_picon();
69         int load_defaults();
70         int save_defaults();
71         void save_data(KeyFrame *keyframe);
72         void read_data(KeyFrame *keyframe);
73         void update_gui();
74         int show_gui();
75         void raise_window();
76         int set_string();
77         int load_configuration();
79         InvertVideoConfig config;
80         InvertVideoThread *thread;
81         Defaults *defaults;
88 REGISTER_PLUGIN(InvertVideoEffect)
96 InvertVideoConfig::InvertVideoConfig()
98         r = 1;
99         g = 1;
100         b = 1;
101         a = 1;
104 void InvertVideoConfig::copy_from(InvertVideoConfig &src)
106         r = src.r;
107         g = src.g;
108         b = src.b;
109         a = src.a;
112 int InvertVideoConfig::equivalent(InvertVideoConfig &src)
114         return r == src.r && 
115                 g == src.g && 
116                 b == src.b && 
117                 a == src.a;
120 void InvertVideoConfig::interpolate(InvertVideoConfig &prev, 
121         InvertVideoConfig &next, 
122         long prev_frame, 
123         long next_frame, 
124         long current_frame)
126         r = prev.r;
127         g = prev.g;
128         b = prev.b;
129         a = prev.a;
135 InvertVideoEnable::InvertVideoEnable(InvertVideoEffect *plugin, int *output, int x, int y, char *text)
136  : BC_CheckBox(x, y, *output, text)
138         this->plugin = plugin;
139         this->output = output;
141 int InvertVideoEnable::handle_event()
143         *output = get_value();
144         plugin->send_configure_change();
145         return 1;
152 InvertVideoWindow::InvertVideoWindow(InvertVideoEffect *plugin, int x, int y)
153  : BC_Window(plugin->gui_string, 
154         x, 
155         y, 
156         260, 
157         130, 
158         260, 
159         130, 
160         0, 
161         0,
162         1)
164         this->plugin = plugin;
167 void InvertVideoWindow::create_objects()
169         int x = 10, y = 10;
170         add_subwindow(r = new InvertVideoEnable(plugin, &plugin->config.r, x, y, _("Invert R")));
171         y += 30;
172         add_subwindow(g = new InvertVideoEnable(plugin, &plugin->config.g, x, y, _("Invert G")));
173         y += 30;
174         add_subwindow(b = new InvertVideoEnable(plugin, &plugin->config.b, x, y, _("Invert B")));
175         y += 30;
176         add_subwindow(a = new InvertVideoEnable(plugin, &plugin->config.a, x, y, _("Invert A")));
178         show_window();
179         flush();
182 int InvertVideoWindow::close_event()
184 // Set result to 1 to indicate a client side close
185         set_done(1);
186         return 1;
193 PLUGIN_THREAD_OBJECT(InvertVideoEffect, InvertVideoThread, InvertVideoWindow)
200 InvertVideoEffect::InvertVideoEffect(PluginServer *server)
201  : PluginVClient(server)
203         PLUGIN_CONSTRUCTOR_MACRO
205 InvertVideoEffect::~InvertVideoEffect()
207         PLUGIN_DESTRUCTOR_MACRO
209 int InvertVideoEffect::is_realtime()
211         return 1;
214 char* InvertVideoEffect::plugin_title()
216         return _("Invert Video");
219 NEW_PICON_MACRO(InvertVideoEffect)
220 SHOW_GUI_MACRO(InvertVideoEffect, InvertVideoThread)
221 RAISE_WINDOW_MACRO(InvertVideoEffect)
222 SET_STRING_MACRO(InvertVideoEffect)
223 LOAD_CONFIGURATION_MACRO(InvertVideoEffect, InvertVideoConfig)
225 void InvertVideoEffect::update_gui()
227         if(thread)
228         {
229                 thread->window->lock_window();
230                 load_configuration();
231                 thread->window->r->update(config.r);
232                 thread->window->g->update(config.g);
233                 thread->window->b->update(config.b);
234                 thread->window->a->update(config.a);
235                 thread->window->unlock_window();
236         }
239 int InvertVideoEffect::load_defaults()
241         char directory[BCTEXTLEN];
242         sprintf(directory, "%sinvertvideo.rc", BCASTDIR);
243         defaults = new Defaults(directory);
244         defaults->load();
245         config.r = defaults->get("R", config.r);
246         config.g = defaults->get("G", config.g);
247         config.b = defaults->get("B", config.b);
248         config.a = defaults->get("A", config.a);
249         return 0;
252 int InvertVideoEffect::save_defaults()
254         defaults->update("R", config.r);
255         defaults->update("G", config.g);
256         defaults->update("B", config.b);
257         defaults->update("A", config.a);
258         defaults->save();
259         return 0;
262 void InvertVideoEffect::save_data(KeyFrame *keyframe)
264         FileXML output;
265         output.set_shared_string(keyframe->data, MESSAGESIZE);
266         output.tag.set_title("INVERTVIDEO");
267         output.tag.set_property("R", config.r);
268         output.tag.set_property("G", config.g);
269         output.tag.set_property("B", config.b);
270         output.tag.set_property("A", config.a);
271         output.append_tag();
272         output.terminate_string();
275 void InvertVideoEffect::read_data(KeyFrame *keyframe)
277         FileXML input;
278         input.set_shared_string(keyframe->data, strlen(keyframe->data));
279         while(!input.read_tag())
280         {
281                 if(input.tag.title_is("INVERTVIDEO"))
282                 {
283                         config.r = input.tag.get_property("R", config.r);
284                         config.g = input.tag.get_property("G", config.g);
285                         config.b = input.tag.get_property("B", config.b);
286                         config.a = input.tag.get_property("A", config.a);
287                 }
288         }
292 #define INVERT_MACRO(type, components, max) \
293 { \
294         for(int i = 0; i < input->get_h(); i++) \
295         { \
296                 type *in_row = (type*)input->get_rows()[i]; \
297                 type *out_row = (type*)output->get_rows()[i]; \
299                 for(int j = 0; j < w; j++) \
300                 { \
301                         if(config.r) out_row[0] = max - in_row[0]; \
302                         if(config.g) out_row[1] = max - in_row[1]; \
303                         if(config.b) out_row[2] = max - in_row[2]; \
304                         if(components == 4) \
305                                 if(config.a) out_row[3] = max - in_row[3]; \
307                         in_row += components; \
308                         out_row += components; \
309                 } \
310         } \
313 int InvertVideoEffect::process_realtime(VFrame *input, VFrame *output)
315         load_configuration();
317         if(!config.r && !config.g && !config.b && !config.a)
318         {
319                 if(input->get_rows()[0] != output->get_rows()[0])
320                         output->copy_from(input);
321         }
322         else
323         {
324                 int w = input->get_w();
326                 switch(input->get_color_model())
327                 {
328                         case BC_RGB888:
329                         case BC_YUV888:
330                                 INVERT_MACRO(unsigned char, 3, 0xff)
331                                 break;
332                         case BC_RGBA8888:
333                         case BC_YUVA8888:
334                                 INVERT_MACRO(unsigned char, 4, 0xff)
335                                 break;
336                         case BC_RGB161616:
337                         case BC_YUV161616:
338                                 INVERT_MACRO(uint16_t, 3, 0xffff)
339                                 break;
340                         case BC_RGBA16161616:
341                         case BC_YUVA16161616:
342                                 INVERT_MACRO(uint16_t, 4, 0xffff)
343                                 break;
344                 }
345         }
347         return 0;