r885: Don't delete a borrowed frame.
[cinelerra_cv/ct.git] / cinelerra / scale.C
blobecde487389f18d5a0bd388503a2381f1536c7138
1 #include "bchash.h"
2 #include "mainundo.h"
3 #include "mwindow.h"
4 #include "scale.h"
5 #include "mainsession.h"
6 #include "tracks.h"
7 #include "videowindow.h"
9 #include <libintl.h>
10 #define _(String) gettext(String)
11 #define gettext_noop(String) String
12 #define N_(String) gettext_noop (String)
14 Scale::Scale(MWindow *mwindow)
15  : BC_MenuItem(_("Resize..."))
16
17         this->mwindow = mwindow; 
18         thread = new ScaleThread(mwindow);
21 Scale::~Scale() 
23         delete thread;
26 int Scale::handle_event()
28         thread->start();
31 ScaleThread::ScaleThread(MWindow *mwindow)
32  : Thread()
33
34         this->mwindow = mwindow; 
35         already_running = 0;
38 ScaleThread::~ScaleThread() {}
40 void ScaleThread::run()
42         if(already_running) return;
43         already_running = 1;
44         constrain_ratio = mwindow->defaults->get("SCALECONSTRAIN", 0);
45         scale_data = mwindow->defaults->get("SCALEDATA", 0);
46         auto_aspect = mwindow->defaults->get("AUDIOASPECT", 0);
47         offsets[0] = offsets[1] = offsets[2] = offsets[3] = 0;
49         orig_dimension[0] = dimension[0] = mwindow->session->track_w;
50         orig_dimension[1] = dimension[1] = mwindow->session->track_h;
51         orig_dimension[2] = dimension[2] = mwindow->session->output_w;
52         orig_dimension[3] = dimension[3] = mwindow->session->output_h;
53         ratio[0] = ratio[1] = ratio[2] = ratio[3] = 1;
54         aspect_w = mwindow->session->aspect_w;
55         aspect_h = mwindow->session->aspect_h;
57         window = new ScaleWindow(this);
58         window->create_objects();
59         int result = window->run_window();
60         if(!result)
61         {
62                 int dummy_offsets[4];
63                 dummy_offsets[0] = dummy_offsets[1] = dummy_offsets[2] = dummy_offsets[3] = 0;
64 // Fake the offsets if data is scaled.
66 // fix tracks
67                 //mwindow->stop_playback(1);
68 // save the before undo
69                 mwindow->undo->update_undo_edits("Resize", 0);
70                 mwindow->tracks->scale_video(dimension, scale_data ? dummy_offsets : offsets, scale_data);
71                 mwindow->session->track_w = dimension[0];
72                 mwindow->session->track_h = dimension[1];
73                 mwindow->session->output_w = dimension[2];
74                 mwindow->session->output_h = dimension[3];
75                 mwindow->session->aspect_w = aspect_w;
76                 mwindow->session->aspect_h = aspect_h;
77                 mwindow->video_window->resize_window();
78                 mwindow->draw();
79                 mwindow->undo->update_undo_edits();
80                 mwindow->session->changes_made = 1;
81                 mwindow->defaults->update("ASPECTW", aspect_w);
82                 mwindow->defaults->update("ASPECTH", aspect_h);
83                 mwindow->defaults->update("AUTOASPECT", auto_aspect);
84         }
85         delete window;
87         mwindow->defaults->update("SCALECONSTRAIN", constrain_ratio);
88         mwindow->defaults->update("SCALEDATA", scale_data);
89         already_running = 0;
92 int ScaleThread::update_window(int offset_updated)
94         int pair_start = 0;
95         int i, result, modified_item, dimension_modified = 0, ratio_modified = 0;
97         for(i = 0, result = 0; i < 4 && !result; i++)
98         {
99                 if(i == 2) pair_start = 2;
100                 if(dimension[i] < 0)
101                 {
102                         dimension[i] *= -1;
103                         result = 1;
104                         modified_item = i;
105                         dimension_modified = 1;
106                 }
107                 if(ratio[i] < 0)
108                 {
109                         ratio[i] *= -1;
110                         result = 1;
111                         modified_item = i;
112                         ratio_modified = 1;
113                 }
114         }
116         if(result)
117         {
118                 if(dimension_modified)
119                         ratio[modified_item] = (float)dimension[modified_item] / orig_dimension[modified_item];
121                 if(ratio_modified && !constrain_ratio)
122                 {
123                         dimension[modified_item] = (int)(orig_dimension[modified_item] * ratio[modified_item]);
124                         window->dimension[modified_item]->update((long)dimension[modified_item]);
125                 }
127                 for(i = pair_start; i < pair_start + 2 && constrain_ratio; i++)
128                 {
129                         if(dimension_modified ||
130                                 (i != modified_item && ratio_modified))
131                         {
132                                 ratio[i] = ratio[modified_item];
133                                 window->ratio[i]->update(ratio[i]);
134                         }
136                         if(ratio_modified ||
137                                 (i != modified_item && dimension_modified))
138                         {
139                                 dimension[i] = (int)(orig_dimension[i] * ratio[modified_item]);
140                                 window->dimension[i]->update((long)dimension[i]);
141                         }
142                 }
143         }
145 //      window->position1->draw();
146 //      window->position2->draw();
147 //printf("%d\n", offsets[0]);
148 //      if(!offset_updated)
149 //      {
150 //              window->offsets[0]->update(offsets[0]);
151 //              window->offsets[1]->update(offsets[1]);
152 //              window->offsets[2]->update(offsets[2]);
153 //              window->offsets[3]->update(offsets[3]);
154 //      }
155         
156         update_aspect(window);
157         return 0;
160 int ScaleThread::update_aspect(ScaleWindow *window)
162         if(auto_aspect)
163         {
164                 char string[1024];
165                 mwindow->create_aspect_ratio(aspect_w, aspect_h, dimension[2], dimension[3]);
166                 sprintf(string, "%.0f", aspect_w);
167                 window->aspect_w->update(string);
168                 sprintf(string, "%.0f", aspect_h);
169                 window->aspect_h->update(string);
170         }
175 ScaleWindow::ScaleWindow(ScaleThread *thread)
176  : BC_Window(PROGRAM_NAME ": Scale", 370, 260, 0, 0)
177 { this->thread = thread; }
179 ScaleWindow::~ScaleWindow()
183 int ScaleWindow::create_objects()
185         int x = 10, y = 10;
186         add_subwindow(new BC_Title(x, y, _("New camera size:")));
187         add_subwindow(new BC_Title(x + 200, y, _("New projector size:")));
188         y += 30;
189         add_subwindow(new BC_Title(x, y, _("Width:")));
190         x += 70;
191         add_subwindow(dimension[0] = new ScaleSizeText(x, y, thread, &(thread->dimension[0])));
192         x += 110;
193         add_subwindow(new BC_Title(x, y, _("Width:")));
194         x += 70;
195         add_subwindow(dimension[2] = new ScaleSizeText(x, y, thread, &(thread->dimension[2])));
197         y += 30;
198         x = 10;
199         add_subwindow(new BC_Title(x, y, _("Height:")));
200         x += 70;
201         add_subwindow(dimension[1] = new ScaleSizeText(x, y, thread, &(thread->dimension[1])));
202         x += 110;
203         add_subwindow(new BC_Title(x, y, _("Height:")));
204         x += 70;
205         add_subwindow(dimension[3] = new ScaleSizeText(x, y, thread, &(thread->dimension[3])));
207         y += 30;
208         x = 10;
209         add_subwindow(new BC_Title(x, y, _("W Ratio:")));
210         x += 70;
211         add_subwindow(ratio[0] = new ScaleRatioText(x, y, thread, &(thread->ratio[0])));
212         x += 110;
213         add_subwindow(new BC_Title(x, y, _("W Ratio:")));
214         x += 70;
215         add_subwindow(ratio[2] = new ScaleRatioText(x, y, thread, &(thread->ratio[2])));
217         y += 30;
218         x = 10;
219         add_subwindow(new BC_Title(x, y, _("H Ratio:")));
220         x += 70;
221         add_subwindow(ratio[1] = new ScaleRatioText(x, y, thread, &(thread->ratio[1])));
222         x += 110;
223         add_subwindow(new BC_Title(x, y, _("H Ratio:")));
224         x += 70;
225         add_subwindow(ratio[3] = new ScaleRatioText(x, y, thread, &(thread->ratio[3])));
227 //      y += 30;
228 //      x = 10;
229 //      add_subwindow(new BC_Title(x, y, "X Offset:"));
230 //      x += 70;
231 //      add_subwindow(offsets[0] = new ScaleOffsetText(x, y, thread, &(thread->offsets[0])));
232 //      x += 110;
233 //      add_subwindow(new BC_Title(x, y, "X Offset:"));
234 //      x += 70;
235 //      add_subwindow(offsets[2] = new ScaleOffsetText(x, y, thread, &(thread->offsets[2])));
237 //      y += 30;
238 //      x = 10;
239 //      add_subwindow(new BC_Title(x, y, "Y Offset:"));
240 //      x += 70;
241 //      add_subwindow(offsets[1] = new ScaleOffsetText(x, y, thread, &(thread->offsets[1])));
242 //      x += 110;
243 //      add_subwindow(new BC_Title(x, y, "Y Offset:"));
244 //      x += 70;
245 //      add_subwindow(offsets[3] = new ScaleOffsetText(x, y, thread, &(thread->offsets[3])));
247         x = 10;
248         y += 30;
249         add_subwindow(new BC_Title(x, y, _("Aspect ratio:")));
250         x += 100;
251         char string[1024];
252         sprintf(string, "%.0f", thread->aspect_w);
253         add_subwindow(aspect_w = new ScaleAspectW(x, y, thread, &(thread->aspect_w), string));
254         x += 55;
255         add_subwindow(new BC_Title(x, y, _(":")));
256         x += 10;
257         sprintf(string, "%.0f", thread->aspect_h);
258         add_subwindow(aspect_h = new ScaleAspectH(x, y, thread, &(thread->aspect_h), string));
259         x += 60;
260         add_subwindow(new ScaleAspectAuto(x, y + 5, thread));
262         y += 30;
263 //      x = 40;
264 //      add_subwindow(new BC_Title(x, y, _("Camera position:")));
265 //      x += 200;
266 //      add_subwindow(new BC_Title(x, y, _("Projector position:")));
268 //      ScalePosition *position;
269 //      x = 60;
270 //      y += 25;
271 //      add_subwindow(position1 = new ScalePosition(x, y, thread, this, 
272 //              &(thread->orig_dimension[0]), &(thread->dimension[0]), &(thread->offsets[0])));
273 //      position1->draw();
275 //      x += 200;
276 //      add_subwindow(position2 = new ScalePosition(x, y, thread, this, 
277 //              &(thread->orig_dimension[2]), &(thread->dimension[2]), &(thread->offsets[2])));
278 //      position2->draw();
280 //      y += 110;
281         x = 10;
282         add_subwindow(new ScaleConstrain(x, y, thread));        
283         x += 200;
284         add_subwindow(new ScaleData(x, y, thread));     
286         y += 30;
287         x = 50;
288         add_subwindow(new BC_OKButton(x, y));
289         x += 200;
290         add_subwindow(new BC_CancelButton(x, y));
293 ScaleSizeText::ScaleSizeText(int x, int y, ScaleThread *thread, int *output)
294  : BC_TextBox(x, y, 100, 1, *output)
296         this->thread = thread; 
297         this->output = output; 
299 ScaleSizeText::~ScaleSizeText() {}
300 int ScaleSizeText::handle_event()
302         *output = atol(get_text());
303         *output /= 2;
304         *output *= 2;
305         if(*output <= 0) *output = 2;
306         if(*output > 10000) *output = 10000;
307         *output *= -1;
308         thread->update_window();
311 ScaleOffsetText::ScaleOffsetText(int x, int y, ScaleThread *thread, int *output)
312  : BC_TextBox(x, y, 100, 1, *output)
313 { this->thread = thread; this->output = output; }
314 ScaleOffsetText::~ScaleOffsetText() {}
315 int ScaleOffsetText::handle_event()
317         *output = atol(get_text());
318         //if(*output <= 0) *output = 0;
319         if(*output > 10000) *output = 10000;
320         if(*output < -10000) *output = -10000;
321         thread->update_window(1);
324 ScaleRatioText::ScaleRatioText(int x, int y, ScaleThread *thread, float *output)
325  : BC_TextBox(x, y, 100, 1, *output)
326 { this->thread = thread; this->output = output; }
327 ScaleRatioText::~ScaleRatioText() {}
328 int ScaleRatioText::handle_event()
330         *output = atof(get_text());
331         //if(*output <= 0) *output = 1;
332         if(*output > 10000) *output = 10000;
333         if(*output < -10000) *output = -10000;
334         *output *= -1;
335         thread->update_window();
341 ScaleConstrain::ScaleConstrain(int x, int y, ScaleThread *thread)
342  : BC_CheckBox(x, y, thread->constrain_ratio, _("Constrain ratio"))
343 { this->thread = thread; }
344 ScaleConstrain::~ScaleConstrain() {}
345 int ScaleConstrain::handle_event()
347         thread->constrain_ratio = get_value();
350 ScaleData::ScaleData(int x, int y, ScaleThread *thread)
351  : BC_CheckBox(x, y, thread->scale_data, _("Scale data"))
352 { this->thread = thread; }
353 ScaleData::~ScaleData() {}
354 int ScaleData::handle_event()
356         thread->scale_data = get_value();
357         thread->update_window();
361 ScaleAspectAuto::ScaleAspectAuto(int x, int y, ScaleThread *thread)
362  : BC_CheckBox(x, y, thread->auto_aspect, _("Auto"))
363 { this->thread = thread; }
365 ScaleAspectAuto::~ScaleAspectAuto()
369 int ScaleAspectAuto::handle_event()
371         thread->auto_aspect = get_value();
372         thread->update_aspect(thread->window);
378 ScaleAspectW::ScaleAspectW(int x, int y, ScaleThread *thread, float *output, char *string)
379  : BC_TextBox(x, y, 50, 1, string)
381         this->output = output;
382         this->thread = thread;
384 ScaleAspectW::~ScaleAspectW()
388 int ScaleAspectW::handle_event()
390         *output = atof(get_text());
394 ScaleAspectH::ScaleAspectH(int x, int y, ScaleThread *thread, float *output, char *string)
395  : BC_TextBox(x, y, 50, 1, string)
397         this->output = output;
398         this->thread = thread;
400 ScaleAspectH::~ScaleAspectH()
404 int ScaleAspectH::handle_event()
406         *output = atof(get_text());