28 #include "../include/KeyFrame.h" 36 void Keyframe::ReorderPoints() {
38 for (int64_t x = 0; x < Points.size(); x++) {
39 int64_t compare_index = x;
40 int64_t smallest_index = x;
42 for (int64_t compare_index = x + 1; compare_index < Points.size(); compare_index++) {
43 if (Points[compare_index].co.X < Points[smallest_index].co.X) {
44 smallest_index = compare_index;
49 if (smallest_index != compare_index) {
50 swap(Points[compare_index], Points[smallest_index]);
56 Keyframe::Keyframe(
double value) : needs_update(true) {
58 CreateFactorialTable();
67 CreateFactorialTable();
78 if (closest.
co.
X == p.
co.
X)
103 Point new_point(x, y, interpolate);
112 for (int64_t x = 0; x <
Points.size(); x++) {
117 if (p.
co.
X == existing_point.
co.
X && p.
co.
Y == existing_point.
co.
Y) {
130 for (int64_t x = 0; x <
Points.size(); x++) {
135 if (p.
co.
X == existing_point.
co.
X) {
147 Point closest(-1, -1);
150 for (int64_t x = 0; x <
Points.size(); x++) {
155 if (existing_point.
co.
X >= p.
co.
X && !useLeft) {
157 closest = existing_point;
159 }
else if (existing_point.
co.
X < p.
co.
X && useLeft) {
161 closest = existing_point;
162 }
else if (existing_point.
co.
X >= p.
co.
X && useLeft) {
169 if (closest.
co.
X == -1) {
173 else if (
Points.size() > 0)
202 return Point(-1, -1);
208 Point maxPoint(-1, -1);
211 for (int64_t x = 0; x <
Points.size(); x++) {
216 if (existing_point.
co.
Y >= maxPoint.
co.
Y) {
218 maxPoint = existing_point;
233 if (index >= 0 && index <
Values.size())
236 else if (index < 0 &&
Values.size() > 0)
255 if (index >= 0 && index <
Values.size())
257 return int(round(
Values[index].Y));
258 else if (index < 0 &&
Values.size() > 0)
260 return int(round(
Values[0].Y));
277 if (index >= 0 && index <
Values.size())
279 return long(round(
Values[index].Y));
280 else if (index < 0 &&
Values.size() > 0)
282 return long(round(
Values[0].Y));
299 if (index >= 0 && index <
Values.size())
302 else if (index < 0 &&
Values.size() > 0)
307 return long(round(
Values[
Values.size() - 1].IsIncreasing()));
325 root[
"Points"] = Json::Value(Json::arrayValue);
328 for (
int x = 0; x <
Points.size(); x++) {
331 root[
"Points"].append(existing_point.
JsonValue());
344 bool success = reader.parse( value, root );
347 throw InvalidJSON(
"JSON could not be parsed (or is invalid)",
"");
357 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)",
"");
370 if (!root[
"Points"].isNull())
372 for (int64_t x = 0; x < root[
"Points"].size(); x++) {
374 Json::Value existing_point = root[
"Points"][(Json::UInt) x];
395 if (index >= 0 && index <
Values.size())
397 return Values[index].Repeat();
398 else if (index < 0 &&
Values.size() > 0)
400 return Values[0].Repeat();
417 if (index >= 0 && index <
Values.size())
419 return Values[index].Delta();
420 else if (index < 0 &&
Values.size() > 0)
434 if (index >= 0 && index <
Points.size())
464 for (int64_t x = 0; x <
Points.size(); x++) {
469 if (p.
co.
X == existing_point.
co.
X && p.
co.
Y == existing_point.
co.
Y) {
486 if (index >= 0 && index <
Points.size())
515 cout << fixed << setprecision(4);
516 for (vector<Point>::iterator it =
Points.begin(); it !=
Points.end(); it++) {
518 cout << p.
co.
X <<
"\t" << p.
co.
Y << endl;
527 cout << fixed << setprecision(4);
528 cout <<
"Frame Number (X)\tValue (Y)\tIs Increasing\tRepeat Numerator\tRepeat Denominator\tDelta (Y Difference)" << endl;
530 for (vector<Coordinate>::iterator it =
Values.begin() + 1; it !=
Values.end(); it++) {
538 #pragma omp critical (keyframe_process) 541 if (needs_update &&
Points.size() == 0) {
545 else if (needs_update &&
Points.size() > 0)
554 for (int64_t x = 0; x < p1.
co.
X; x++)
563 for (int64_t x = 0; x <
Points.size() - 1; x++) {
568 ProcessSegment(x, p1, p2);
573 bool increasing =
true;
574 int repeat_count = 1;
575 int64_t last_value = 0;
576 for (vector<Coordinate>::iterator it =
Values.begin() + 1; it !=
Values.end(); it++) {
577 int current_value = long(round((*it).Y));
578 int64_t next_value = long(round((*it).Y));
579 int64_t prev_value = long(round((*it).Y));
580 if (it + 1 !=
Values.end())
581 next_value =
long(round((*(it + 1)).Y));
582 if (it - 1 >=
Values.begin())
583 prev_value =
long(round((*(it - 1)).Y));
586 for (vector<Coordinate>::iterator direction_it = it + 1; direction_it !=
Values.end(); direction_it++) {
587 int64_t next = long(round((*direction_it).Y));
590 if (current_value < next)
595 else if (current_value > next)
603 (*it).IsIncreasing(increasing);
606 if (current_value == last_value)
614 int additional_repeats = 0;
615 for (vector<Coordinate>::iterator repeat_it = it + 1; repeat_it !=
Values.end(); repeat_it++) {
616 int64_t next = long(round((*repeat_it).Y));
617 if (next == current_value)
619 additional_repeats++;
625 (*it).Repeat(
Fraction(repeat_count, repeat_count + additional_repeats));
628 (*it).Delta(current_value - last_value);
631 last_value = current_value;
636 needs_update =
false;
640 void Keyframe::ProcessSegment(
int Segment,
Point p1,
Point p2) {
642 int64_t number_of_values = round(p2.
co.
X) - round(p1.
co.
X);
645 if (number_of_values == 0)
656 double current_value = p1.
co.
Y;
657 double value_difference = p2.
co.
Y - p1.
co.
Y;
658 double value_increment = 0.0f;
662 value_increment = value_difference / (double) (number_of_values);
669 current_value += value_increment;
672 for (int64_t x = 0; x < number_of_values; x++) {
677 current_value += value_increment;
690 number_of_values *= 4;
693 double X_diff = p2.
co.
X - p1.
co.
X;
694 double Y_diff = p2.
co.
Y - p1.
co.
Y;
696 vector<Coordinate> segment_coordinates;
697 segment_coordinates.push_back(p1.
co);
700 segment_coordinates.push_back(p2.
co);
702 vector<Coordinate> raw_coordinates;
703 int64_t npts = segment_coordinates.size();
704 int64_t icount, jcount;
712 step = (double) 1.0 / (number_of_values - 1);
714 for (int64_t i1 = 0; i1 < number_of_values; i1++) {
715 if ((1.0 - t) < 5
e-6)
723 for (int64_t i = 0; i < npts; i++) {
725 double basis = Bernstein(npts - 1, i, t);
726 new_x += basis * co.
X;
727 new_y += basis * co.
Y;
734 raw_coordinates.push_back(current_value);
743 int64_t current_frame = p1.
co.
X;
744 double current_value = p1.
co.
Y;
745 for (int64_t i = 0; i < raw_coordinates.size(); i++)
750 if (current_frame == round(raw.
X))
752 current_value = raw.
Y;
756 int64_t number_of_missing = round(raw.
X) - current_frame;
757 for (int64_t missing = 0; missing < number_of_missing; missing++)
760 Coordinate new_coord(current_frame, current_value);
762 if (Segment == 0 || Segment > 0 && current_frame > p1.
co.
X)
764 Values.push_back(new_coord);
771 current_value = raw.
Y;
776 Coordinate new_coord(current_frame, current_value);
777 Values.push_back(new_coord);
792 for (int64_t x = 0; x < number_of_values; x++) {
793 if (x < (number_of_values - 1)) {
810 void Keyframe::CreateFactorialTable() {
812 FactorialLookup[0] = 1.0;
813 FactorialLookup[1] = 1.0;
814 FactorialLookup[2] = 2.0;
815 FactorialLookup[3] = 6.0;
819 double Keyframe::Factorial(int64_t n) {
820 assert(n >= 0 && n <= 3);
821 return FactorialLookup[n];
825 double Keyframe::Ni(int64_t n, int64_t i) {
827 double a1 = Factorial(n);
828 double a2 = Factorial(i);
829 double a3 = Factorial(n - i);
835 double Keyframe::Bernstein(int64_t n, int64_t i,
double t) {
841 if (t == 0.0 && i == 0)
846 if (n == i && t == 1.0)
849 tni = pow((1 - t), (n - i));
852 basis = Ni(n, i) * ti * tni;
861 for (int64_t point_index = 0; point_index <
Points.size(); point_index++) {
863 if (point_index == 0)
867 Points[point_index].co.X = round(
Points[point_index].co.X * scale);
878 vector<Point> FlippedPoints;
879 for (int64_t point_index = 0, reverse_index =
Points.size() - 1; point_index <
Points.size(); point_index++, reverse_index--) {
883 FlippedPoints.push_back(p);
887 Points.swap(FlippedPoints);
vector< Coordinate > Values
Vector of all Values (i.e. the processed coordinates from the curve)
Point GetMaxPoint()
Get max point (by Y coordinate)
Json::Value JsonValue()
Generate Json::JsonValue for this object.
This class represents a Cartesian coordinate (X, Y) used in the Keyframe animation system...
int64_t GetCount()
Get the number of points (i.e. # of points)
Keyframe()
Default constructor for the Keyframe class.
void FlipPoints()
Flip all the points in this openshot::Keyframe (useful for reversing an effect or transition...
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Bezier curves are quadratic curves, which create a smooth curve.
Point & GetPoint(int64_t index)
Get a point at a specific index.
InterpolationType interpolation
This is the interpolation mode.
Coordinate handle_right
This is the right handle coordinate (in percentages from 0 to 1)
bool Contains(Point p)
Does this keyframe contain a specific point.
Coordinate handle_left
This is the left handle coordinate (in percentages from 0 to 1)
void ScalePoints(double scale)
A Point is the basic building block of a key-frame curve.
Point GetPreviousPoint(Point p)
Get previous point (.
void UpdatePoint(int64_t index, Point p)
Replace an existing point with a new point.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
void AddPoint(Point p)
Add a new point on the key-frame. Each point has a primary coordinate, a left handle, and a right handle.
void IsIncreasing(bool is_increasing)
Set the increasing flag (used internally on the timeline, to track changes to coordinates) ...
double Y
The Y value of the coordinate (usually representing the value of the property being animated) ...
void PrintValues()
Print just the Y value of the point's primary coordinate.
void Repeat(Fraction is_repeated)
Set the repeating Fraction (used internally on the timeline, to track changes to coordinates) ...
void RemovePoint(Point p)
Remove a point by matching a coordinate.
bool IsIncreasing(int index)
Get the direction of the curve at a specific index (increasing or decreasing)
This class represents a fraction.
int GetInt(int64_t index)
Get the rounded INT value at a specific index.
int64_t FindIndex(Point p)
Get the index of a point by matching a coordinate.
void Process()
Calculate all of the values for this keyframe.
Fraction GetRepeatFraction(int64_t index)
Get the fraction that represents how many times this value is repeated in the curve.
vector< Point > Points
Vector of all Points.
double X
The X value of the coordinate (usually representing the frame #)
double GetDelta(int64_t index)
Get the change in Y value (from the previous Y value)
Point GetClosestPoint(Point p)
Get current point (or closest point to the right) from the X coordinate (i.e. the frame number) ...
InterpolationType
This controls how a Keyframe uses this point to interpolate between two points.
double GetValue(int64_t index)
Get the value at a specific index.
This namespace is the default namespace for all code in the openshot library.
void Delta(double new_delta)
Set the delta / difference between previous coordinate value (used internally on the timeline...
string Json()
Get and Set JSON methods.
Linear curves are angular, straight lines between two points.
Coordinate co
This is the primary coordinate.
Exception for invalid JSON.
int64_t GetLong(int64_t index)
Get the rounded LONG value at a specific index.
Exception for an out of bounds key-frame point.
void PrintPoints()
Print a list of points.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
void SetJson(string value)
Load JSON string into this object.
Constant curves jump from their previous position to a new one (with no interpolation).