00001 #include "clip.h"
00002 #include "filexml.h"
00003 #include "maskauto.h"
00004 #include "maskautos.h"
00005
00006 #include <stdlib.h>
00007 #include <string.h>
00008
00009
00010
00011
00012 MaskPoint::MaskPoint()
00013 {
00014 x = 0;
00015 y = 0;
00016 control_x1 = 0;
00017 control_y1 = 0;
00018 control_x2 = 0;
00019 control_y2 = 0;
00020 }
00021
00022 MaskPoint& MaskPoint::operator=(MaskPoint& ptr)
00023 {
00024 this->x = ptr.x;
00025 this->y = ptr.y;
00026 this->control_x1 = ptr.control_x1;
00027 this->control_y1 = ptr.control_y1;
00028 this->control_x2 = ptr.control_x2;
00029 this->control_y2 = ptr.control_y2;
00030 }
00031
00032 int MaskPoint::operator==(MaskPoint& ptr)
00033 {
00034 return EQUIV(x, ptr.x) &&
00035 EQUIV(y, ptr.y) &&
00036 EQUIV(control_x1, ptr.control_x1) &&
00037 EQUIV(control_y1, ptr.control_y1) &&
00038 EQUIV(control_x2, ptr.control_x2) &&
00039 EQUIV(control_y2, ptr.control_y2);
00040 }
00041
00042 SubMask::SubMask(MaskAuto *keyframe)
00043 {
00044 this->keyframe = keyframe;
00045 }
00046
00047 SubMask::~SubMask()
00048 {
00049 }
00050
00051 int SubMask::operator==(SubMask& ptr)
00052 {
00053 if(points.total != ptr.points.total) return 0;
00054
00055 for(int i = 0; i < points.total; i++)
00056 {
00057 if(!(*points.values[i] == *ptr.points.values[i]))
00058 return 0;
00059 }
00060
00061 return 1;
00062 }
00063
00064 void SubMask::copy_from(SubMask& ptr)
00065 {
00066 points.remove_all_objects();
00067
00068 for(int i = 0; i < ptr.points.total; i++)
00069 {
00070 MaskPoint *point = new MaskPoint;
00071 *point = *ptr.points.values[i];
00072 points.append(point);
00073 }
00074 }
00075
00076 void SubMask::load(FileXML *file)
00077 {
00078 points.remove_all_objects();
00079
00080 int result = 0;
00081 while(!result)
00082 {
00083 result = file->read_tag();
00084
00085 if(!result)
00086 {
00087 if(file->tag.title_is("/MASK"))
00088 {
00089 result = 1;
00090 }
00091 else
00092 if(file->tag.title_is("POINT"))
00093 {
00094 char string[BCTEXTLEN];
00095 string[0] = 0;
00096 file->read_text_until("/POINT", string, BCTEXTLEN);
00097
00098 MaskPoint *point = new MaskPoint;
00099 char *ptr = string;
00100
00101
00102 point->x = atof(ptr);
00103 ptr = strchr(ptr, ',');
00104
00105 if(ptr)
00106 {
00107 point->y = atof(ptr + 1);
00108 ptr = strchr(ptr + 1, ',');
00109
00110 if(ptr)
00111 {
00112
00113 point->control_x1 = atof(ptr + 1);
00114 ptr = strchr(ptr + 1, ',');
00115 if(ptr)
00116 {
00117
00118 point->control_y1 = atof(ptr + 1);
00119 ptr = strchr(ptr + 1, ',');
00120 if(ptr)
00121 {
00122
00123 point->control_x2 = atof(ptr + 1);
00124 ptr = strchr(ptr + 1, ',');
00125 if(ptr) point->control_y2 = atof(ptr + 1);
00126 }
00127 }
00128 }
00129
00130 }
00131 points.append(point);
00132 }
00133 }
00134 }
00135 }
00136
00137 void SubMask::copy(FileXML *file)
00138 {
00139 if(points.total)
00140 {
00141 file->tag.set_title("MASK");
00142 file->tag.set_property("NUMBER", keyframe->masks.number_of(this));
00143 file->append_tag();
00144 file->append_newline();
00145
00146 for(int i = 0; i < points.total; i++)
00147 {
00148 file->append_newline();
00149 file->tag.set_title("POINT");
00150 file->append_tag();
00151 char string[BCTEXTLEN];
00152
00153 sprintf(string, "%.7g, %.7g, %.7g, %.7g, %.7g, %.7g",
00154 points.values[i]->x,
00155 points.values[i]->y,
00156 points.values[i]->control_x1,
00157 points.values[i]->control_y1,
00158 points.values[i]->control_x2,
00159 points.values[i]->control_y2);
00160
00161 file->append_text(string);
00162 file->tag.set_title("/POINT");
00163 file->append_tag();
00164 }
00165 file->append_newline();
00166
00167 file->tag.set_title("/MASK");
00168 file->append_tag();
00169 file->append_newline();
00170 }
00171 }
00172
00173 void SubMask::dump()
00174 {
00175 for(int i = 0; i < points.total; i++)
00176 {
00177 printf(" point=%d x=%.2f y=%.2f in_x=%.2f in_y=%.2f out_x=%.2f out_y=%.2f\n",
00178 i,
00179 points.values[i]->x,
00180 points.values[i]->y,
00181 points.values[i]->control_x1,
00182 points.values[i]->control_y1,
00183 points.values[i]->control_x2,
00184 points.values[i]->control_y2);
00185 }
00186 }
00187
00188
00189 MaskAuto::MaskAuto(EDL *edl, MaskAutos *autos)
00190 : Auto(edl, autos)
00191 {
00192 mode = MASK_SUBTRACT_ALPHA;
00193 feather = 0;
00194 value = 100;
00195 apply_before_plugins = 0;
00196
00197
00198
00199
00200 for(int i = 0; i < SUBMASKS; i++)
00201 masks.append(new SubMask(this));
00202 }
00203
00204 MaskAuto::~MaskAuto()
00205 {
00206 masks.remove_all_objects();
00207 }
00208
00209 int MaskAuto::operator==(Auto &that)
00210 {
00211 return identical((MaskAuto*)&that);
00212 }
00213
00214
00215
00216 int MaskAuto::operator==(MaskAuto &that)
00217 {
00218 return identical((MaskAuto*)&that);
00219 }
00220
00221
00222 int MaskAuto::identical(MaskAuto *src)
00223 {
00224 if(value != src->value ||
00225 mode != src->mode ||
00226 feather != src->feather ||
00227 masks.total != src->masks.total ||
00228 apply_before_plugins != src->apply_before_plugins) return 0;
00229
00230 for(int i = 0; i < masks.total; i++)
00231 if(!(*masks.values[i] == *src->masks.values[i])) return 0;
00232
00233 return 1;
00234 }
00235
00236 void MaskAuto::copy_from(Auto *src)
00237 {
00238 copy_from((MaskAuto*)src);
00239 }
00240
00241 void MaskAuto::copy_from(MaskAuto *src)
00242 {
00243 Auto::copy_from(src);
00244
00245 mode = src->mode;
00246 feather = src->feather;
00247 value = src->value;
00248 apply_before_plugins = src->apply_before_plugins;
00249
00250 masks.remove_all_objects();
00251 for(int i = 0; i < src->masks.total; i++)
00252 {
00253 masks.append(new SubMask(this));
00254 masks.values[i]->copy_from(*src->masks.values[i]);
00255 }
00256 }
00257
00258
00259 int MaskAuto::interpolate_from(Auto *a1, Auto *a2, int64_t position) {
00260 MaskAuto *mask_auto1 = (MaskAuto *)a1;
00261 MaskAuto *mask_auto2 = (MaskAuto *)a2;
00262
00263 if (!mask_auto2 || mask_auto2->masks.total == 0)
00264 {
00265 copy_from(mask_auto1);
00266 return 0;
00267 }
00268 this->mode = mask_auto1->mode;
00269 this->feather = mask_auto1->feather;
00270 this->value = mask_auto1->value;
00271 this->apply_before_plugins = mask_auto1->apply_before_plugins;
00272 this->position = position;
00273 masks.remove_all_objects();
00274
00275 for(int i = 0;
00276 i < mask_auto1->masks.total;
00277 i++)
00278 {
00279 SubMask *new_submask = new SubMask(this);
00280 masks.append(new_submask);
00281 SubMask *mask1 = mask_auto1->masks.values[i];
00282 SubMask *mask2 = mask_auto2->masks.values[i];
00283
00284
00285 int total_points = MIN(mask1->points.total, mask2->points.total);
00286 for(int j = 0; j < total_points; j++)
00287 {
00288 MaskPoint *point = new MaskPoint;
00289 MaskAutos::avg_points(point,
00290 mask1->points.values[j],
00291 mask2->points.values[j],
00292 position,
00293 mask_auto1->position,
00294 mask_auto2->position);
00295 new_submask->points.append(point);
00296 }
00297
00298 }
00299
00300
00301 }
00302
00303
00304 SubMask* MaskAuto::get_submask(int number)
00305 {
00306 CLAMP(number, 0, masks.total - 1);
00307 return masks.values[number];
00308 }
00309
00310 void MaskAuto::load(FileXML *file)
00311 {
00312 mode = file->tag.get_property("MODE", mode);
00313 feather = file->tag.get_property("FEATHER", feather);
00314 value = file->tag.get_property("VALUE", value);
00315 apply_before_plugins = file->tag.get_property("APPLY_BEFORE_PLUGINS", apply_before_plugins);
00316 for(int i = 0; i < masks.total; i++)
00317 {
00318 delete masks.values[i];
00319 masks.values[i] = new SubMask(this);
00320 }
00321
00322 int result = 0;
00323 while(!result)
00324 {
00325 result = file->read_tag();
00326
00327 if(!result)
00328 {
00329 if(file->tag.title_is("/AUTO"))
00330 result = 1;
00331 else
00332 if(file->tag.title_is("MASK"))
00333 {
00334 SubMask *mask = masks.values[file->tag.get_property("NUMBER", 0)];
00335 mask->load(file);
00336 }
00337 }
00338 }
00339
00340 }
00341
00342 void MaskAuto::copy(int64_t start, int64_t end, FileXML *file, int default_auto)
00343 {
00344 file->tag.set_title("AUTO");
00345 file->tag.set_property("MODE", mode);
00346 file->tag.set_property("VALUE", value);
00347 file->tag.set_property("FEATHER", feather);
00348 file->tag.set_property("APPLY_BEFORE_PLUGINS", apply_before_plugins);
00349
00350 if(default_auto)
00351 file->tag.set_property("POSITION", 0);
00352 else
00353 file->tag.set_property("POSITION", position - start);
00354 file->append_tag();
00355 file->append_newline();
00356
00357 for(int i = 0; i < masks.total; i++)
00358 {
00359
00360 masks.values[i]->copy(file);
00361
00362 }
00363
00364 file->append_newline();
00365 file->tag.set_title("/AUTO");
00366 file->append_tag();
00367 file->append_newline();
00368 }
00369
00370 void MaskAuto::dump()
00371 {
00372 printf(" mode=%d value=%d\n", mode, value);
00373 for(int i = 0; i < masks.total; i++)
00374 {
00375 printf(" submask %d\n", i);
00376 masks.values[i]->dump();
00377 }
00378 }
00379
00380 void MaskAuto::translate_submasks(float translate_x, float translate_y)
00381 {
00382 for(int i = 0; i < masks.total; i++)
00383 {
00384 SubMask *mask = get_submask(i);
00385 for (int j = 0; j < mask->points.total; j++)
00386 {
00387 mask->points.values[j]->x += translate_x;
00388 mask->points.values[j]->y += translate_y;
00389 }
00390 }
00391 }
00392
00393
00394