update internationalization data
[goodguy/history.git] / cinelerra-5.0 / plugins / swapchannels / swapchannels.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "bchash.h"
25 #include "filexml.h"
26 #include "language.h"
27 #include "swapchannels.h"
28 #include "vframe.h"
29
30
31
32 #include <stdint.h>
33 #include <string.h>
34
35
36
37
38
39
40 REGISTER_PLUGIN(SwapMain)
41
42
43
44
45
46
47
48
49 SwapConfig::SwapConfig()
50 {
51         red = RED_SRC;
52         green = GREEN_SRC;
53         blue = BLUE_SRC;
54     alpha = ALPHA_SRC;
55 }
56
57
58 int SwapConfig::equivalent(SwapConfig &that)
59 {
60         return (red == that.red &&
61                 green == that.green &&
62                 blue == that.blue &&
63                 alpha == that.alpha);
64 }
65
66 void SwapConfig::copy_from(SwapConfig &that)
67 {
68         red = that.red;
69         green = that.green;
70         blue = that.blue;
71         alpha = that.alpha;
72 }
73
74
75
76
77
78
79
80
81 SwapWindow::SwapWindow(SwapMain *plugin)
82  : PluginClientWindow(plugin,
83         250, 
84         170, 
85         250, 
86         170, 
87         0)
88 {
89         this->plugin = plugin;
90 }
91
92 SwapWindow::~SwapWindow()
93 {
94 }
95
96         
97 void SwapWindow::create_objects()
98 {
99         int x = 10, y = 10;
100         int margin = 30;
101
102         add_subwindow(new BC_Title(x, y, _("Swap channels")));
103         y += margin;
104         add_subwindow(new BC_Title(x + 160, y + 5, _("-> Red")));
105         add_subwindow(red = new SwapMenu(plugin, &(plugin->config.red), x, y));
106         red->create_objects();
107         y += margin;
108         add_subwindow(new BC_Title(x + 160, y + 5, _("-> Green")));
109         add_subwindow(green = new SwapMenu(plugin, &(plugin->config.green), x, y));
110         green->create_objects();
111         y += margin;
112         add_subwindow(new BC_Title(x + 160, y + 5, _("-> Blue")));
113         add_subwindow(blue = new SwapMenu(plugin, &(plugin->config.blue), x, y));
114         blue->create_objects();
115         y += margin;
116         add_subwindow(new BC_Title(x + 160, y + 5, _("-> Alpha")));
117         add_subwindow(alpha = new SwapMenu(plugin, &(plugin->config.alpha), x, y));
118         alpha->create_objects();
119
120         show_window();
121         flush();
122 }
123
124
125
126
127
128
129
130
131
132 SwapMenu::SwapMenu(SwapMain *client, int *output, int x, int y)
133  : BC_PopupMenu(x, y, 150, client->output_to_text(*output))
134 {
135         this->client = client;
136         this->output = output;
137 }
138
139 int SwapMenu::handle_event()
140 {
141         client->send_configure_change();
142         return 1;
143 }
144
145 void SwapMenu::create_objects()
146 {
147         add_item(new SwapItem(this, client->output_to_text(RED_SRC)));
148         add_item(new SwapItem(this, client->output_to_text(GREEN_SRC)));
149         add_item(new SwapItem(this, client->output_to_text(BLUE_SRC)));
150         add_item(new SwapItem(this, client->output_to_text(ALPHA_SRC)));
151         add_item(new SwapItem(this, client->output_to_text(NO_SRC)));
152         add_item(new SwapItem(this, client->output_to_text(MAX_SRC)));
153 }
154
155
156
157
158 SwapItem::SwapItem(SwapMenu *menu, const char *title)
159  : BC_MenuItem(title)
160 {
161         this->menu = menu;
162 }
163
164 int SwapItem::handle_event()
165 {
166         menu->set_text(get_text());
167         *(menu->output) = menu->client->text_to_output(get_text());
168         menu->handle_event();
169         return 1;
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 SwapMain::SwapMain(PluginServer *server)
192  : PluginVClient(server)
193 {
194         reset();
195         
196 }
197
198 SwapMain::~SwapMain()
199 {
200         
201         
202 //      if(temp) delete temp;
203 }
204
205 void SwapMain::reset()
206 {
207         temp = 0;
208 }
209
210
211 const char* SwapMain::plugin_title()  { return _("Swap channels"); }
212 int SwapMain::is_synthesis() { return 1; }
213 int SwapMain::is_realtime()  { return 1; }
214
215 NEW_WINDOW_MACRO(SwapMain, SwapWindow)
216
217
218 void SwapMain::save_data(KeyFrame *keyframe)
219 {
220         FileXML output;
221
222 // cause data to be stored directly in text
223         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
224         output.tag.set_title("SWAPCHANNELS");
225         output.tag.set_property("RED", config.red);
226         output.tag.set_property("GREEN", config.green);
227         output.tag.set_property("BLUE", config.blue);
228         output.tag.set_property("ALPHA", config.alpha);
229         output.append_tag();
230         output.append_newline();
231         output.terminate_string();
232 // data is now in *text
233 }
234
235 void SwapMain::read_data(KeyFrame *keyframe)
236 {
237         FileXML input;
238
239         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
240
241         int result = 0;
242
243         while(!result)
244         {
245                 result = input.read_tag();
246
247                 if(!result)
248                 {
249                         if(input.tag.title_is("SWAPCHANNELS"))
250                         {
251                                 config.red = input.tag.get_property("RED", config.red);
252                                 config.green = input.tag.get_property("GREEN", config.green);
253                                 config.blue = input.tag.get_property("BLUE", config.blue);
254                                 config.alpha = input.tag.get_property("ALPHA", config.alpha);
255                         }
256                 }
257         }
258 }
259
260 void SwapMain::update_gui()
261 {
262         if(thread) 
263         {
264                 load_configuration();
265                 thread->window->lock_window();
266                 ((SwapWindow*)thread->window)->red->set_text(output_to_text(config.red));
267                 ((SwapWindow*)thread->window)->green->set_text(output_to_text(config.green));
268                 ((SwapWindow*)thread->window)->blue->set_text(output_to_text(config.blue));
269                 ((SwapWindow*)thread->window)->alpha->set_text(output_to_text(config.alpha));
270                 thread->window->unlock_window();
271         }
272 }
273
274
275 int SwapMain::load_configuration()
276 {
277         KeyFrame *prev_keyframe;
278         prev_keyframe = get_prev_keyframe(get_source_position());
279         
280         read_data(prev_keyframe);
281         return 1;
282 }
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 #define MAXMINSRC(src, min, max) \
308         (src == MAX_SRC ? max : min)
309
310 #define SWAP_CHANNELS(type, min, max, components) \
311 { \
312         int h = frame->get_h(); \
313         int w = frame->get_w(); \
314         int red = config.red; \
315         int green = config.green; \
316         int blue = config.blue; \
317         int alpha = config.alpha; \
318  \
319         if(components == 3) \
320         { \
321                 if(red == ALPHA_SRC) red = MAX_SRC; \
322                 if(green == ALPHA_SRC) green = MAX_SRC; \
323                 if(blue == ALPHA_SRC) blue = MAX_SRC; \
324         } \
325  \
326  \
327         for(int i = 0; i < h; i++) \
328         { \
329                 type *inrow = (type*)frame->get_rows()[i]; \
330                 type *outrow = (type*)temp->get_rows()[i]; \
331  \
332                 for(int j = 0; j < w; j++) \
333                 { \
334                         if(red < 4) \
335                                 *outrow++ = *(inrow + red); \
336                         else \
337                                 *outrow++ = MAXMINSRC(red, 0, max); \
338  \
339                         if(green < 4) \
340                                 *outrow++ = *(inrow + green); \
341                         else \
342                                 *outrow++ = MAXMINSRC(green, min, max); \
343  \
344                         if(blue < 4) \
345                                 *outrow++ = *(inrow + blue); \
346                         else \
347                                 *outrow++ = MAXMINSRC(blue, min, max); \
348  \
349                         if(components == 4) \
350                         { \
351                                 if(alpha < 4) \
352                                         *outrow++ = *(inrow + alpha); \
353                                 else \
354                                         *outrow++ = MAXMINSRC(alpha, 0, max); \
355                         } \
356  \
357                         inrow += components; \
358                 } \
359         } \
360  \
361         frame->copy_from(temp); \
362 }
363
364
365
366 int SwapMain::process_buffer(VFrame *frame,
367         int64_t start_position,
368         double frame_rate)
369 {
370         load_configuration();
371
372         read_frame(frame, 
373                 0, 
374                 start_position, 
375                 frame_rate,
376                 get_use_opengl());
377
378
379 // Use hardware
380         if(get_use_opengl())
381         {
382                 run_opengl();
383                 return 0;
384         }
385
386
387         temp = new_temp(frame->get_w(), 
388                 frame->get_h(), 
389                 frame->get_color_model());
390
391         switch(frame->get_color_model())
392         {
393                 case BC_RGB_FLOAT:
394                         SWAP_CHANNELS(float, 0, 1, 3);
395                         break;
396                 case BC_RGBA_FLOAT:
397                         SWAP_CHANNELS(float, 0, 1, 4);
398                         break;
399                 case BC_RGB888:
400                         SWAP_CHANNELS(unsigned char, 0, 0xff, 3);
401                         break;
402                 case BC_YUV888:
403                         SWAP_CHANNELS(unsigned char, 0x80, 0xff, 3);
404                         break;
405                 case BC_RGBA8888:
406                         SWAP_CHANNELS(unsigned char, 0, 0xff, 4);
407                         break;
408                 case BC_YUVA8888:
409                         SWAP_CHANNELS(unsigned char, 0x80, 0xff, 4);
410                         break;
411         }
412         
413         
414         return 0;
415 }
416
417
418 const char* SwapMain::output_to_text(int value)
419 {
420         switch(value)
421         {
422                 case RED_SRC:
423                         return _("Red");
424                         break;
425                 case GREEN_SRC:
426                         return _("Green");
427                         break;
428                 case BLUE_SRC:
429                         return _("Blue");
430                         break;
431                 case ALPHA_SRC:
432                         return _("Alpha");
433                         break;
434                 case NO_SRC:
435                         return "0%";
436                         break;
437                 case MAX_SRC:
438                         return "100%";
439                         break;
440                 default:
441                         return "";
442                         break;
443         }
444 }
445
446 int SwapMain::text_to_output(const char *text)
447 {
448         if(!strcmp(text, _("Red"))) return RED_SRC;
449         if(!strcmp(text, _("Green"))) return GREEN_SRC;
450         if(!strcmp(text, _("Blue"))) return BLUE_SRC;
451         if(!strcmp(text, _("Alpha"))) return ALPHA_SRC;
452         if(!strcmp(text, "0%")) return NO_SRC;
453         if(!strcmp(text, "100%")) return MAX_SRC;
454         return 0;
455 }
456
457 int SwapMain::handle_opengl()
458 {
459 #ifdef HAVE_GL
460
461         char output_frag[BCTEXTLEN];
462         sprintf(output_frag, 
463                 "uniform sampler2D tex;\n"
464                 "uniform float chroma_offset;\n"
465                 "void main()\n"
466                 "{\n"
467                 "       vec4 in_color = texture2D(tex, gl_TexCoord[0].st);\n"
468                 "       vec4 out_color;\n");
469
470 #define COLOR_SWITCH(config, variable) \
471         strcat(output_frag, "   out_color." variable " = "); \
472         switch(config) \
473         { \
474                 case RED_SRC: strcat(output_frag, "in_color.r;\n"); break; \
475                 case GREEN_SRC: strcat(output_frag, "in_color.g;\n"); break; \
476                 case BLUE_SRC: strcat(output_frag, "in_color.b;\n"); break; \
477                 case ALPHA_SRC: strcat(output_frag, "in_color.a;\n"); break; \
478                 case NO_SRC: strcat(output_frag, "chroma_offset;\n"); break; \
479                 case MAX_SRC: strcat(output_frag, "1.0;\n"); break; \
480         }
481
482
483         COLOR_SWITCH(config.red, "r");
484         COLOR_SWITCH(config.green, "g");
485         COLOR_SWITCH(config.blue, "b");
486         COLOR_SWITCH(config.alpha, "a");
487
488         strcat(output_frag, 
489                 "       gl_FragColor = out_color;\n"
490                 "}\n");
491
492         get_output()->to_texture();
493         get_output()->enable_opengl();
494         get_output()->init_screen();
495         get_output()->clear_pbuffer();
496         get_output()->bind_texture(0);
497
498         unsigned int shader_id = VFrame::make_shader(0,
499                 output_frag,
500                 0);
501         glUseProgram(shader_id);
502         glUniform1i(glGetUniformLocation(shader_id, "tex"), 0);
503         glUniform1f(glGetUniformLocation(shader_id, "chroma_offset"), 
504                 BC_CModels::is_yuv(get_output()->get_color_model()) ? 0.5 : 0.0);
505
506         get_output()->draw_texture();
507         glUseProgram(0);
508         get_output()->set_opengl_state(VFrame::SCREEN);
509 #endif
510         return 0;
511 }
512
513
514