28 #include "../include/KeyFrame.h" 36 void Keyframe::ReorderPoints() {
38 for (
long int x = 0; x < Points.size(); x++) {
39 long int compare_index = x;
40 long int smallest_index = x;
42 for (
long int 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(
float value) : Auto_Handle_Percentage(0.4f), needs_update(true) {
58 CreateFactorialTable();
67 CreateFactorialTable();
78 if (closest.
co.
X == p.
co.
X)
106 Point new_point(x, y, interpolate);
124 Point *Previous_Point = NULL;
125 Point *Next_Point = NULL;
126 float Previous_X_diff = 0.0f;
127 float Next_X_diff = 0.0f;
131 Previous_Point = &
Points[index - 1];
134 if (index < (
Points.size() - 1))
135 Next_Point = &
Points[index + 1];
159 for (
long int x = 0; x <
Points.size(); x++) {
164 if (p.co.X == existing_point.
co.
X && p.co.Y == existing_point.
co.
Y) {
177 for (
long int x = 0; x <
Points.size(); x++) {
182 if (p.
co.
X == existing_point.
co.
X) {
194 Point closest(-1, -1);
197 for (
long int x = 0; x <
Points.size(); x++) {
202 if (existing_point.
co.
X >= p.
co.
X) {
204 closest = existing_point;
210 if (closest.
co.
X == -1) {
214 else if (
Points.size() > 0)
231 if (index >= 0 && index <
Values.size())
234 else if (index < 0 &&
Values.size() > 0)
253 if (index >= 0 && index <
Values.size())
255 return int(round(
Values[index].Y));
256 else if (index < 0 &&
Values.size() > 0)
258 return int(round(
Values[0].Y));
275 if (index >= 0 && index <
Values.size())
277 return long(round(
Values[index].Y));
278 else if (index < 0 &&
Values.size() > 0)
280 return long(round(
Values[0].Y));
297 if (index >= 0 && index <
Values.size())
300 else if (index < 0 &&
Values.size() > 0)
305 return long(round(
Values[
Values.size() - 1].IsIncreasing()));
323 root[
"Points"] = Json::Value(Json::arrayValue);
326 for (
int x = 0; x <
Points.size(); x++) {
329 root[
"Points"].append(existing_point.
JsonValue());
342 bool success = reader.parse( value, root );
345 throw InvalidJSON(
"JSON could not be parsed (or is invalid)",
"");
355 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)",
"");
368 if (!root[
"Points"].isNull())
370 for (
long int x = 0; x < root[
"Points"].size(); x++) {
372 Json::Value existing_point = root[
"Points"][(Json::UInt) x];
384 if (!root[
"Auto_Handle_Percentage"].isNull())
396 if (index >= 0 && index <
Values.size())
398 return Values[index].Repeat();
399 else if (index < 0 &&
Values.size() > 0)
401 return Values[0].Repeat();
418 if (index >= 0 && index <
Values.size())
420 return Values[index].Delta();
421 else if (index < 0 &&
Values.size() > 0)
435 if (index >= 0 && index <
Points.size())
465 for (
long int x = 0; x <
Points.size(); x++) {
470 if (p.co.X == existing_point.
co.
X && p.co.Y == existing_point.
co.
Y) {
487 if (index >= 0 && index <
Points.size())
516 cout << fixed << setprecision(4);
517 for (vector<Point>::iterator it =
Points.begin(); it !=
Points.end(); it++) {
519 cout << p.
co.
X <<
"\t" << p.
co.
Y << endl;
528 cout << fixed << setprecision(4);
529 cout <<
"Frame Number (X)\tValue (Y)\tIs Increasing\tRepeat Numerator\tRepeat Denominator\tDelta (Y Difference)" << endl;
531 for (vector<Coordinate>::iterator it =
Values.begin() + 1; it !=
Values.end(); it++) {
539 #pragma omp critical (keyframe_process) 542 if (needs_update &&
Points.size() == 0) {
546 else if (needs_update &&
Points.size() > 0)
555 for (
long int x = 0; x < p1.
co.
X; x++)
564 for (
long int x = 0; x <
Points.size() - 1; x++) {
569 ProcessSegment(x, p1, p2);
574 bool increasing =
true;
575 int repeat_count = 1;
576 long int last_value = 0;
577 for (vector<Coordinate>::iterator it =
Values.begin() + 1; it !=
Values.end(); it++) {
578 int current_value = long(round((*it).Y));
579 long int next_value = long(round((*it).Y));
580 long int prev_value = long(round((*it).Y));
581 if (it + 1 !=
Values.end())
582 next_value =
long(round((*(it + 1)).Y));
583 if (it - 1 >=
Values.begin())
584 prev_value =
long(round((*(it - 1)).Y));
587 for (vector<Coordinate>::iterator direction_it = it + 1; direction_it !=
Values.end(); direction_it++) {
588 long int next = long(round((*direction_it).Y));
591 if (current_value < next)
596 else if (current_value > next)
604 (*it).IsIncreasing(increasing);
607 if (current_value == last_value)
615 int additional_repeats = 0;
616 for (vector<Coordinate>::iterator repeat_it = it + 1; repeat_it !=
Values.end(); repeat_it++) {
617 long int next = long(round((*repeat_it).Y));
618 if (next == current_value)
620 additional_repeats++;
626 (*it).Repeat(
Fraction(repeat_count, repeat_count + additional_repeats));
629 (*it).Delta(current_value - last_value);
632 last_value = current_value;
637 needs_update =
false;
641 void Keyframe::ProcessSegment(
int Segment,
Point p1,
Point p2) {
643 long int number_of_values = round(p2.
co.
X) - round(p1.
co.
X);
646 if (number_of_values == 0)
657 float current_value = p1.
co.
Y;
658 float value_difference = p2.
co.
Y - p1.
co.
Y;
659 float value_increment = 0.0f;
663 value_increment = value_difference / (float) (number_of_values);
670 current_value += value_increment;
673 for (
long int x = 0; x < number_of_values; x++) {
678 current_value += value_increment;
691 number_of_values *= 4;
693 vector<Coordinate> segment_coordinates;
694 segment_coordinates.push_back(p1.
co);
697 segment_coordinates.push_back(p2.
co);
699 vector<Coordinate> raw_coordinates;
700 long int npts = segment_coordinates.size();
701 long int icount, jcount;
709 step = (double) 1.0 / (number_of_values - 1);
711 for (
long int i1 = 0; i1 < number_of_values; i1++) {
712 if ((1.0 - t) < 5
e-6)
720 for (
long int i = 0; i < npts; i++) {
722 double basis = Bernstein(npts - 1, i, t);
723 new_x += basis * co.
X;
724 new_y += basis * co.
Y;
731 raw_coordinates.push_back(current_value);
740 long int current_frame = p1.
co.
X;
741 float current_value = p1.
co.
Y;
742 for (
long int i = 0; i < raw_coordinates.size(); i++)
747 if (current_frame == round(raw.
X))
749 current_value = raw.
Y;
753 long int number_of_missing = round(raw.
X) - current_frame;
754 for (
long int missing = 0; missing < number_of_missing; missing++)
757 Coordinate new_coord(current_frame, current_value);
759 if (Segment == 0 || Segment > 0 && current_frame > p1.
co.
X)
761 Values.push_back(new_coord);
768 current_value = raw.
Y;
773 Coordinate new_coord(current_frame, current_value);
774 Values.push_back(new_coord);
789 for (
long int x = 0; x < number_of_values; x++) {
790 if (x < (number_of_values - 1)) {
807 void Keyframe::CreateFactorialTable() {
809 FactorialLookup[0] = 1.0;
810 FactorialLookup[1] = 1.0;
811 FactorialLookup[2] = 2.0;
812 FactorialLookup[3] = 6.0;
816 double Keyframe::Factorial(
long int n) {
817 assert(n >= 0 && n <= 3);
818 return FactorialLookup[n];
822 double Keyframe::Ni(
long int n,
long int i) {
824 double a1 = Factorial(n);
825 double a2 = Factorial(i);
826 double a3 = Factorial(n - i);
832 double Keyframe::Bernstein(
long int n,
long int i,
double t) {
838 if (t == 0.0 && i == 0)
843 if (n == i && t == 1.0)
846 tni = pow((1 - t), (n - i));
849 basis = Ni(n, i) * ti * tni;
858 for (
long int point_index = 0; point_index <
Points.size(); point_index++) {
860 if (point_index == 0)
864 Points[point_index].co.X = round(
Points[point_index].co.X * scale);
875 vector<Point> FlippedPoints;
876 for (
long int point_index = 0, reverse_index =
Points.size() - 1; point_index <
Points.size(); point_index++, reverse_index--) {
880 FlippedPoints.push_back(p);
884 Points.swap(FlippedPoints);
vector< Coordinate > Values
Vector of all Values (i.e. the processed coordinates from the curve)
Json::Value JsonValue()
Generate Json::JsonValue for this object.
This class represents a Cartesian coordinate (X, Y) used in the Keyframe animation system...
void Delta(float new_delta)
Set the delta / difference between previous coordinate value (used internally on the timeline...
float GetDelta(long int index)
Get the change in Y value (from the previous Y value)
Keyframe()
Default constructor for the Keyframe class.
void FlipPoints()
Flip all the points in this openshot::Keyframe (useful for reversing an effect or transition...
Point & GetPoint(long int index)
Get a point at a specific index.
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Bezier curves are quadratic curves, which create a smooth curve.
void AddPoint(float x, float y, InterpolationType interpolate)
Add a new point on the key-frame, with a specific interpolation type.
InterpolationType interpolation
This is the interpolation mode.
Coordinate handle_right
This is the right handle coordinate.
bool Contains(Point p)
Does this keyframe contain a specific point.
Coordinate handle_left
This is the left handle coordinate.
A Point is the basic building block of a key-frame curve.
HandleType handle_type
This is the handle mode.
void SetHandles(Point current)
Set the handles, used for smooth curves. The handles are based on the surrounding points...
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.
float GetValue(long int index)
Get the value at a specific index.
void IsIncreasing(bool is_increasing)
Set the increasing flag (used internally on the timeline, to track changes to coordinates) ...
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) ...
long int FindIndex(Point p)
Get the index of a point by matching a coordinate.
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.
void ScalePoints(float scale)
float Auto_Handle_Percentage
Percentage the left and right handles should be adjusted to, to create a smooth curve.
float X
The X value of the coordinate (usually representing the frame #)
void Process()
Calculate all of the values for this keyframe.
vector< Point > Points
Vector of all Points.
Automatically adjust the handles to achieve the smoothest curve.
Point GetClosestPoint(Point p)
Get current point (or closest point) from the X coordinate (i.e. the frame number) ...
InterpolationType
This controls how a Keyframe uses this point to interpolate between two points.
int GetInt(long int index)
Get the rounded INT value at a specific index.
This namespace is the default namespace for all code in the openshot library.
long int GetCount()
Get the number of points (i.e. # of points)
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.
void UpdatePoint(long int index, Point p)
Replace an existing point with a new point.
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.
float Y
The Y value of the coordinate (usually representing the value of the property being animated) ...
long int GetLong(long int index)
Get the rounded LONG value at a specific index.
Constant curves jump from their previous position to a new one (with no interpolation).
Fraction GetRepeatFraction(long int index)
Get the fraction that represents how many times this value is repeated in the curve.