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, "%.6e, %.6e, %.6e, %.6e, %.6e, %.6e",
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
00196
00197
00198
00199 for(int i = 0; i < SUBMASKS; i++)
00200 masks.append(new SubMask(this));
00201 }
00202
00203 MaskAuto::~MaskAuto()
00204 {
00205 masks.remove_all_objects();
00206 }
00207
00208 int MaskAuto::operator==(Auto &that)
00209 {
00210 return identical((MaskAuto*)&that);
00211 }
00212
00213
00214
00215 int MaskAuto::operator==(MaskAuto &that)
00216 {
00217 return identical((MaskAuto*)&that);
00218 }
00219
00220
00221 int MaskAuto::identical(MaskAuto *src)
00222 {
00223 if(value != src->value ||
00224 mode != src->mode ||
00225 feather != src->feather ||
00226 masks.total != src->masks.total) return 0;
00227
00228 for(int i = 0; i < masks.total; i++)
00229 if(!(*masks.values[i] == *src->masks.values[i])) return 0;
00230
00231 return 1;
00232 }
00233
00234 void MaskAuto::copy_from(Auto *src)
00235 {
00236 copy_from((MaskAuto*)src);
00237 }
00238
00239 void MaskAuto::copy_from(MaskAuto *src)
00240 {
00241 Auto::copy_from(src);
00242
00243 mode = src->mode;
00244 feather = src->feather;
00245 value = src->value;
00246
00247 masks.remove_all_objects();
00248 for(int i = 0; i < src->masks.total; i++)
00249 {
00250 masks.append(new SubMask(this));
00251 masks.values[i]->copy_from(*src->masks.values[i]);
00252 }
00253 }
00254
00255
00256 int MaskAuto::interpolate_from(Auto *a1, Auto *a2, int64_t position) {
00257 MaskAuto *mask_auto1 = (MaskAuto *)a1;
00258 MaskAuto *mask_auto2 = (MaskAuto *)a2;
00259
00260 if (!mask_auto2 || mask_auto2->masks.total == 0)
00261 {
00262 copy_from(mask_auto1);
00263 return 0;
00264 }
00265 this->mode = mask_auto1->mode;
00266 this->feather = mask_auto1->feather;
00267 this->value = mask_auto1->value;
00268 this->position = position;
00269 masks.remove_all_objects();
00270
00271 for(int i = 0;
00272 i < mask_auto1->masks.total;
00273 i++)
00274 {
00275 SubMask *new_submask = new SubMask(this);
00276 masks.append(new_submask);
00277 SubMask *mask1 = mask_auto1->masks.values[i];
00278 SubMask *mask2 = mask_auto2->masks.values[i];
00279
00280
00281 int total_points = MIN(mask1->points.total, mask2->points.total);
00282 for(int j = 0; j < total_points; j++)
00283 {
00284 MaskPoint *point = new MaskPoint;
00285 MaskAutos::avg_points(point,
00286 mask1->points.values[j],
00287 mask2->points.values[j],
00288 position,
00289 mask_auto1->position,
00290 mask_auto2->position);
00291 new_submask->points.append(point);
00292 }
00293
00294 }
00295
00296
00297 }
00298
00299
00300 SubMask* MaskAuto::get_submask(int number)
00301 {
00302 CLAMP(number, 0, masks.total - 1);
00303 return masks.values[number];
00304 }
00305
00306 void MaskAuto::load(FileXML *file)
00307 {
00308 mode = file->tag.get_property("MODE", mode);
00309 feather = file->tag.get_property("FEATHER", feather);
00310 value = file->tag.get_property("VALUE", value);
00311 for(int i = 0; i < masks.total; i++)
00312 {
00313 delete masks.values[i];
00314 masks.values[i] = new SubMask(this);
00315 }
00316
00317 int result = 0;
00318 while(!result)
00319 {
00320 result = file->read_tag();
00321
00322 if(!result)
00323 {
00324 if(file->tag.title_is("/AUTO"))
00325 result = 1;
00326 else
00327 if(file->tag.title_is("MASK"))
00328 {
00329 SubMask *mask = masks.values[file->tag.get_property("NUMBER", 0)];
00330 mask->load(file);
00331 }
00332 }
00333 }
00334
00335 }
00336
00337 void MaskAuto::copy(int64_t start, int64_t end, FileXML *file, int default_auto)
00338 {
00339 file->tag.set_title("AUTO");
00340 file->tag.set_property("MODE", mode);
00341 file->tag.set_property("VALUE", value);
00342 file->tag.set_property("FEATHER", feather);
00343 if(default_auto)
00344 file->tag.set_property("POSITION", 0);
00345 else
00346 file->tag.set_property("POSITION", position - start);
00347 file->append_tag();
00348 file->append_newline();
00349
00350 for(int i = 0; i < masks.total; i++)
00351 {
00352
00353 masks.values[i]->copy(file);
00354
00355 }
00356
00357 file->append_newline();
00358 file->tag.set_title("/AUTO");
00359 file->append_tag();
00360 file->append_newline();
00361 }
00362
00363 void MaskAuto::dump()
00364 {
00365 printf(" mode=%d value=%d\n", mode, value);
00366 for(int i = 0; i < masks.total; i++)
00367 {
00368 printf(" submask %d\n", i);
00369 masks.values[i]->dump();
00370 }
00371 }
00372
00373 void MaskAuto::translate_submasks(float translate_x, float translate_y)
00374 {
00375 for(int i = 0; i < masks.total; i++)
00376 {
00377 SubMask *mask = get_submask(i);
00378 for (int j = 0; j < mask->points.total; j++)
00379 {
00380 mask->points.values[j]->x += translate_x;
00381 mask->points.values[j]->y += translate_y;
00382 }
00383 }
00384 }
00385
00386
00387