You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Improved image caching logic, to better estimate max image sizes possible, based on clip scale and keyframe settings... so we are always dealing with the smallest possible frame sizes for performance (without losing quality)
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
31
src/Clip.cpp
31
src/Clip.cpp
@@ -597,13 +597,32 @@ tr1::shared_ptr<Frame> 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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -123,6 +123,11 @@ tr1::shared_ptr<Frame> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user