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
25 #include "translate.h"
26 #include "translatewin.h"
33 REGISTER_PLUGIN(TranslateMain)
35 TranslateConfig::TranslateConfig()
40 void TranslateConfig::reset()
53 int TranslateConfig::equivalent(TranslateConfig &that)
55 return EQUIV(in_x, that.in_x) &&
56 EQUIV(in_y, that.in_y) &&
57 EQUIV(in_w, that.in_w) &&
58 EQUIV(in_h, that.in_h) &&
59 EQUIV(out_x, that.out_x) &&
60 EQUIV(out_y, that.out_y) &&
61 EQUIV(out_w, that.out_w) &&
62 EQUIV(out_h, that.out_h);
65 void TranslateConfig::copy_from(TranslateConfig &that)
77 void TranslateConfig::interpolate(TranslateConfig &prev,
78 TranslateConfig &next,
81 int64_t current_frame)
83 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
84 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
86 this->in_x = prev.in_x * prev_scale + next.in_x * next_scale;
87 this->in_y = prev.in_y * prev_scale + next.in_y * next_scale;
88 this->in_w = prev.in_w * prev_scale + next.in_w * next_scale;
89 this->in_h = prev.in_h * prev_scale + next.in_h * next_scale;
90 this->out_x = prev.out_x * prev_scale + next.out_x * next_scale;
91 this->out_y = prev.out_y * prev_scale + next.out_y * next_scale;
92 this->out_w = prev.out_w * prev_scale + next.out_w * next_scale;
93 this->out_h = prev.out_h * prev_scale + next.out_h * next_scale;
103 TranslateMain::TranslateMain(PluginServer *server)
104 : PluginVClient(server)
111 TranslateMain::~TranslateMain()
115 if(temp_frame) delete temp_frame;
117 if(overlayer) delete overlayer;
121 const char* TranslateMain::plugin_title() { return N_("Translate"); }
122 int TranslateMain::is_realtime() { return 1; }
126 LOAD_CONFIGURATION_MACRO(TranslateMain, TranslateConfig)
128 void TranslateMain::save_data(KeyFrame *keyframe)
132 // cause data to be stored directly in text
133 output.set_shared_output(keyframe->xbuf);
136 output.tag.set_title("TRANSLATE");
137 output.tag.set_property("IN_X", config.in_x);
138 output.tag.set_property("IN_Y", config.in_y);
139 output.tag.set_property("IN_W", config.in_w);
140 output.tag.set_property("IN_H", config.in_h);
141 output.tag.set_property("OUT_X", config.out_x);
142 output.tag.set_property("OUT_Y", config.out_y);
143 output.tag.set_property("OUT_W", config.out_w);
144 output.tag.set_property("OUT_H", config.out_h);
146 output.tag.set_title("/TRANSLATE");
148 output.append_newline();
149 output.terminate_string();
150 // data is now in *text
153 void TranslateMain::read_data(KeyFrame *keyframe)
157 input.set_shared_input(keyframe->xbuf);
163 result = input.read_tag();
167 if(input.tag.title_is("TRANSLATE"))
169 config.in_x = input.tag.get_property("IN_X", config.in_x);
170 config.in_y = input.tag.get_property("IN_Y", config.in_y);
171 config.in_w = input.tag.get_property("IN_W", config.in_w);
172 config.in_h = input.tag.get_property("IN_H", config.in_h);
173 config.out_x = input.tag.get_property("OUT_X", config.out_x);
174 config.out_y = input.tag.get_property("OUT_Y", config.out_y);
175 config.out_w = input.tag.get_property("OUT_W", config.out_w);
176 config.out_h = input.tag.get_property("OUT_H", config.out_h);
183 #define EPSILON 0.001
185 int TranslateMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
187 VFrame *input = input_ptr;
188 VFrame *output = output_ptr;
190 load_configuration();
192 //printf("TranslateMain::process_realtime 1 %p\n", input);
193 if( input->get_rows()[0] == output->get_rows()[0] ) {
195 temp_frame->get_w() != input_ptr->get_w() ||
196 temp_frame->get_h() != input_ptr->get_h() ||
197 temp_frame->get_color_model() != input_ptr->get_color_model() ) ) {
202 temp_frame = new VFrame(input_ptr->get_w(), input_ptr->get_h(),
203 input->get_color_model(), 0);
204 temp_frame->copy_from(input);
207 //printf("TranslateMain::process_realtime 2 %p\n", input);
212 overlayer = new OverlayFrame(smp + 1);
215 output->clear_frame();
217 if( config.in_w < EPSILON ) return 1;
218 if( config.in_h < EPSILON ) return 1;
219 if( config.out_w < EPSILON ) return 1;
220 if( config.out_h < EPSILON ) return 1;
222 float ix1 = config.in_x, ox1 = config.out_x;
223 float ix2 = ix1 + config.in_w;
231 if(ix2 > output->get_w())
232 ix2 = output->get_w();
234 float iy1 = config.in_y, oy1 = config.out_y;
235 float iy2 = iy1 + config.in_h;
243 if( iy2 > output->get_h() )
244 iy2 = output->get_h();
246 float cx = config.out_w / config.in_w;
247 float cy = config.out_h / config.in_h;
249 float ox2 = ox1 + (ix2 - ix1) * cx;
250 float oy2 = oy1 + (iy2 - iy1) * cy;
260 if( ox2 > output->get_w() ) {
261 ix2 -= (ox2 - output->get_w()) / cx;
262 ox2 = output->get_w();
264 if( oy2 > output->get_h() ) {
265 iy2 -= (oy2 - output->get_h()) / cy;
266 oy2 = output->get_h();
269 if( ix1 >= ix2 ) return 1;
270 if( iy1 >= iy2 ) return 1;
271 if( ox1 >= ox2 ) return 1;
272 if( oy1 >= oy2 ) return 1;
274 overlayer->overlay(output, input,
278 get_interpolation_type());
282 NEW_WINDOW_MACRO(TranslateMain, TranslateWin)
284 void TranslateMain::update_gui()
286 if( !thread ) return;
287 if( !load_configuration() ) return;
289 TranslateWin *window = (TranslateWin*)thread->window;
290 window->lock_window();
291 window->in_x->update(config.in_x);
292 window->in_y->update(config.in_y);
293 window->in_w->update(config.in_w);
294 window->in_h->update(config.in_h);
295 window->out_x->update(config.out_x);
296 window->out_y->update(config.out_y);
297 window->out_w->update(config.out_w);
298 window->out_h->update(config.out_h);
299 window->unlock_window();