modify clr btn 16 plugins, add regdmp for sigtraps, rework mask_engine, mask rotate...
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / shiftinterlace / shiftinterlace.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 "shiftinterlace.h"
23
24
25
26
27
28 PluginClient* new_plugin(PluginServer *server)
29 {
30         return new ShiftInterlaceMain(server);
31 }
32
33
34
35
36 ShiftInterlaceConfig::ShiftInterlaceConfig()
37 {
38         reset(RESET_ALL);
39 }
40
41 void ShiftInterlaceConfig::reset(int clear)
42 {
43         switch(clear) {
44                 case RESET_ODD_OFFSET : odd_offset = 0;
45                         break;
46                 case RESET_EVEN_OFFSET : even_offset = 0;
47                         break;
48                 case RESET_ALL :
49                 default:
50                         odd_offset = 0;
51                         even_offset = 0;
52                         break;
53         }
54 }
55
56
57 int ShiftInterlaceConfig::equivalent(ShiftInterlaceConfig &that)
58 {
59         return (odd_offset == that.odd_offset &&
60                 even_offset == that.even_offset);
61 }
62
63 void ShiftInterlaceConfig::copy_from(ShiftInterlaceConfig &that)
64 {
65         odd_offset = that.odd_offset;
66         even_offset = that.even_offset;
67 }
68
69 void ShiftInterlaceConfig::interpolate(ShiftInterlaceConfig &prev,
70                 ShiftInterlaceConfig &next,
71                 long prev_frame,
72                 long next_frame,
73                 long current_frame)
74 {
75         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
76         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
77
78         this->odd_offset = (int)(prev.odd_offset * prev_scale + next.odd_offset * next_scale);
79         this->even_offset = (int)(prev.even_offset * prev_scale + next.even_offset * next_scale);
80 }
81
82
83
84
85
86
87 ShiftInterlaceWindow::ShiftInterlaceWindow(ShiftInterlaceMain *plugin)
88  : PluginClientWindow(plugin,
89         370,
90         110,
91         370,
92         110,
93         0)
94 {
95         this->plugin = plugin;
96 }
97
98
99 void ShiftInterlaceWindow::create_objects()
100 {
101         int x = 10, y = 10;
102         int margin = 30;
103         int x1 = 0; int clrBtn_w = 50;
104
105         add_subwindow(new BC_Title(x, y, _("Odd offset:")));
106         add_subwindow(odd_offset = new ShiftInterlaceOdd(plugin, x + 90, y));
107         x1 = x + 90 + odd_offset->get_w() + 10;
108         add_subwindow(odd_offsetClr = new ShiftInterlaceSliderClr(plugin, this, x1, y, clrBtn_w, RESET_ODD_OFFSET));
109
110         y += margin;
111         add_subwindow(new BC_Title(x, y, _("Even offset:")));
112         add_subwindow(even_offset = new ShiftInterlaceEven(plugin, x + 90, y));
113         add_subwindow(even_offsetClr = new ShiftInterlaceSliderClr(plugin, this, x1, y, clrBtn_w, RESET_EVEN_OFFSET));
114
115         y += 40;
116         add_subwindow(reset = new ShiftInterlaceReset(plugin, this, x, y));
117         show_window();
118         flush();
119 }
120
121 // for Reset button
122 void ShiftInterlaceWindow::update_gui(int clear)
123 {
124         switch(clear) {
125                 case RESET_ODD_OFFSET : odd_offset->update(plugin->config.odd_offset);
126                         break;
127                 case RESET_EVEN_OFFSET : even_offset->update(plugin->config.even_offset);
128                         break;
129                 case RESET_ALL :
130                 default:
131                         odd_offset->update(plugin->config.odd_offset);
132                         even_offset->update(plugin->config.even_offset);
133                         break;
134         }
135 }
136
137
138
139 ShiftInterlaceOdd::ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y)
140  : BC_ISlider(x,
141         y,
142         0,
143         200,
144         200,
145         -100,
146         100,
147         plugin->config.odd_offset)
148 {
149         this->plugin = plugin;
150 }
151 int ShiftInterlaceOdd::handle_event()
152 {
153         plugin->config.odd_offset = get_value();
154         plugin->send_configure_change();
155         return 1;
156 }
157
158
159
160
161 ShiftInterlaceEven::ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y)
162  : BC_ISlider(x,
163         y,
164         0,
165         200,
166         200,
167         -100,
168         100,
169         plugin->config.even_offset)
170 {
171         this->plugin = plugin;
172 }
173
174
175 int ShiftInterlaceEven::handle_event()
176 {
177         plugin->config.even_offset = get_value();
178         plugin->send_configure_change();
179         return 1;
180 }
181
182
183
184
185 ShiftInterlaceReset::ShiftInterlaceReset(ShiftInterlaceMain *plugin, ShiftInterlaceWindow *gui, int x, int y)
186  : BC_GenericButton(x, y, _("Reset"))
187 {
188         this->plugin = plugin;
189         this->gui = gui;
190 }
191 ShiftInterlaceReset::~ShiftInterlaceReset()
192 {
193 }
194 int ShiftInterlaceReset::handle_event()
195 {
196         plugin->config.reset(RESET_ALL);
197         gui->update_gui(RESET_ALL);
198         plugin->send_configure_change();
199         return 1;
200 }
201
202
203 ShiftInterlaceSliderClr::ShiftInterlaceSliderClr(ShiftInterlaceMain *plugin, ShiftInterlaceWindow *gui, int x, int y, int w, int clear)
204  : BC_Button(x, y, w, plugin->get_theme()->get_image_set("reset_button"))
205 {
206         this->plugin = plugin;
207         this->gui = gui;
208         this->clear = clear;
209 }
210 ShiftInterlaceSliderClr::~ShiftInterlaceSliderClr()
211 {
212 }
213 int ShiftInterlaceSliderClr::handle_event()
214 {
215         // clear==1 ==> Odd slider
216         // clear==2 ==> Even slider
217         plugin->config.reset(clear);
218         gui->update_gui(clear);
219         plugin->send_configure_change();
220         return 1;
221 }
222
223
224
225
226
227
228
229
230
231 ShiftInterlaceMain::ShiftInterlaceMain(PluginServer *server)
232  : PluginVClient(server)
233 {
234
235 }
236
237 ShiftInterlaceMain::~ShiftInterlaceMain()
238 {
239
240 }
241
242
243 const char* ShiftInterlaceMain::plugin_title() { return N_("ShiftInterlace"); }
244 int ShiftInterlaceMain::is_realtime() { return 1; }
245
246
247
248
249
250 LOAD_CONFIGURATION_MACRO(ShiftInterlaceMain, ShiftInterlaceConfig)
251
252 NEW_WINDOW_MACRO(ShiftInterlaceMain, ShiftInterlaceWindow)
253
254
255
256 void ShiftInterlaceMain::save_data(KeyFrame *keyframe)
257 {
258         FileXML output;
259
260 // cause data to be stored directly in text
261         output.set_shared_output(keyframe->xbuf);
262         output.tag.set_title("SHIFTINTERLACE");
263         output.tag.set_property("ODD_OFFSET", config.odd_offset);
264         output.tag.set_property("EVEN_OFFSET", config.even_offset);
265         output.append_tag();
266         output.tag.set_title("/SHIFTINTERLACE");
267         output.append_tag();
268         output.append_newline();
269         output.terminate_string();
270 // data is now in *text
271 }
272
273 void ShiftInterlaceMain::read_data(KeyFrame *keyframe)
274 {
275         FileXML input;
276
277         input.set_shared_input(keyframe->xbuf);
278
279         int result = 0;
280
281         while(!result)
282         {
283                 result = input.read_tag();
284
285                 if(!result)
286                 {
287                         if(input.tag.title_is("SHIFTINTERLACE"))
288                         {
289                                 config.odd_offset = input.tag.get_property("ODD_OFFSET", config.odd_offset);
290                                 config.even_offset = input.tag.get_property("EVEN_OFFSET", config.even_offset);
291                         }
292                 }
293         }
294 }
295
296 void ShiftInterlaceMain::update_gui()
297 {
298         if(thread)
299         {
300                 load_configuration();
301                 thread->window->lock_window();
302                 ((ShiftInterlaceWindow*)thread->window)->odd_offset->update(config.odd_offset);
303                 ((ShiftInterlaceWindow*)thread->window)->even_offset->update(config.even_offset);
304                 thread->window->unlock_window();
305         }
306 }
307
308
309 #define SHIFT_ROW_MACRO(components, type, chroma_offset) \
310 { \
311         type *input_row = (type*)input_frame->get_rows()[row]; \
312         type *output_row = (type*)output_frame->get_rows()[row]; \
313  \
314         if(offset < 0) \
315         { \
316                 int i, j; \
317                 for(i = 0, j = -offset;  \
318                         j < w;  \
319                         i++, j++) \
320                 { \
321                         output_row[i * components + 0] = input_row[j * components + 0]; \
322                         output_row[i * components + 1] = input_row[j * components + 1]; \
323                         output_row[i * components + 2] = input_row[j * components + 2]; \
324                         if(components == 4) output_row[i * components + 3] = input_row[j * components + 3]; \
325                 } \
326  \
327                 for( ; i < w; i++) \
328                 { \
329                         output_row[i * components + 0] = 0; \
330                         output_row[i * components + 1] = chroma_offset; \
331                         output_row[i * components + 2] = chroma_offset; \
332                         if(components == 4) output_row[i * components + 3] = 0; \
333                 } \
334         } \
335         else \
336         { \
337                 int i, j; \
338                 for(i = w - offset - 1, j = w - 1; \
339                         j >= offset; \
340                         i--, \
341                         j--) \
342                 { \
343                         output_row[j * components + 0] = input_row[i * components + 0]; \
344                         output_row[j * components + 1] = input_row[i * components + 1]; \
345                         output_row[j * components + 2] = input_row[i * components + 2]; \
346                         if(components == 4) output_row[j * components + 3] = input_row[i * components + 3]; \
347                 } \
348  \
349                 for( ; j >= 0; j--) \
350                 { \
351                         output_row[j * components + 0] = 0; \
352                         output_row[j * components + 1] = chroma_offset; \
353                         output_row[j * components + 2] = chroma_offset; \
354                         if(components == 4) output_row[j * components + 3] = 0; \
355                 } \
356         } \
357 }
358
359
360 void ShiftInterlaceMain::shift_row(VFrame *input_frame,
361         VFrame *output_frame,
362         int offset,
363         int row)
364 {
365         int w = input_frame->get_w();
366         switch(input_frame->get_color_model())
367         {
368                 case BC_RGB888:
369                         SHIFT_ROW_MACRO(3, unsigned char, 0x0)
370                         break;
371                 case BC_RGB_FLOAT:
372                         SHIFT_ROW_MACRO(3, float, 0x0)
373                         break;
374                 case BC_YUV888:
375                         SHIFT_ROW_MACRO(3, unsigned char, 0x80)
376                         break;
377                 case BC_RGBA_FLOAT:
378                         SHIFT_ROW_MACRO(4, float, 0x0)
379                         break;
380                 case BC_RGBA8888:
381                         SHIFT_ROW_MACRO(4, unsigned char, 0x0)
382                         break;
383                 case BC_YUVA8888:
384                         SHIFT_ROW_MACRO(4, unsigned char, 0x80)
385                         break;
386                 case BC_RGB161616:
387                         SHIFT_ROW_MACRO(3, uint16_t, 0x0)
388                         break;
389                 case BC_YUV161616:
390                         SHIFT_ROW_MACRO(3, uint16_t, 0x8000)
391                         break;
392                 case BC_RGBA16161616:
393                         SHIFT_ROW_MACRO(4, uint16_t, 0x0)
394                         break;
395                 case BC_YUVA16161616:
396                         SHIFT_ROW_MACRO(4, uint16_t, 0x8000)
397                         break;
398         }
399 }
400
401 int ShiftInterlaceMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
402 {
403         load_configuration();
404
405         int h = input_ptr->get_h();
406         for(int i = 0; i < h; i++)
407         {
408                 if(i % 2)
409                         shift_row(input_ptr, output_ptr, config.even_offset, i);
410                 else
411                         shift_row(input_ptr, output_ptr, config.odd_offset, i);
412         }
413
414         return 0;
415 }
416
417