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
23 * 2019. Derivative by Translate plugin. This plugin works also with Proxy.
24 * It uses Percent values instead of Pixel value coordinates.
38 REGISTER_PLUGIN(CropMain)
40 CropConfig::CropConfig()
42 reset(RESET_DEFAULT_SETTINGS);
45 void CropConfig::reset(int clear)
60 case RESET_POSITION_X :
63 case RESET_POSITION_Y :
67 case RESET_DEFAULT_SETTINGS :
81 int CropConfig::equivalent(CropConfig &that)
83 return EQUIV(crop_l, that.crop_l) &&
84 EQUIV(crop_t, that.crop_t) &&
85 EQUIV(crop_r, that.crop_r) &&
86 EQUIV(crop_b, that.crop_b) &&
87 EQUIV(position_x, that.position_x) &&
88 EQUIV(position_y, that.position_y);
91 void CropConfig::copy_from(CropConfig &that)
97 position_x = that.position_x;
98 position_y = that.position_y;
101 void CropConfig::interpolate(CropConfig &prev,
105 int64_t current_frame)
107 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
108 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
110 this->crop_l = prev.crop_l * prev_scale + next.crop_l * next_scale;
111 this->crop_t = prev.crop_t * prev_scale + next.crop_t * next_scale;
112 this->crop_r = prev.crop_r * prev_scale + next.crop_r * next_scale;
113 this->crop_b = prev.crop_b * prev_scale + next.crop_b * next_scale;
114 this->position_x = prev.position_x * prev_scale + next.position_x * next_scale;
115 this->position_y = prev.position_y * prev_scale + next.position_y * next_scale;
125 CropMain::CropMain(PluginServer *server)
126 : PluginVClient(server)
133 CropMain::~CropMain()
137 if(temp_frame) delete temp_frame;
139 if(overlayer) delete overlayer;
143 const char* CropMain::plugin_title() { return N_("Crop & Position"); }
144 int CropMain::is_realtime() { return 1; }
148 LOAD_CONFIGURATION_MACRO(CropMain, CropConfig)
150 void CropMain::save_data(KeyFrame *keyframe)
154 // cause data to be stored directly in text
155 output.set_shared_output(keyframe->xbuf);
158 output.tag.set_title("CROP");
159 output.tag.set_property("LEFT", config.crop_l);
160 output.tag.set_property("TOP", config.crop_t);
161 output.tag.set_property("RIGHT", config.crop_r);
162 output.tag.set_property("BOTTOM", config.crop_b);
163 output.tag.set_property("POSITION_X", config.position_x);
164 output.tag.set_property("POSITION_Y", config.position_y);
166 output.tag.set_title("/CROP");
168 output.append_newline();
169 output.terminate_string();
170 // data is now in *text
173 void CropMain::read_data(KeyFrame *keyframe)
177 input.set_shared_input(keyframe->xbuf);
183 result = input.read_tag();
187 if(input.tag.title_is("CROP"))
189 config.crop_l = input.tag.get_property("LEFT", config.crop_l);
190 config.crop_t = input.tag.get_property("TOP", config.crop_t);
191 config.crop_r = input.tag.get_property("RIGHT", config.crop_r);
192 config.crop_b = input.tag.get_property("BOTTOM", config.crop_b);
193 config.position_x = input.tag.get_property("POSITION_X", config.position_x);
194 config.position_y = input.tag.get_property("POSITION_Y", config.position_y);
201 #define EPSILON 0.001
203 int CropMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
205 VFrame *input = input_ptr;
206 VFrame *output = output_ptr;
208 load_configuration();
210 //printf("CropMain::process_realtime 1 %p\n", input);
211 if( input->get_rows()[0] == output->get_rows()[0] ) {
213 temp_frame->get_w() != input_ptr->get_w() ||
214 temp_frame->get_h() != input_ptr->get_h() ||
215 temp_frame->get_color_model() != input_ptr->get_color_model() ) ) {
220 temp_frame = new VFrame(input_ptr->get_w(), input_ptr->get_h(),
221 input->get_color_model(), 0);
222 temp_frame->copy_from(input);
225 //printf("CropMain::process_realtime 2 %p\n", input);
230 overlayer = new OverlayFrame(smp + 1);
233 output->clear_frame();
235 /* OLD code by "Translate" plugin
236 if( config.in_w < EPSILON ) return 1;
237 if( config.in_h < EPSILON ) return 1;
238 if( config.out_w < EPSILON ) return 1;
239 if( config.out_h < EPSILON ) return 1;
244 *** Little description of the points ***
245 Points (ix1, iy1) and (ix2, iy2) are the Camera coordinates:
246 (ix1, iy1) is the point on top-left,
247 (ix2, iy2) is the point on bottom-right.
248 Points (ox1, oy1) and (ox2, oy2) are the Projector coordinates:
249 (ox1, oy1) is the point on top-left,
250 (ox2, oy2) is the point on bottom-right.
253 // Convert from Percent to Pixel coordinate (Percent value in plugin GUI)
254 // so it works also for Proxy
255 float ix1 = config.crop_l / 100 * output->get_w();
257 ox1 += config.position_x / 100 * output->get_w();
258 float ix2 = ((100.00 - config.crop_r) / 100) * output->get_w();
265 if(ix2 > output->get_w())
266 ix2 = output->get_w();
268 // Convert from Percent to Pixel coordinate (Percent value in plugin GUI)
269 // so it works also for Proxy
270 float iy1 = config.crop_t / 100 * output->get_h();
272 oy1 += config.position_y / 100 * output->get_h();
273 float iy2 = ((100.00 - config.crop_b) / 100) * output->get_h();
280 if( iy2 > output->get_h() )
281 iy2 = output->get_h();
283 // Scale features: OLD code by "Translate" plugin.
284 // (I leave here for future development)
285 // Scale_: scale_x=scale_y=1. It means NO SCALE.
289 float ox2 = ox1 + (ix2 - ix1) * cx;
290 float oy2 = oy1 + (iy2 - iy1) * cy;
300 if( ox2 > output->get_w() ) {
301 ix2 -= (ox2 - output->get_w()) / cx;
302 ox2 = output->get_w();
304 if( oy2 > output->get_h() ) {
305 iy2 -= (oy2 - output->get_h()) / cy;
306 oy2 = output->get_h();
309 if( ix1 >= ix2 ) return 1;
310 if( iy1 >= iy2 ) return 1;
311 if( ox1 >= ox2 ) return 1;
312 if( oy1 >= oy2 ) return 1;
314 overlayer->overlay(output, input,
318 get_interpolation_type());
322 NEW_WINDOW_MACRO(CropMain, CropWin)
324 void CropMain::update_gui()
326 if( !thread ) return;
327 if( !load_configuration() ) return;
329 CropWin *window = (CropWin*)thread->window;
330 window->lock_window();
332 window->crop_l->update(config.crop_l);
333 window->crop_t->update(config.crop_t);
334 window->crop_r->update(config.crop_r);
335 window->crop_b->update(config.crop_b);
336 window->position_x->update(config.position_x);
337 window->position_y->update(config.position_y);
339 window->update(RESET_ALL);
341 window->unlock_window();