Skip to content

Commit

Permalink
SCALE_NONE was incorrectly sizing SVG, Image, and Video files. Since …
Browse files Browse the repository at this point in the history
…OpenShot changes the preview window size during editing, the SCALE_NONE clips should always be scaled to the ratio: preview / timeline... so they stay relative sized to the timeline size.

For example, if an SVG is 500px wide, and the project is 1000px wide... the SVG in SCALE_NONE mode should always be 50% with width of the video, regardless of how small you make the preview window.
  • Loading branch information
jonoomph committed Aug 11, 2021
1 parent 7e419b9 commit 1c2786d
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 31 deletions.
10 changes: 3 additions & 7 deletions src/Clip.cpp
Expand Up @@ -1380,13 +1380,9 @@ QTransform Clip::get_transform(std::shared_ptr<Frame> frame, int width, int heig
break;
}
case (SCALE_NONE): {
// Calculate ratio of source size to project size
// Even with no scaling, previews need to be adjusted correctly
// (otherwise NONE scaling draws the frame image outside of the preview)
float source_width_ratio = source_size.width() / float(width);
float source_height_ratio = source_size.height() / float(height);
source_size.scale(width * source_width_ratio, height * source_height_ratio, Qt::KeepAspectRatio);

// Image is already the original size (i.e. no scaling mode) relative
// to the preview window size (i.e. timeline / preview ratio). No further
// scaling is needed here.
// Debug output
ZmqLogger::Instance()->AppendDebugMethod("Clip::get_transform (Scale: SCALE_NONE)", "frame->number", frame->number, "source_width", source_size.width(), "source_height", source_size.height());
break;
Expand Down
16 changes: 13 additions & 3 deletions src/FFmpegReader.cpp
Expand Up @@ -33,6 +33,7 @@

#include "FFmpegReader.h"
#include "Exceptions.h"
#include "Timeline.h"

#include <thread> // for std::this_thread::sleep_for
#include <chrono> // for std::chrono::milliseconds
Expand Down Expand Up @@ -1285,9 +1286,18 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) {
}

} else {
// No scaling, use original image size (slower)
max_width = info.width;
max_height = info.height;
// Scale video to equivalent unscaled size
// Since the preview window can change sizes, we want to always
// scale against the ratio of original video size to timeline size
float preview_ratio = 1.0;
if (parent->ParentTimeline()) {
Timeline *t = (Timeline *) parent->ParentTimeline();
preview_ratio = t->preview_width / float(t->info.width);
}
float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
max_width = info.width * max_scale_x * preview_ratio;
max_height = info.height * max_scale_y * preview_ratio;
}
}

