4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "shiftinterlace.h"
28 PluginClient* new_plugin(PluginServer *server)
30 return new ShiftInterlaceMain(server);
36 ShiftInterlaceConfig::ShiftInterlaceConfig()
41 void ShiftInterlaceConfig::reset(int clear)
44 case RESET_ODD_OFFSET : odd_offset = 0;
46 case RESET_EVEN_OFFSET : even_offset = 0;
57 int ShiftInterlaceConfig::equivalent(ShiftInterlaceConfig &that)
59 return (odd_offset == that.odd_offset &&
60 even_offset == that.even_offset);
63 void ShiftInterlaceConfig::copy_from(ShiftInterlaceConfig &that)
65 odd_offset = that.odd_offset;
66 even_offset = that.even_offset;
69 void ShiftInterlaceConfig::interpolate(ShiftInterlaceConfig &prev,
70 ShiftInterlaceConfig &next,
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);
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);
87 ShiftInterlaceWindow::ShiftInterlaceWindow(ShiftInterlaceMain *plugin)
88 : PluginClientWindow(plugin,
95 this->plugin = plugin;
99 void ShiftInterlaceWindow::create_objects()
101 int xs10 = xS(10), xs30 = xS(30), xs50 = xS(50), xs90 = xS(90);
102 int ys10 = yS(10), ys40 = yS(40);
103 int x = xs10, y = ys10;
105 int x1 = 0; int clrBtn_w = xs50;
107 add_subwindow(new BC_Title(x, y, _("Odd offset:")));
108 add_subwindow(odd_offset = new ShiftInterlaceOdd(plugin, x + xs90, y));
109 x1 = x + xs90 + odd_offset->get_w() + xs10;
110 add_subwindow(odd_offsetClr = new ShiftInterlaceSliderClr(plugin, this, x1, y, clrBtn_w, RESET_ODD_OFFSET));
113 add_subwindow(new BC_Title(x, y, _("Even offset:")));
114 add_subwindow(even_offset = new ShiftInterlaceEven(plugin, x + xs90, y));
115 add_subwindow(even_offsetClr = new ShiftInterlaceSliderClr(plugin, this, x1, y, clrBtn_w, RESET_EVEN_OFFSET));
118 add_subwindow(reset = new ShiftInterlaceReset(plugin, this, x, y));
124 void ShiftInterlaceWindow::update_gui(int clear)
127 case RESET_ODD_OFFSET : odd_offset->update(plugin->config.odd_offset);
129 case RESET_EVEN_OFFSET : even_offset->update(plugin->config.even_offset);
133 odd_offset->update(plugin->config.odd_offset);
134 even_offset->update(plugin->config.even_offset);
141 ShiftInterlaceOdd::ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y)
149 plugin->config.odd_offset)
151 this->plugin = plugin;
153 int ShiftInterlaceOdd::handle_event()
155 plugin->config.odd_offset = get_value();
156 plugin->send_configure_change();
163 ShiftInterlaceEven::ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y)
171 plugin->config.even_offset)
173 this->plugin = plugin;
177 int ShiftInterlaceEven::handle_event()
179 plugin->config.even_offset = get_value();
180 plugin->send_configure_change();
187 ShiftInterlaceReset::ShiftInterlaceReset(ShiftInterlaceMain *plugin, ShiftInterlaceWindow *gui, int x, int y)
188 : BC_GenericButton(x, y, _("Reset"))
190 this->plugin = plugin;
193 ShiftInterlaceReset::~ShiftInterlaceReset()
196 int ShiftInterlaceReset::handle_event()
198 plugin->config.reset(RESET_ALL);
199 gui->update_gui(RESET_ALL);
200 plugin->send_configure_change();
205 ShiftInterlaceSliderClr::ShiftInterlaceSliderClr(ShiftInterlaceMain *plugin, ShiftInterlaceWindow *gui, int x, int y, int w, int clear)
206 : BC_Button(x, y, w, plugin->get_theme()->get_image_set("reset_button"))
208 this->plugin = plugin;
212 ShiftInterlaceSliderClr::~ShiftInterlaceSliderClr()
215 int ShiftInterlaceSliderClr::handle_event()
217 // clear==1 ==> Odd slider
218 // clear==2 ==> Even slider
219 plugin->config.reset(clear);
220 gui->update_gui(clear);
221 plugin->send_configure_change();
233 ShiftInterlaceMain::ShiftInterlaceMain(PluginServer *server)
234 : PluginVClient(server)
239 ShiftInterlaceMain::~ShiftInterlaceMain()
245 const char* ShiftInterlaceMain::plugin_title() { return N_("ShiftInterlace"); }
246 int ShiftInterlaceMain::is_realtime() { return 1; }
252 LOAD_CONFIGURATION_MACRO(ShiftInterlaceMain, ShiftInterlaceConfig)
254 NEW_WINDOW_MACRO(ShiftInterlaceMain, ShiftInterlaceWindow)
258 void ShiftInterlaceMain::save_data(KeyFrame *keyframe)
262 // cause data to be stored directly in text
263 output.set_shared_output(keyframe->xbuf);
264 output.tag.set_title("SHIFTINTERLACE");
265 output.tag.set_property("ODD_OFFSET", config.odd_offset);
266 output.tag.set_property("EVEN_OFFSET", config.even_offset);
268 output.tag.set_title("/SHIFTINTERLACE");
270 output.append_newline();
271 output.terminate_string();
272 // data is now in *text
275 void ShiftInterlaceMain::read_data(KeyFrame *keyframe)
279 input.set_shared_input(keyframe->xbuf);
285 result = input.read_tag();
289 if(input.tag.title_is("SHIFTINTERLACE"))
291 config.odd_offset = input.tag.get_property("ODD_OFFSET", config.odd_offset);
292 config.even_offset = input.tag.get_property("EVEN_OFFSET", config.even_offset);
298 void ShiftInterlaceMain::update_gui()
302 load_configuration();
303 thread->window->lock_window();
304 ((ShiftInterlaceWindow*)thread->window)->odd_offset->update(config.odd_offset);
305 ((ShiftInterlaceWindow*)thread->window)->even_offset->update(config.even_offset);
306 thread->window->unlock_window();
311 #define SHIFT_ROW_MACRO(components, type, chroma_offset) \
313 type *input_row = (type*)input_frame->get_rows()[row]; \
314 type *output_row = (type*)output_frame->get_rows()[row]; \
319 for(i = 0, j = -offset; \
323 output_row[i * components + 0] = input_row[j * components + 0]; \
324 output_row[i * components + 1] = input_row[j * components + 1]; \
325 output_row[i * components + 2] = input_row[j * components + 2]; \
326 if(components == 4) output_row[i * components + 3] = input_row[j * components + 3]; \
331 output_row[i * components + 0] = 0; \
332 output_row[i * components + 1] = chroma_offset; \
333 output_row[i * components + 2] = chroma_offset; \
334 if(components == 4) output_row[i * components + 3] = 0; \
340 for(i = w - offset - 1, j = w - 1; \
345 output_row[j * components + 0] = input_row[i * components + 0]; \
346 output_row[j * components + 1] = input_row[i * components + 1]; \
347 output_row[j * components + 2] = input_row[i * components + 2]; \
348 if(components == 4) output_row[j * components + 3] = input_row[i * components + 3]; \
351 for( ; j >= 0; j--) \
353 output_row[j * components + 0] = 0; \
354 output_row[j * components + 1] = chroma_offset; \
355 output_row[j * components + 2] = chroma_offset; \
356 if(components == 4) output_row[j * components + 3] = 0; \
362 void ShiftInterlaceMain::shift_row(VFrame *input_frame,
363 VFrame *output_frame,
367 int w = input_frame->get_w();
368 switch(input_frame->get_color_model())
371 SHIFT_ROW_MACRO(3, unsigned char, 0x0)
374 SHIFT_ROW_MACRO(3, float, 0x0)
377 SHIFT_ROW_MACRO(3, unsigned char, 0x80)
380 SHIFT_ROW_MACRO(4, float, 0x0)
383 SHIFT_ROW_MACRO(4, unsigned char, 0x0)
386 SHIFT_ROW_MACRO(4, unsigned char, 0x80)
389 SHIFT_ROW_MACRO(3, uint16_t, 0x0)
392 SHIFT_ROW_MACRO(3, uint16_t, 0x8000)
394 case BC_RGBA16161616:
395 SHIFT_ROW_MACRO(4, uint16_t, 0x0)
397 case BC_YUVA16161616:
398 SHIFT_ROW_MACRO(4, uint16_t, 0x8000)
403 int ShiftInterlaceMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
405 load_configuration();
407 int h = input_ptr->get_h();
408 for(int i = 0; i < h; i++)
411 shift_row(input_ptr, output_ptr, config.even_offset, i);
413 shift_row(input_ptr, output_ptr, config.odd_offset, i);