r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / scale / scale.C
blob8d84d7e5cd1a34ff2b0fa2ff392f018e04aea07e
1 #include "clip.h"
2 #include "filexml.h"
3 #include "picon_png.h"
4 #include "scale.h"
5 #include "scalewin.h"
7 #include <string.h>
9 #include <libintl.h>
10 #define _(String) gettext(String)
11 #define gettext_noop(String) String
12 #define N_(String) gettext_noop (String)
14 REGISTER_PLUGIN(ScaleMain)
18 ScaleConfig::ScaleConfig()
20         w = 1;
21         h = 1;
22         constrain = 0;
25 void ScaleConfig::copy_from(ScaleConfig &src)
27         w = src.w;
28         h = src.h;
29         constrain = src.constrain;
31 int ScaleConfig::equivalent(ScaleConfig &src)
33         return EQUIV(w, src.w) && 
34                 EQUIV(h, src.h) && 
35                 constrain == src.constrain;
38 void ScaleConfig::interpolate(ScaleConfig &prev, 
39         ScaleConfig &next, 
40         int64_t prev_frame, 
41         int64_t next_frame, 
42         int64_t current_frame)
44         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
45         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
47         this->w = prev.w * prev_scale + next.w * next_scale;
48         this->h = prev.h * prev_scale + next.h * next_scale;
49         this->constrain = prev.constrain;
59 ScaleMain::ScaleMain(PluginServer *server)
60  : PluginVClient(server)
62         temp_frame = 0;
63         overlayer = 0;
64         PLUGIN_CONSTRUCTOR_MACRO
67 ScaleMain::~ScaleMain()
69         PLUGIN_DESTRUCTOR_MACRO
71         if(temp_frame) delete temp_frame;
72         temp_frame = 0;
73         if(overlayer) delete overlayer;
74         overlayer = 0;
77 char* ScaleMain::plugin_title() { return _("Scale"); }
78 int ScaleMain::is_realtime() { return 1; }
80 NEW_PICON_MACRO(ScaleMain)
82 int ScaleMain::load_defaults()
84         char directory[1024], string[1024];
85 // set the default directory
86         sprintf(directory, "%sscale.rc", BCASTDIR);
88 // load the defaults
89         defaults = new Defaults(directory);
90         defaults->load();
92         config.w = defaults->get("WIDTH", config.w);
93         config.h = defaults->get("HEIGHT", config.h);
94         config.constrain = defaults->get("CONSTRAIN", config.constrain);
95 //printf("ScaleMain::load_defaults %f %f\n",config.w  , config.h);
98 int ScaleMain::save_defaults()
100         defaults->update("WIDTH", config.w);
101         defaults->update("HEIGHT", config.h);
102         defaults->update("CONSTRAIN", config.constrain);
103         defaults->save();
106 LOAD_CONFIGURATION_MACRO(ScaleMain, ScaleConfig)
109 void ScaleMain::save_data(KeyFrame *keyframe)
111         FileXML output;
113 // cause data to be stored directly in text
114         output.set_shared_string(keyframe->data, MESSAGESIZE);
116 // Store data
117         output.tag.set_title("SCALE");
118         output.tag.set_property("WIDTH", config.w);
119         output.tag.set_property("HEIGHT", config.h);
120         output.append_tag();
122         if(config.constrain)
123         {
124                 output.tag.set_title("CONSTRAIN");
125                 output.append_tag();
126         }
127         output.terminate_string();
128 // data is now in *text
131 void ScaleMain::read_data(KeyFrame *keyframe)
133         FileXML input;
135         input.set_shared_string(keyframe->data, strlen(keyframe->data));
137         int result = 0;
138         config.constrain = 0;
140         while(!result)
141         {
142                 result = input.read_tag();
144                 if(!result)
145                 {
146                         if(input.tag.title_is("SCALE"))
147                         {
148                                 config.w = input.tag.get_property("WIDTH", config.w);
149                                 config.h = input.tag.get_property("HEIGHT", config.h);
150                         }
151                         else
152                         if(input.tag.title_is("CONSTRAIN"))
153                         {
154                                 config.constrain = 1;
155                         }
156                 }
157         }
167 int ScaleMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
169         VFrame *input, *output;
170         
171         input = input_ptr;
172         output = output_ptr;
174         load_configuration();
176 //printf("ScaleMain::process_realtime 1 %p\n", input);
177         if(input->get_rows()[0] == output->get_rows()[0])
178         {
179                 if(!temp_frame) 
180                         temp_frame = new VFrame(0, 
181                                 input_ptr->get_w(), 
182                                 input_ptr->get_h(),
183                                 input->get_color_model());
184                 temp_frame->copy_from(input);
185                 input = temp_frame;
186         }
187 //printf("ScaleMain::process_realtime 2 %p\n", input);
189         if(!overlayer)
190         {
191                 overlayer = new OverlayFrame(smp + 1);
192         }
195         if(config.w == 1 && config.h == 1)
196         {
197 // No scaling
198                 if(input->get_rows()[0] != output->get_rows()[0])
199                 {
200                         output->copy_from(input);
201                 }
202         }
203         else
204         {
205 // Perform scaling
206                 float center_x, center_y;
207                 float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2;
209                 center_x = (float)input_ptr->get_w() / 2;
210                 center_y = (float)input_ptr->get_h() / 2;
211                 in_x1 = 0;
212                 in_x2 = input_ptr->get_w();
213                 in_y1 = 0;
214                 in_y2 = input_ptr->get_h();
215                 out_x1 = (float)center_x - (float)input_ptr->get_w() * config.w / 2;
216                 out_x2 = (float)center_x + (float)input_ptr->get_w() * config.w / 2;
217                 out_y1 = (float)center_y - (float)input_ptr->get_h() * config.h / 2;
218                 out_y2 = (float)center_y + (float)input_ptr->get_h() * config.h / 2;
221 //printf("ScaleMain::process_realtime %f = %d / 2\n", center_x, input_ptr->get_w());
222 //printf("ScaleMain::process_realtime %f = %f + %d * %f / 2\n", 
223 //      out_x1, center_x, input_ptr->get_w(), config.w);
225                 if(out_x1 < 0)
226                 {
227                         in_x1 += -out_x1 / config.w;
228                         out_x1 = 0;
229                 }
231                 if(out_x2 > input_ptr->get_w())
232                 {
233                         in_x2 -= (out_x2 - input_ptr->get_w()) / config.w;
234                         out_x2 = input_ptr->get_w();
235                 }
237                 if(out_y1 < 0)
238                 {
239                         in_y1 += -out_y1 / config.h;
240                         out_y1 = 0;
241                 }
243                 if(out_y2 > input_ptr->get_h())
244                 {
245                         in_y2 -= (out_y2 - input_ptr->get_h()) / config.h;
246                         out_y2 = input_ptr->get_h();
247                 }
249                 output->clear_frame();
251 // printf("ScaleMain::process_realtime 3 output=%p input=%p config.w=%f config.h=%f"
252 //      "%f %f %f %f -> %f %f %f %f\n", 
253 //      output,
254 //      input,
255 //      config.w, 
256 //      config.h,
257 //      in_x1, 
258 //      in_y1, 
259 //      in_x2, 
260 //      in_y2,
261 //      out_x1, 
262 //      out_y1, 
263 //      out_x2, 
264 //      out_y2);
265                 overlayer->overlay(output, 
266                         input,
267                         in_x1, 
268                         in_y1, 
269                         in_x2, 
270                         in_y2,
271                         out_x1, 
272                         out_y1, 
273                         out_x2, 
274                         out_y2, 
275                         1,
276                         TRANSFER_REPLACE,
277                         get_interpolation_type());
279         }
284 SHOW_GUI_MACRO(ScaleMain, ScaleThread)
285 RAISE_WINDOW_MACRO(ScaleMain)
286 SET_STRING_MACRO(ScaleMain)
288 void ScaleMain::update_gui()
290         if(thread) 
291         {
292                 load_configuration();
293                 thread->window->lock_window();
294                 thread->window->width->update(config.w);
295                 thread->window->height->update(config.h);
296                 thread->window->constrain->update(config.constrain);
297                 thread->window->unlock_window();
298         }