diff --git a/include/KeyFrame.h b/include/KeyFrame.h
index 5a5565a0..8a3fcfd5 100644
--- a/include/KeyFrame.h
+++ b/include/KeyFrame.h
@@ -141,6 +141,9 @@ namespace openshot {
/// Get current point (or closest point) from the X coordinate (i.e. the frame number)
Point GetClosestPoint(Point p);
+ /// Get max point (by Y coordinate)
+ Point GetMaxPoint();
+
// Get the number of values (i.e. coordinates on the X axis)
long int GetLength();
diff --git a/src/Clip.cpp b/src/Clip.cpp
index a93db20a..2ce820e9 100644
--- a/src/Clip.cpp
+++ b/src/Clip.cpp
@@ -597,13 +597,32 @@ tr1::shared_ptr Clip::GetOrCreateFrame(long int number)
// Debug output
ZmqLogger::Instance()->AppendDebugMethod("Clip::GetOrCreateFrame (from reader)", "number", number, "samples_in_frame", samples_in_frame, "", -1, "", -1, "", -1, "", -1);
- // Set max image size (used for performance optimization)
- if (scale_x.GetValue(number) > 1.000001 || scale_y.GetValue(number) > 1.000001)
- // Scaling larger, use original image size (slower but better quality)
+ // Determine the max size of this clips source image (based on the timeline's size, the scaling mode,
+ // and the scaling keyframes). This is a performance improvement, to keep the images as small as possible,
+ // without loosing quality.
+ if (scale == SCALE_FIT || scale == SCALE_STRETCH) {
+ // Best fit or Stretch scaling (based on max timeline size * scaling keyframes)
+ float max_scale_x = scale_x.GetMaxPoint().co.Y;
+ float max_scale_y = scale_y.GetMaxPoint().co.Y;
+ reader->SetMaxSize(max_width * max_scale_x, max_height * max_scale_y);
+
+ } else if (scale == SCALE_CROP) {
+ // Cropping scale mode (based on max timeline size * cropped size * scaling keyframes)
+ float max_scale_x = scale_x.GetMaxPoint().co.Y;
+ float max_scale_y = scale_y.GetMaxPoint().co.Y;
+ QSize width_size(max_width * max_scale_x, round(max_width / (float(reader->info.width) / float(reader->info.height))));
+ QSize height_size(round(max_height / (float(reader->info.height) / float(reader->info.width))), max_height * max_scale_y);
+
+ // respect aspect ratio
+ if (width_size.width() >= max_width && width_size.height() >= max_height)
+ reader->SetMaxSize(width_size.width(), width_size.height());
+ else
+ reader->SetMaxSize(height_size.width(), height_size.height());
+
+ } else {
+ // No scaling, use original image size (slower)
reader->SetMaxSize(0, 0);
- else
- // No scaling applied, use max_size (usually the size of the timeline)
- reader->SetMaxSize(max_width, max_height);
+ }
// Attempt to get a frame (but this could fail if a reader has just been closed)
new_frame = reader->GetFrame(number);
diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp
index 6c3777df..4bb4b062 100644
--- a/src/KeyFrame.cpp
+++ b/src/KeyFrame.cpp
@@ -220,6 +220,25 @@ Point Keyframe::GetClosestPoint(Point p) {
return closest;
}
+// Get max point (by Y coordinate)
+Point Keyframe::GetMaxPoint() {
+ Point maxPoint(-1, -1);
+
+ // loop through points, and find the largest Y value
+ for (long int x = 0; x < Points.size(); x++) {
+ // Get each point
+ Point existing_point = Points[x];
+
+ // Is point larger than max point
+ if (existing_point.co.Y >= maxPoint.co.Y) {
+ // New max point found
+ maxPoint = existing_point;
+ }
+ }
+
+ return maxPoint;
+}
+
// Get the value at a specific index
float Keyframe::GetValue(long int index)
{
diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp
index 5bfecc59..8ee56374 100644
--- a/src/QtImageReader.cpp
+++ b/src/QtImageReader.cpp
@@ -123,6 +123,11 @@ tr1::shared_ptr QtImageReader::GetFrame(long int requested_frame) throw(R
// A max_width/max_height = 0 means do not scale (probably because we are scaling the image larger than 100%)
if (max_width != 0 && max_height != 0 && max_width < info.width && max_height < info.height)
{
+ // Remove cache that is no longer valid (if needed)
+ if (cached_image && !(cached_image->width() == max_width || cached_image->height() == max_height))
+ // Expire this cache
+ cached_image.reset();
+
// Scale image smaller (or use a previous scaled image)
if (!cached_image) {
// Create a scoped lock, allowing only a single thread to run the following code at one time
diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp
index 4d970465..0a8739c2 100644
--- a/tests/KeyFrame_Tests.cpp
+++ b/tests/KeyFrame_Tests.cpp
@@ -244,6 +244,32 @@ TEST(Keyframe_Get_Closest_Point)
}
+
+TEST(Keyframe_Get_Max_Point)
+{
+ // Create a keyframe curve
+ Keyframe kf;
+ kf.AddPoint(1, 1.0);
+
+ // Spot check values from the curve
+ CHECK_EQUAL(kf.GetMaxPoint().co.Y, 1.0);
+
+ kf.AddPoint(2, 0.0);
+
+ // Spot check values from the curve
+ CHECK_EQUAL(kf.GetMaxPoint().co.Y, 1.0);
+
+ kf.AddPoint(3, 2.0);
+
+ // Spot check values from the curve
+ CHECK_EQUAL(kf.GetMaxPoint().co.Y, 2.0);
+
+ kf.AddPoint(4, 1.0);
+
+ // Spot check values from the curve
+ CHECK_EQUAL(kf.GetMaxPoint().co.Y, 2.0);
+}
+
TEST(Keyframe_Scale_Keyframe)
{
// Create a keyframe curve with 2 points