From 1c2786de357f60ef1c22c282e7f9b3cd5f23c694 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Wed, 11 Aug 2021 12:10:46 -0500 Subject: [PATCH] SCALE_NONE was incorrectly sizing SVG, Image, and Video files. Since 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. --- src/Clip.cpp | 10 ++---- src/FFmpegReader.cpp | 16 ++++++++-- src/QtImageReader.cpp | 74 +++++++++++++++++++++++++++++++------------ src/QtImageReader.h | 2 +- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 5b4270356..35d0fba13 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1380,13 +1380,9 @@ QTransform Clip::get_transform(std::shared_ptr 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; diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 98d39ce1f..c1eaa7482 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -33,6 +33,7 @@ #include "FFmpegReader.h" #include "Exceptions.h" +#include "Timeline.h" #include // for std::this_thread::sleep_for #include // for std::chrono::milliseconds @@ -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; } } diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp index 29243ed45..1800a0f24 100644 --- a/src/QtImageReader.cpp +++ b/src/QtImageReader.cpp @@ -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) { @@ -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 @@ -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; } @@ -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; } } @@ -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(); @@ -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 @@ -269,22 +297,28 @@ bool QtImageReader::load_svg_path(QString) { image = std::make_shared(); 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(QIcon(path).pixmap(svg_size).toImage()); - } else { - // Scale image without re-rasterizing it (due to lack of QApplication) - image = std::make_shared(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(QIcon(path).pixmap(svg_size).toImage()); + } else { + // Scale image without re-rasterizing it (due to lack of QApplication) + image = std::make_shared(image->scaled( + svg_size.width(), svg_size.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + } } } } - return loaded; + return default_size; } // Generate JSON string of this object diff --git a/src/QtImageReader.h b/src/QtImageReader.h index 0dc359b15..687e85e14 100644 --- a/src/QtImageReader.h +++ b/src/QtImageReader.h @@ -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();