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 "maskautos.h"
33 MaskPoint::MaskPoint()
43 void MaskPoint::copy_from(MaskPoint &ptr)
47 this->control_x1 = ptr.control_x1;
48 this->control_y1 = ptr.control_y1;
49 this->control_x2 = ptr.control_x2;
50 this->control_y2 = ptr.control_y2;
53 MaskPoint& MaskPoint::operator=(MaskPoint& ptr)
59 int MaskPoint::operator==(MaskPoint& ptr)
61 return EQUIV(x, ptr.x) &&
63 EQUIV(control_x1, ptr.control_x1) &&
64 EQUIV(control_y1, ptr.control_y1) &&
65 EQUIV(control_x2, ptr.control_x2) &&
66 EQUIV(control_y2, ptr.control_y2);
69 SubMask::SubMask(MaskAuto *keyframe)
71 this->keyframe = keyframe;
78 int SubMask::equivalent(SubMask& ptr)
80 if(points.size() != ptr.points.size()) return 0;
82 for(int i = 0; i < points.size(); i++)
84 if(!(*points.get(i) == *ptr.points.get(i)))
92 int SubMask::operator==(SubMask& ptr)
94 return equivalent(ptr);
97 void SubMask::copy_from(SubMask& ptr)
99 points.remove_all_objects();
100 //printf("SubMask::copy_from 1 %p %d\n", this, ptr.points.total);
101 for(int i = 0; i < ptr.points.total; i++)
103 MaskPoint *point = new MaskPoint;
104 *point = *ptr.points.values[i];
105 points.append(point);
109 void SubMask::load(FileXML *file)
111 points.remove_all_objects();
116 result = file->read_tag();
120 if(file->tag.title_is("/MASK"))
125 if(file->tag.title_is("POINT"))
127 char string[BCTEXTLEN];
129 file->read_text_until("/POINT", string, BCTEXTLEN);
131 MaskPoint *point = new MaskPoint;
133 //printf("MaskAuto::load 1 %s\n", ptr);
135 point->x = atof(ptr);
136 ptr = strchr(ptr, ',');
137 //printf("MaskAuto::load 2 %s\n", ptr + 1);
140 point->y = atof(ptr + 1);
141 ptr = strchr(ptr + 1, ',');
145 //printf("MaskAuto::load 3 %s\n", ptr + 1);
146 point->control_x1 = atof(ptr + 1);
147 ptr = strchr(ptr + 1, ',');
150 //printf("MaskAuto::load 4 %s\n", ptr + 1);
151 point->control_y1 = atof(ptr + 1);
152 ptr = strchr(ptr + 1, ',');
155 //printf("MaskAuto::load 5 %s\n", ptr + 1);
156 point->control_x2 = atof(ptr + 1);
157 ptr = strchr(ptr + 1, ',');
158 if(ptr) point->control_y2 = atof(ptr + 1);
164 points.append(point);
170 void SubMask::copy(FileXML *file)
174 file->tag.set_title("MASK");
175 file->tag.set_property("NUMBER", keyframe->masks.number_of(this));
177 file->append_newline();
179 for(int i = 0; i < points.total; i++)
181 file->append_newline();
182 file->tag.set_title("POINT");
184 char string[BCTEXTLEN];
185 //printf("SubMask::copy 1 %p %d %p\n", this, i, points.values[i]);
186 sprintf(string, "%.6e, %.6e, %.6e, %.6e, %.6e, %.6e",
189 points.values[i]->control_x1,
190 points.values[i]->control_y1,
191 points.values[i]->control_x2,
192 points.values[i]->control_y2);
193 //printf("SubMask::copy 2\n");
194 file->append_text(string);
195 file->tag.set_title("/POINT");
198 file->append_newline();
200 file->tag.set_title("/MASK");
202 file->append_newline();
208 for(int i = 0; i < points.total; i++)
210 printf(" point=%d x=%.2f y=%.2f in_x=%.2f in_y=%.2f out_x=%.2f out_y=%.2f\n",
214 points.values[i]->control_x1,
215 points.values[i]->control_y1,
216 points.values[i]->control_x2,
217 points.values[i]->control_y2);
222 MaskAuto::MaskAuto(EDL *edl, MaskAutos *autos)
225 mode = MASK_SUBTRACT_ALPHA;
229 // We define a fixed number of submasks so that interpolation for each
232 for(int i = 0; i < SUBMASKS; i++)
233 masks.append(new SubMask(this));
236 MaskAuto::~MaskAuto()
238 masks.remove_all_objects();
241 int MaskAuto::operator==(Auto &that)
243 return identical((MaskAuto*)&that);
248 int MaskAuto::operator==(MaskAuto &that)
250 return identical((MaskAuto*)&that);
254 int MaskAuto::identical(MaskAuto *src)
256 if(value != src->value ||
258 feather != src->feather ||
259 masks.size() != src->masks.size()) return 0;
261 for(int i = 0; i < masks.size(); i++)
262 if(!(*masks.values[i] == *src->masks.values[i])) return 0;
267 void MaskAuto::update_parameter(MaskAuto *ref, MaskAuto *src)
269 if(src->value != ref->value)
271 this->value = src->value;
274 if(src->mode != ref->mode)
276 this->mode = src->mode;
279 if(!EQUIV(src->feather, ref->feather))
281 this->feather = src->feather;
284 for(int i = 0; i < masks.size(); i++)
286 if(!src->get_submask(i)->equivalent(*ref->get_submask(i)))
287 this->get_submask(i)->copy_from(*src->get_submask(i));
291 void MaskAuto::copy_from(Auto *src)
293 copy_from((MaskAuto*)src);
296 void MaskAuto::copy_from(MaskAuto *src)
298 Auto::copy_from(src);
302 void MaskAuto::copy_data(MaskAuto *src)
305 feather = src->feather;
308 masks.remove_all_objects();
309 for(int i = 0; i < src->masks.size(); i++)
311 masks.append(new SubMask(this));
312 masks.values[i]->copy_from(*src->masks.values[i]);
317 SubMask* MaskAuto::get_submask(int number)
319 CLAMP(number, 0, masks.size() - 1);
320 return masks.values[number];
323 void MaskAuto::get_points(ArrayList<MaskPoint*> *points,
326 points->remove_all_objects();
327 SubMask *submask_ptr = get_submask(submask);
328 for(int i = 0; i < submask_ptr->points.size(); i++)
330 MaskPoint *point = new MaskPoint;
331 point->copy_from(*submask_ptr->points.get(i));
332 points->append(point);
336 void MaskAuto::set_points(ArrayList<MaskPoint*> *points,
339 SubMask *submask_ptr = get_submask(submask);
340 submask_ptr->points.remove_all_objects();
341 for(int i = 0; i < points->size(); i++)
343 MaskPoint *point = new MaskPoint;
344 point->copy_from(*points->get(i));
345 submask_ptr->points.append(point);
350 void MaskAuto::load(FileXML *file)
352 mode = file->tag.get_property("MODE", mode);
353 feather = file->tag.get_property("FEATHER", feather);
354 value = file->tag.get_property("VALUE", value);
355 for(int i = 0; i < masks.size(); i++)
357 delete masks.values[i];
358 masks.values[i] = new SubMask(this);
364 result = file->read_tag();
368 if(file->tag.title_is("/AUTO"))
371 if(file->tag.title_is("MASK"))
373 SubMask *mask = masks.values[file->tag.get_property("NUMBER", 0)];
381 void MaskAuto::copy(int64_t start, int64_t end, FileXML *file, int default_auto)
383 file->tag.set_title("AUTO");
384 file->tag.set_property("MODE", mode);
385 file->tag.set_property("VALUE", value);
386 file->tag.set_property("FEATHER", feather);
388 file->tag.set_property("POSITION", 0);
390 file->tag.set_property("POSITION", position - start);
392 file->append_newline();
394 for(int i = 0; i < masks.size(); i++)
396 //printf("MaskAuto::copy 1 %p %d %p\n", this, i, masks.values[i]);
397 masks.values[i]->copy(file);
398 //printf("MaskAuto::copy 10\n");
401 file->append_newline();
402 file->tag.set_title("/AUTO");
404 file->append_newline();
407 void MaskAuto::dump()
409 printf(" mode=%d value=%d\n", mode, value);
410 for(int i = 0; i < masks.size(); i++)
412 printf(" submask %d\n", i);
413 masks.values[i]->dump();
417 void MaskAuto::translate_submasks(float translate_x, float translate_y)
419 for(int i = 0; i < masks.size(); i++)
421 SubMask *mask = get_submask(i);
422 for (int j = 0; j < mask->points.total; j++)
424 mask->points.values[j]->x += translate_x;
425 mask->points.values[j]->y += translate_y;