From a68a4e151779e174cba3fc180797ed84a2a72d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Tue, 6 Dec 2022 12:06:35 +0100 Subject: [PATCH] feat(cli): speedup scaling with painter scaling (#88) As suggested by PySide6's documentation, we avoid using pixmap.scaled() on every frame, but use scaled content to resize the image. This seems to ignore ratio, explaining why we need a new option flag. --- manim_slides/present.py | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/manim_slides/present.py b/manim_slides/present.py index d4bf93c..49a4070 100644 --- a/manim_slides/present.py +++ b/manim_slides/present.py @@ -2,7 +2,7 @@ import os import platform import sys import time -from enum import IntEnum, auto, unique +from enum import Enum, IntEnum, auto, unique from typing import Any, Dict, List, Optional, Tuple, Union import click @@ -28,9 +28,17 @@ WINDOW_NAME = "Manim Slides" WINDOW_INFO_NAME = f"{WINDOW_NAME}: Info" WINDOWS = platform.system() == "Windows" + +class AspectRatio(Enum): + ignore = Qt.IgnoreAspectRatio + keep = Qt.KeepAspectRatio + auto = "auto" + + ASPECT_RATIO_MODES = { - "ignore": Qt.IgnoreAspectRatio, - "keep": Qt.KeepAspectRatio, + "ignore": AspectRatio.ignore, + "keep": AspectRatio.keep, + "auto": AspectRatio.auto, } RESIZE_MODES = { @@ -514,7 +522,7 @@ class App(QWidget): # type: ignore fullscreen: bool = False, resolution: Tuple[int, int] = (1980, 1080), hide_mouse: bool = False, - aspect_ratio: Qt.AspectRatioMode = Qt.IgnoreAspectRatio, + aspect_ratio: AspectRatio = AspectRatio.auto, resize_mode: Qt.TransformationMode = Qt.SmoothTransformation, background_color: str = "black", **kwargs: Any, @@ -533,6 +541,9 @@ class App(QWidget): # type: ignore self.setCursor(Qt.BlankCursor) self.label = QLabel(self) + + if self.aspect_ratio == AspectRatio.auto: + self.label.setScaledContents(True) self.label.setAlignment(Qt.AlignCenter) self.label.resize(self.display_width, self.display_height) self.label.setStyleSheet(f"background-color: {background_color}") @@ -584,10 +595,11 @@ class App(QWidget): # type: ignore self.deleteLater() def resizeEvent(self, event: QResizeEvent) -> None: - self.pixmap = self.pixmap.scaled( - self.width(), self.height(), self.aspect_ratio, self.resize_mode - ) - self.label.setPixmap(self.pixmap) + if not self.label.hasScaledContents(): + self.pixmap = self.pixmap.scaled( + self.width(), self.height(), self.aspect_ratio.value, self.resize_mode + ) + self.label.setPixmap(self.pixmap) self.label.resize(self.width(), self.height()) def closeEvent(self, event: QCloseEvent) -> None: @@ -601,9 +613,11 @@ class App(QWidget): # type: ignore bytes_per_line = ch * w qt_img = QImage(cv_img.data, w, h, bytes_per_line, QImage.Format_BGR888) - if w != self.width() or h != self.height(): + if not self.label.hasScaledContents() and ( + w != self.width() or h != self.height() + ): qt_img = qt_img.scaled( - self.width(), self.height(), self.aspect_ratio, self.resize_mode + self.width(), self.height(), self.aspect_ratio.value, self.resize_mode ) self.label.setPixmap(QPixmap.fromImage(qt_img)) @@ -755,8 +769,8 @@ def get_scenes_presentation_config( @click.option( "--aspect-ratio", type=click.Choice(ASPECT_RATIO_MODES.keys(), case_sensitive=False), - default="ignore", - help="Set the aspect ratio mode to be used when rescaling video.", + default="auto", + help="Set the aspect ratio mode to be used when rescaling video. `'auto'` option is equivalent to `'ignore'`, but can be much faster due to not calling `scaled()` method on every frame.", show_default=True, ) @click.option(