add auto zoombar/status color, fix 3 batchrender boobies, rotate plugin tweaks, add...
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / flip / flip.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 "clip.h"
23 #include "bccmodels.h"
24 #include "bchash.h"
25 #include "filexml.h"
26 #include "flip.h"
27 #include "flipwindow.h"
28 #include "language.h"
29
30 #include <stdint.h>
31 #include <string.h>
32
33 REGISTER_PLUGIN(FlipMain)
34
35
36
37
38
39
40 FlipConfig::FlipConfig()
41 {
42         flip_horizontal = 0;
43         flip_vertical = 0;
44 }
45
46 void FlipConfig::copy_from(FlipConfig &that)
47 {
48         flip_horizontal = that.flip_horizontal;
49         flip_vertical = that.flip_vertical;
50 }
51
52 int FlipConfig::equivalent(FlipConfig &that)
53 {
54         return flip_horizontal == that.flip_horizontal &&
55                 flip_vertical == that.flip_vertical;
56 }
57
58 void FlipConfig::interpolate(FlipConfig &prev,
59         FlipConfig &next,
60         long prev_frame,
61         long next_frame,
62         long current_frame)
63 {
64         this->flip_horizontal = prev.flip_horizontal;
65         this->flip_vertical = prev.flip_vertical;
66 }
67
68
69
70
71
72
73
74
75
76
77 FlipMain::FlipMain(PluginServer *server)
78  : PluginVClient(server)
79 {
80
81 }
82
83 FlipMain::~FlipMain()
84 {
85
86 }
87
88 const char* FlipMain::plugin_title() { return N_("Flip"); }
89 int FlipMain::is_realtime() { return 1; }
90
91
92 #define SWAP_PIXELS(type, components, in, out) \
93 { \
94         type temp = in[0]; \
95         in[0] = out[0]; \
96         out[0] = temp; \
97  \
98         temp = in[1]; \
99         in[1] = out[1]; \
100         out[1] = temp; \
101  \
102         temp = in[2]; \
103         in[2] = out[2]; \
104         out[2] = temp; \
105  \
106         if(components == 4) \
107         { \
108                 temp = in[3]; \
109                 in[3] = out[3]; \
110                 out[3] = temp; \
111         } \
112 }
113
114 #define FLIP_MACRO(type, components) \
115 { \
116         type **input_rows, **output_rows; \
117         type *input_row, *output_row; \
118         input_rows = ((type**)frame->get_rows()); \
119         output_rows = ((type**)frame->get_rows()); \
120  \
121         if(config.flip_vertical) \
122         { \
123                 for(i = 0, j = h - 1; i < h / 2; i++, j--) \
124                 { \
125                         input_row = input_rows[i]; \
126                         output_row = output_rows[j]; \
127                         for(k = 0; k < w; k++) \
128                         { \
129                                 SWAP_PIXELS(type, components, output_row, input_row); \
130                                 output_row += components; \
131                                 input_row += components; \
132                         } \
133                 } \
134         } \
135  \
136         if(config.flip_horizontal) \
137         { \
138                 for(i = 0; i < h; i++) \
139                 { \
140                         input_row = input_rows[i]; \
141                         output_row = output_rows[i] + (w - 1) * components; \
142                         for(k = 0; k < w / 2; k++) \
143                         { \
144                                 SWAP_PIXELS(type, components, output_row, input_row); \
145                                 input_row += components; \
146                                 output_row -= components; \
147                         } \
148                 } \
149         } \
150 }
151
152 int FlipMain::process_buffer(VFrame *frame,
153                 int64_t start_position,
154                 double frame_rate)
155 {
156         int i, j, k;
157         int w = frame->get_w();
158         int h = frame->get_h();
159         int colormodel = frame->get_color_model();
160
161         load_configuration();
162
163         read_frame(frame,
164                 0,
165                 get_source_position(),
166                 get_framerate(),
167                 get_use_opengl());
168
169
170
171         if(get_use_opengl())
172         {
173                 if(config.flip_vertical || config.flip_horizontal)
174                         return run_opengl();
175                 else
176                         return 0;
177         }
178
179         switch(colormodel)
180         {
181                 case BC_RGB888:
182                 case BC_YUV888:
183                         FLIP_MACRO(unsigned char, 3);
184                         break;
185                 case BC_RGB_FLOAT:
186                         FLIP_MACRO(float, 3);
187                         break;
188                 case BC_RGB161616:
189                 case BC_YUV161616:
190                         FLIP_MACRO(uint16_t, 3);
191                         break;
192                 case BC_RGBA8888:
193                 case BC_YUVA8888:
194                         FLIP_MACRO(unsigned char, 4);
195                         break;
196                 case BC_RGBA_FLOAT:
197                         FLIP_MACRO(float, 4);
198                         break;
199                 case BC_RGBA16161616:
200                 case BC_YUVA16161616:
201                         FLIP_MACRO(uint16_t, 4);
202                         break;
203         }
204         return 0;
205 }
206
207
208 NEW_WINDOW_MACRO(FlipMain, FlipWindow)
209 LOAD_CONFIGURATION_MACRO(FlipMain, FlipConfig)
210
211 void FlipMain::update_gui()
212 {
213         if(thread)
214         {
215                 load_configuration();
216                 thread->window->lock_window();
217                 ((FlipWindow*)thread->window)->flip_vertical->update((int)config.flip_vertical);
218                 ((FlipWindow*)thread->window)->flip_horizontal->update((int)config.flip_horizontal);
219                 thread->window->unlock_window();
220         }
221 }
222
223 void FlipMain::save_data(KeyFrame *keyframe)
224 {
225         FileXML output;
226
227 // cause data to be stored directly in text
228         output.set_shared_output(keyframe->xbuf);
229         output.tag.set_title("FLIP");
230         output.append_tag();
231         if(config.flip_vertical)
232         {
233                 output.tag.set_title("VERTICAL");
234                 output.append_tag();
235                 output.tag.set_title("/VERTICAL");
236                 output.append_tag();
237         }
238
239         if(config.flip_horizontal)
240         {
241                 output.tag.set_title("HORIZONTAL");
242                 output.append_tag();
243                 output.tag.set_title("/HORIZONTAL");
244                 output.append_tag();
245         }
246         output.tag.set_title("/FLIP");
247         output.append_tag();
248         output.append_newline();
249         output.terminate_string();
250 // data is now in *text
251 }
252
253 void FlipMain::read_data(KeyFrame *keyframe)
254 {
255         FileXML input;
256
257         input.set_shared_input(keyframe->xbuf);
258
259         int result = 0;
260         config.flip_vertical = config.flip_horizontal = 0;
261
262         while(!result)
263         {
264                 result = input.read_tag();
265
266                 if(!result)
267                 {
268                         if(input.tag.title_is("VERTICAL"))
269                         {
270                                 config.flip_vertical = 1;
271                         }
272                         else
273                         if(input.tag.title_is("HORIZONTAL"))
274                         {
275                                 config.flip_horizontal = 1;
276                         }
277                 }
278         }
279 }
280
281
282 int FlipMain::handle_opengl()
283 {
284 #ifdef HAVE_GL
285         get_output()->to_texture();
286         get_output()->enable_opengl();
287         get_output()->init_screen();
288         get_output()->bind_texture(0);
289
290         if(config.flip_vertical && !config.flip_horizontal)
291         {
292                 get_output()->draw_texture(0,
293                         0,
294                         get_output()->get_w(),
295                         get_output()->get_h(),
296                         0,
297                         get_output()->get_h(),
298                         get_output()->get_w(),
299                         0);
300         }
301
302         if(config.flip_horizontal && !config.flip_vertical)
303         {
304                 get_output()->draw_texture(0,
305                         0,
306                         get_output()->get_w(),
307                         get_output()->get_h(),
308                         get_output()->get_w(),
309                         0,
310                         0,
311                         get_output()->get_h());
312         }
313
314         if(config.flip_vertical && config.flip_horizontal)
315         {
316                 get_output()->draw_texture(0,
317                         0,
318                         get_output()->get_w(),
319                         get_output()->get_h(),
320                         get_output()->get_w(),
321                         get_output()->get_h(),
322                         0,
323                         0);
324         }
325
326         get_output()->set_opengl_state(VFrame::SCREEN);
327 #endif
328         return 0;
329 }
330
331
332