Expand Down
74 changes: 54 additions & 20 deletions src/QtImageReader.cpp
Expand Up @@ -68,10 +68,14 @@ void QtImageReader::Open()
if (!is_open)
{
bool loaded = false;
QSize default_svg_size;

// Check for SVG files and rasterizing them to QImages
if (path.toLower().endsWith(".svg") || path.toLower().endsWith(".svgz")) {
loaded = load_svg_path(path);
default_svg_size = load_svg_path(path);
if (!default_svg_size.isEmpty()) {
loaded = true;
}
}

if (!loaded) {
Expand Down Expand Up @@ -100,8 +104,15 @@ void QtImageReader::Open()
info.file_size = image->byteCount();
#endif
info.vcodec = "QImage";
info.width = image->width();
info.height = image->height();
if (!default_svg_size.isEmpty()) {
// Use default SVG size (if detected)
info.width = default_svg_size.width();
info.height = default_svg_size.height();
} else {
// Use Qt Image size as a fallback
info.width = image->width();
info.height = image->height();
}
info.pixel_ratio.num = 1;
info.pixel_ratio.den = 1;
info.duration = 60 * 60 * 1; // 1 hour duration
Expand Down Expand Up @@ -196,7 +207,7 @@ QSize QtImageReader::calculate_max_size() {
int max_width = info.width;
int max_height = info.height;
if (max_width == 0 || max_height == 0) {
// If no size determined yet, default to 4K
// If no size determined yet
max_width = 1920;
max_height = 1080;
}
Expand Down Expand Up @@ -227,11 +238,23 @@ QSize QtImageReader::calculate_max_size() {
if (width_size.width() >= max_width && width_size.height() >= max_height) {
max_width = std::max(max_width, width_size.width());
max_height = std::max(max_height, width_size.height());
}
else {
} else {
max_width = std::max(max_width, height_size.width());
max_height = std::max(max_height, height_size.height());
}
} else if (parent->scale == SCALE_NONE) {
// Scale images to equivalent unscaled size
// Since the preview window can change sizes, we want to always
// scale against the ratio of original image size to timeline size
float preview_ratio = 1.0;
if (parent->ParentTimeline()) {
Timeline *t = (Timeline *) parent->ParentTimeline();
preview_ratio = t->preview_width / float(t->info.width);
}
float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
max_width = info.width * max_scale_x * preview_ratio;
max_height = info.height * max_scale_y * preview_ratio;
}
}

Expand All @@ -240,8 +263,9 @@ QSize QtImageReader::calculate_max_size() {
}

// Load an SVG file with Resvg or fallback with Qt
bool QtImageReader::load_svg_path(QString) {
QSize QtImageReader::load_svg_path(QString) {
bool loaded = false;
QSize default_size(0,0);

// Calculate max image size
QSize current_max_size = calculate_max_size();
Expand All @@ -250,8 +274,12 @@ bool QtImageReader::load_svg_path(QString) {
// Use libresvg for parsing/rasterizing SVG
ResvgRenderer renderer(path);
if (renderer.isValid()) {
// Set default SVG size
default_size.setWidth(renderer.defaultSize().width());
default_size.setHeight(renderer.defaultSize().height());

// Scale SVG size to keep aspect ratio, and fill the max_size as best as possible
QSize svg_size(renderer.defaultSize().width(), renderer.defaultSize().height());
QSize svg_size(default_size.width(), default_size.height());
svg_size.scale(current_max_size.width(), current_max_size.height(), Qt::KeepAspectRatio);

// Load SVG at max size
Expand All @@ -269,22 +297,28 @@ bool QtImageReader::load_svg_path(QString) {
image = std::make_shared<QImage>();
loaded = image->load(path);

if (loaded && (image->width() < current_max_size.width() || image->height() < current_max_size.height())) {
// Load SVG into larger/project size (so image is not blurry)
QSize svg_size = image->size().scaled(current_max_size.width(), current_max_size.height(), Qt::KeepAspectRatio);
if (QCoreApplication::instance()) {
// Requires QApplication to be running (for QPixmap support)
// Re-rasterize SVG image to max size
image = std::make_shared<QImage>(QIcon(path).pixmap(svg_size).toImage());
} else {
// Scale image without re-rasterizing it (due to lack of QApplication)
image = std::make_shared<QImage>(image->scaled(
svg_size.width(), svg_size.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
if (loaded) {
// Set default SVG size
default_size.setWidth(image->width());
default_size.setHeight(image->height());

if (image->width() < current_max_size.width() || image->height() < current_max_size.height()) {
// Load SVG into larger/project size (so image is not blurry)
QSize svg_size = image->size().scaled(current_max_size.width(), current_max_size.height(), Qt::KeepAspectRatio);
if (QCoreApplication::instance()) {
// Requires QApplication to be running (for QPixmap support)
// Re-rasterize SVG image to max size
image = std::make_shared<QImage>(QIcon(path).pixmap(svg_size).toImage());
} else {
// Scale image without re-rasterizing it (due to lack of QApplication)
image = std::make_shared<QImage>(image->scaled(
svg_size.width(), svg_size.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
}
}
}

return loaded;
return default_size;
}

// Generate JSON string of this object
Expand Down
2 changes: 1 addition & 1 deletion src/QtImageReader.h
Expand Up @@ -77,7 +77,7 @@ namespace openshot
///
/// @returns Success as a boolean
/// @param path The file path of the SVG file
bool load_svg_path(QString path);
QSize load_svg_path(QString path);

/// Calculate the max_size QSize, based on parent timeline and parent clip settings
QSize calculate_max_size();
Expand Down

0 comments on commit 1c2786d

Please sign in to comment.