From 87e628a9e93e1752e80d9a20ef346cc61abf05fe Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 28 Jul 2022 20:57:13 +0200 Subject: [PATCH] cellPhotoDecode: optimize get_scaled_image --- rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp | 2 +- rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp | 2 +- rpcs3/Emu/System.h | 2 +- rpcs3/main_application.cpp | 52 +++++++++++++++++----- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp b/rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp index 7cd6599fb3..5ba46d0cb9 100644 --- a/rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPhotoDecode.cpp @@ -162,7 +162,7 @@ error_code cellPhotoDecodeFromFile(vm::cptr srcHddDir, vm::cptr srcH s32 width{}; s32 height{}; - if (!Emu.GetCallbacks().get_scaled_image(path, set_param->width, set_param->height, width, height, static_cast(set_param->dstBuffer.get_ptr()))) + if (!Emu.GetCallbacks().get_scaled_image(path, set_param->width, set_param->height, width, height, static_cast(set_param->dstBuffer.get_ptr()), false)) { cellPhotoDecode.error("Failed to decode '%s'", path); return CELL_PHOTO_DECODE_ERROR_DECODE; diff --git a/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp b/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp index 23ec40b3b0..cdbaa2689a 100644 --- a/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp @@ -157,7 +157,7 @@ error_code select_photo(std::string dst_dir) if (!fs::stat(info.path, f_info) || f_info.is_directory) { - cellPhotoImportUtil.error("Path is not a directory: '%s'", info.path); + cellPhotoImportUtil.error("Path does not belong to a valid file: '%s'", info.path); result = CELL_PHOTO_IMPORT_ERROR_ACCESS_ERROR; // TODO: is this correct ? pi_manager.is_busy = false; pi_manager.func_finish(ppu, result, g_filedata, pi_manager.userdata); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 6fa1a2d948..51839a438a 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -97,7 +97,7 @@ struct EmuCallbacks std::function get_localized_u32string; std::function play_sound; std::function get_image_info; // (filename, sub_type, width, height, CellSearchOrientation) - std::function get_scaled_image; // (filename, target_width, target_height, width, height, dst) + std::function get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit) std::string(*resolve_path)(std::string_view) = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt }; diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index a132ada532..c75ca809b1 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -189,11 +189,15 @@ EmuCallbacks main_application::CreateCallbacks() success = true; sys_log.notice("get_image_info found image: filename='%s', sub_type='%s', width=%d, height=%d, orientation=%d", filename, sub_type, width, height, orientation); } + else + { + sys_log.warning("get_image_info failed to read '%s'. Error='%s'", filename, reader.errorString().toStdString()); + } }); return success; }; - callbacks.get_scaled_image = [](const std::string& path, s32 target_width, s32 target_height, s32& width, s32& height, u8* dst) -> bool + callbacks.get_scaled_image = [](const std::string& path, s32 target_width, s32 target_height, s32& width, s32& height, u8* dst, bool force_fit) -> bool { width = 0; height = 0; @@ -206,34 +210,58 @@ EmuCallbacks main_application::CreateCallbacks() bool success = false; Emu.BlockingCallFromMainThread([&]() { - QImage image{}; - success = image.load(QString::fromStdString(path)) && !image.isNull(); + // We use QImageReader instead of QImage. This way we can load and scale image in one step. + QImageReader reader(QString::fromStdString(path)); - if (success) + if (reader.canRead()) { - width = image.width(); - height = image.height(); + QSize size = reader.size(); + width = size.width(); + height = size.height(); if (width <= 0 || height <= 0) { - success = false; return; } - if (width > target_width || height > target_height) + if (force_fit || width > target_width || height > target_height) { - const QSize size(target_width, target_height); - image = image.scaled(QSize(target_width, target_height), Qt::AspectRatioMode::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation); - width = image.width(); - height = image.height(); + const f32 target_ratio = target_width / static_cast(target_height); + const f32 image_ratio = width / static_cast(height); + const f32 convert_ratio = image_ratio / target_ratio; + + if (convert_ratio > 1.0f) + { + size = QSize(target_width, target_height / convert_ratio); + } + else if (convert_ratio < 1.0f) + { + size = QSize(target_width * convert_ratio, target_height); + } + else + { + size = QSize(target_width, target_height); + } + + reader.setScaledSize(size); + width = size.width(); + height = size.height(); } + QImage image = reader.read(); + if (image.format() != QImage::Format::Format_RGBA8888) { image = image.convertToFormat(QImage::Format::Format_RGBA8888); } std::memcpy(dst, image.constBits(), std::min(4 * target_width * target_height, image.height() * image.bytesPerLine())); + success = true; + sys_log.notice("get_scaled_image scaled image: path='%s', width=%d, height=%d", path, width, height); + } + else + { + sys_log.error("get_scaled_image failed to read '%s'. Error='%s'", path, reader.errorString().toStdString()); } }); return success;