53 double const diff_Y = right.
co.
Y - left.
co.
Y;
54 double const diff_X = right.
co.
X - left.
co.
X;
55 double const slope = diff_Y / diff_X;
56 return left.
co.
Y + slope * (target - left.
co.
X);
61 double const X_diff = right.
co.
X - left.
co.
X;
62 double const Y_diff = right.
co.
Y - left.
co.
Y;
72 double B[4] = {1, 3, 3, 1};
73 double oneMinTExp = 1;
75 for (
int i = 0; i < 4; ++i, tExp *= t) {
78 for (
int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) {
79 B[4 - i - 1] *= oneMinTExp;
81 double const x = p0.
X * B[0] + p1.
X * B[1] + p2.
X * B[2] + p3.
X * B[3];
82 double const y = p0.
Y * B[0] + p1.
Y * B[1] + p2.
Y * B[2] + p3.
Y * B[3];
83 if (fabs(target - x) < allowed_error) {
99 if(left.
co.
X > target){
102 if(target > right.
co.
X){
114 template<
typename Check>
116 int64_t start = left.
co.
X;
117 int64_t stop = right.
co.
X;
118 while (start < stop) {
119 int64_t
const mid = (start + stop + 1) / 2;
121 if (check(round(value), current)) {
131 Keyframe::Keyframe(
double value) {
133 AddPoint(
Point(value));
137 Keyframe::Keyframe(
const std::vector<openshot::Point>& points) : Points(points) {};
144 std::vector<Point>::iterator candidate =
146 if (candidate == end(Points)) {
150 }
else if ((*candidate).co.X == p.
co.
X) {
158 size_t const candidate_index = candidate - begin(Points);
160 std::move_backward(begin(Points) + candidate_index, end(Points) - 1, end(Points));
161 Points[candidate_index] = p;
169 Point new_point(x, y, interpolate);
178 for (std::vector<Point>::size_type x = 0; x < Points.size(); x++) {
180 Point existing_point = Points[x];
183 if (p.
co.
X == existing_point.
co.
X && p.
co.
Y == existing_point.
co.
Y) {
195 std::vector<Point>::const_iterator i =
197 return i != end(Points) && i->co.X == p.
co.
X;
202 if (Points.size() == 0) {
203 return Point(-1, -1);
208 std::vector<Point>::const_iterator candidate =
211 if (candidate == end(Points)) {
215 return Points.back();
217 if (candidate == begin(Points)) {
221 return Points.front();
224 return *(candidate - 1);
244 return Points[index - 1];
250 return Point(-1, -1);
256 Point maxPoint(-1, -1);
258 for (
Point const & existing_point: Points) {
259 if (existing_point.co.Y >= maxPoint.
co.
Y) {
260 maxPoint = existing_point;
269 if (Points.empty()) {
272 std::vector<Point>::const_iterator candidate =
273 std::lower_bound(begin(Points), end(Points), static_cast<double>(index),
IsPointBeforeX);
275 if (candidate == end(Points)) {
277 return Points.back().co.Y;
279 if (candidate == begin(Points)) {
281 return Points.front().co.Y;
283 if (candidate->co.X == index) {
285 return candidate->co.Y;
287 std::vector<Point>::const_iterator predecessor = candidate - 1;
298 return long(round(
GetValue(index)));
304 if (index < 1 || (index + 1) >=
GetLength()) {
307 std::vector<Point>::const_iterator candidate =
308 std::lower_bound(begin(Points), end(Points), static_cast<double>(index),
IsPointBeforeX);
309 if (candidate == end(Points)) {
312 if ((candidate->co.X == index) || (candidate == begin(Points))) {
315 int64_t
const value =
GetLong(index);
317 if (value < round(candidate->co.Y)) {
319 }
else if (value > round(candidate->co.Y)) {
323 }
while (candidate != end(Points));
339 root[
"Points"] = Json::Value(Json::arrayValue);
342 for (
const auto existing_point : Points) {
343 root[
"Points"].append(existing_point.JsonValue());
360 catch (
const std::exception& e)
363 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
372 if (!root[
"Points"].isNull())
374 for (
const auto existing_point : root[
"Points"]) {
391 if (index < 1 || (index + 1) >=
GetLength()) {
394 assert(Points.size() > 1);
398 int64_t
const current_value =
GetLong(index);
399 std::vector<Point>::const_iterator
const candidate =
400 std::lower_bound(begin(Points), end(Points), static_cast<double>(index),
IsPointBeforeX);
401 assert(candidate != end(Points));
404 int64_t next_repeats = 0;
405 std::vector<Point>::const_iterator i = candidate;
410 if (i->co.X == index) {
414 bool all_constant =
true;
415 for (; i != end(Points); ++i) {
416 if (current_value != round(i->co.Y)) {
417 all_constant =
false;
421 if (! all_constant) {
426 assert(i != begin(Points));
427 Point const left = *(i - 1);
428 Point const right = *i;
430 if (current_value < round(i->co.Y)) {
433 assert(current_value > round(i->co.Y));
436 next_repeats = change_at - index;
439 next_repeats = Points.back().co.X - index;
445 if (i != begin(Points)) {
453 int64_t previous_repeats = 0;
455 for (; i != begin(Points); --i) {
456 if (current_value != round(i->co.Y)) {
457 all_constant =
false;
464 if (current_value != round(i->co.Y)) {
465 assert(i != candidate);
466 all_constant =
false;
468 if (! all_constant) {
471 Point const left = *i;
472 Point const right = *(i + 1);
474 if (current_value > round(left.
co.
Y)) {
477 assert(current_value < round(left.
co.
Y));
480 previous_repeats = index - change_at;
484 previous_repeats = index;
486 int64_t total_repeats = previous_repeats + next_repeats;
487 return Fraction(previous_repeats, total_repeats);
492 if (index < 1)
return 0;
493 if (index == 1 && ! Points.empty())
return Points[0].co.Y;
501 if (index >= 0 && index < (int64_t)Points.size())
502 return Points[index];
510 if (Points.empty())
return 0;
511 if (Points.size() == 1)
return 1;
512 return round(Points.back().co.X) + 1;
518 return Points.size();
524 for (std::vector<Point>::size_type x = 0; x < Points.size(); x++) {
526 Point existing_point = Points[x];
529 if (p.
co.
X == existing_point.
co.
X && p.
co.
Y == existing_point.
co.
Y) {
531 Points.erase(Points.begin() + x);
543 if (index >= 0 && index < (int64_t)Points.size())
546 Points.erase(Points.begin() + index);
563 cout << fixed << setprecision(4);
564 for (std::vector<Point>::const_iterator it = Points.begin(); it != Points.end(); it++) {
566 cout << p.
co.
X <<
"\t" << p.
co.
Y << endl;
571 cout << fixed << setprecision(4);
572 cout <<
"Frame Number (X)\tValue (Y)\tIs Increasing\tRepeat Numerator\tRepeat Denominator\tDelta (Y Difference)\n";
574 for (int64_t i = 1; i <
GetLength(); ++i) {
590 for (std::vector<Point>::size_type point_index = 1; point_index < Points.size(); point_index++) {
592 Points[point_index].co.X = round(Points[point_index].co.X * scale);
598 for (std::vector<Point>::size_type point_index = 0, reverse_index = Points.size() - 1; point_index < reverse_index; point_index++, reverse_index--) {
601 swap(Points[point_index].co.Y, Points[reverse_index].co.Y);
double GetDelta(int64_t index) const
Get the change in Y value (from the previous Y value)
This class represents a Cartesian coordinate (X, Y) used in the Keyframe animation system...
int num
Numerator for the fraction.
Point GetMaxPoint() const
Get max point (by Y coordinate)
void FlipPoints()
Flip all the points in this openshot::Keyframe (useful for reversing an effect or transition...
Point const & GetPoint(int64_t index) const
Get a point at a specific index.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
int64_t GetLong(int64_t index) const
Get the rounded LONG value at a specific index.
Bezier curves are quadratic curves, which create a smooth curve.
InterpolationType interpolation
This is the interpolation mode.
Coordinate handle_right
This is the right handle coordinate (in percentages from 0 to 1)
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) const
Get previous point (.
const Json::Value stringToJson(const std::string value)
bool IsIncreasing(int index) const
Get the direction of the curve at a specific index (increasing or decreasing)
Header file for the Keyframe class.
bool Contains(Point p) const
Does this keyframe contain a specific point.
double InterpolateBezierCurve(Point const &left, Point const &right, double const target, double const allowed_error)
Bezier interpolation between two points.
void UpdatePoint(int64_t index, Point p)
Replace an existing point with a new point.
int GetInt(int64_t index) const
Get the rounded INT value at a specific index.
double InterpolateLinearCurve(Point const &left, Point const &right, double const target)
Linear interpolation between two points.
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.
Header file for all Exception classes.
double Y
The Y value of the coordinate (usually representing the value of the property being animated) ...
Point GetClosestPoint(Point p) const
Get current point (or closest point to the right) from the X coordinate (i.e. the frame number) ...
void PrintPoints() const
Print a list of points.
void RemovePoint(Point p)
Remove a point by matching a coordinate.
This class represents a fraction.
double InterpolateBetween(Point const &left, Point const &right, double target, double allowed_error)
Interpolate two points using the right Point's interpolation method.
double X
The X value of the coordinate (usually representing the frame #)
void PrintValues() const
Print just the Y value of the point's primary coordinate.
int64_t SearchBetweenPoints(Point const &left, Point const &right, int64_t const current, Check check)
InterpolationType
This controls how a Keyframe uses this point to interpolate between two points.
bool IsPointBeforeX(Point const &p, double const x)
Check if the X coordinate of a given Point is lower than a given value.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
This namespace is the default namespace for all code in the openshot library.
Json::Value JsonValue() const
Generate Json::Value for this object.
Linear curves are angular, straight lines between two points.
Coordinate co
This is the primary coordinate.
int64_t FindIndex(Point p) const
Get the index of a point by matching a coordinate.
Exception for invalid JSON.
int64_t GetCount() const
Get the number of points (i.e. # of points)
double GetValue(int64_t index) const
Get the value at a specific index.
Exception for an out of bounds key-frame point.
void SetJson(const std::string value)
Load JSON string into this object.
Fraction GetRepeatFraction(int64_t index) const
Get the fraction that represents how many times this value is repeated in the curve.
int den
Denominator for the fraction.
int64_t GetLength() const
Constant curves jump from their previous position to a new one (with no interpolation).
std::string Json() const
Generate JSON string of this object.