diff --git a/es-app/src/scrapers/Scraper.cpp b/es-app/src/scrapers/Scraper.cpp index f6345d7d8..0d0b6181c 100644 --- a/es-app/src/scrapers/Scraper.cpp +++ b/es-app/src/scrapers/Scraper.cpp @@ -22,6 +22,7 @@ #include "views/ViewController.h" #endif +#include <cmath> #include <FreeImage.h> #include <fstream> @@ -307,8 +308,7 @@ MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result, // Resize it. if (it->resizeFile) { - if (!resizeImage(filePath, Settings::getInstance()->getInt("ScraperResizeMaxWidth"), - Settings::getInstance()->getInt("ScraperResizeMaxHeight"))) { + if (!resizeImage(filePath, it->subDirectory)) { setError("Error saving resized image.\nOut of memory? Disk full?"); return; } @@ -319,7 +319,7 @@ MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result, // If it's not cached, then initiate the download. else { mFuncs.push_back(ResolvePair(downloadMediaAsync(it->fileURL, filePath, - it->existingMediaFile, it->resizeFile, mResult.savedNewMedia), + it->existingMediaFile, it->subDirectory, it->resizeFile, mResult.savedNewMedia), [this, filePath] {})); } } @@ -353,6 +353,7 @@ std::unique_ptr<MediaDownloadHandle> downloadMediaAsync( const std::string& url, const std::string& saveAs, const std::string& existingMediaPath, + const std::string& mediaType, const bool resizeFile, bool& savedNewMedia) { @@ -360,25 +361,22 @@ std::unique_ptr<MediaDownloadHandle> downloadMediaAsync( url, saveAs, existingMediaPath, + mediaType, resizeFile, - savedNewMedia, - Settings::getInstance()->getInt("ScraperResizeMaxWidth"), - Settings::getInstance()->getInt("ScraperResizeMaxHeight"))); + savedNewMedia)); } MediaDownloadHandle::MediaDownloadHandle( const std::string& url, const std::string& path, const std::string& existingMediaPath, + const std::string& mediaType, const bool resizeFile, - bool& savedNewMedia, - int maxWidth, - int maxHeight) + bool& savedNewMedia) : mSavePath(path), mExistingMediaFile(existingMediaPath), + mMediaType(mediaType), mResizeFile(resizeFile), - mMaxWidth(maxWidth), - mMaxHeight(maxHeight), mReq(new HttpReq(url)) { mSavedNewMediaPtr = &savedNewMedia; @@ -453,7 +451,7 @@ void MediaDownloadHandle::update() // Resize it. if (mResizeFile) { - if (!resizeImage(mSavePath, mMaxWidth, mMaxHeight)) { + if (!resizeImage(mSavePath, mMediaType)) { setError("Error saving resized image.\nOut of memory? Disk full?"); return; } @@ -465,17 +463,25 @@ void MediaDownloadHandle::update() setStatus(ASYNC_DONE); } -// You can pass 0 for width or height to keep aspect ratio. -bool resizeImage(const std::string& path, int maxWidth, int maxHeight) +bool resizeImage(const std::string& path, const std::string& mediaType) { - // Nothing to do. - if (maxWidth == 0 && maxHeight == 0) - return true; + float maxWidth = 0.0f; + float maxHeight = 0.0f; + + if (mediaType == "marquees") { + // We don't really need huge marquees. + maxWidth = 1000.0f; + maxHeight = 600.0f; + } + else { + maxWidth = 2560.0f; + maxHeight = 1440.0f; + } FREE_IMAGE_FORMAT format = FIF_UNKNOWN; FIBITMAP* image = nullptr; - // Detect the filetype. + // Detect the file format. format = FreeImage_GetFileType(path.c_str(), 0); if (format == FIF_UNKNOWN) format = FreeImage_GetFIFFromFilename(path.c_str()); @@ -484,7 +490,7 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight) return false; } - // Make sure we can read this filetype first, then load it. + // Make sure we can read this format, and if so, then load it. if (FreeImage_FIFSupportsReading(format)) { image = FreeImage_Load(format, path.c_str()); } @@ -496,23 +502,37 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight) float width = static_cast<float>(FreeImage_GetWidth(image)); float height = static_cast<float>(FreeImage_GetHeight(image)); - // If the image is smaller than maxWidth or maxHeight, then don't do any - // scaling. It doesn't make sense to upscale the image and waste disk space. - if (maxWidth > width || maxHeight > height) { + // If the image is smaller than (or the same size as) maxWidth and maxHeight, then don't + // do any scaling. It doesn't make sense to upscale the image and waste disk space. + if (maxWidth >= width && maxHeight >= height) { + LOG(LogDebug) << "Scraper::resizeImage(): Saving image \"" << path << + "\" at its original resolution " << width << "x" << height; FreeImage_Unload(image); return true; } - if (maxWidth == 0) - maxWidth = static_cast<int>((maxHeight / height) * width); - else if (maxHeight == 0) - maxHeight = static_cast<int>((maxWidth / width) * height); + float scaleFactor = 0.0f; - FIBITMAP* imageRescaled = FreeImage_Rescale(image, maxWidth, maxHeight, FILTER_BILINEAR); + // Calculate how much we should scale. + if (width > maxWidth) { + scaleFactor = maxWidth / width; + if (height * scaleFactor > maxHeight) + scaleFactor = maxHeight / height; + } + else { + scaleFactor = maxHeight / height; + } + + maxWidth = floorf(width * scaleFactor); + maxHeight = floorf(height * scaleFactor); + + // We use Lanczos3 which is the highest quality resampling method available in FreeImage. + FIBITMAP* imageRescaled = FreeImage_Rescale(image, static_cast<int>(maxWidth), + static_cast<int>(maxHeight), FILTER_LANCZOS3); FreeImage_Unload(image); if (imageRescaled == nullptr) { - LOG(LogError) << "Could not resize image (not enough memory or invalid bitdepth?)"; + LOG(LogError) << "Couldn't resize image, not enough memory or invalid bit depth?"; return false; } @@ -522,6 +542,10 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight) if (!saved) { LOG(LogError) << "Failed to save resized image"; } + else { + LOG(LogDebug) << "Scraper::resizeImage(): Downscaled image \"" << path << "\" from " + << width << "x" << height << " to " << maxWidth << "x" << maxHeight; + } return saved; } diff --git a/es-app/src/scrapers/Scraper.h b/es-app/src/scrapers/Scraper.h index 77ab0b7b1..5cf3c6f0d 100644 --- a/es-app/src/scrapers/Scraper.h +++ b/es-app/src/scrapers/Scraper.h @@ -195,10 +195,9 @@ public: const std::string& url, const std::string& path, const std::string& existingMediaPath, + const std::string& mediaType, const bool resizeFile, - bool& savedNewMedia, - int maxWidth, - int maxHeight); + bool& savedNewMedia); void update() override; @@ -206,10 +205,9 @@ private: std::unique_ptr<HttpReq> mReq; std::string mSavePath; std::string mExistingMediaFile; + std::string mMediaType; bool mResizeFile; bool *mSavedNewMediaPtr; - int mMaxWidth; - int mMaxHeight; }; // Downloads to the home directory, using this subdirectory structure: @@ -218,12 +216,11 @@ private: std::string getSaveAsPath(const ScraperSearchParams& params, const std::string& filetypeSubdirectory, const std::string& url); -// Will resize according to Settings::getInt("ScraperResizeMaxWidth") and -// Settings::getInt("ScraperResizeMaxHeight"). std::unique_ptr<MediaDownloadHandle> downloadMediaAsync( const std::string& url, const std::string& saveAs, const std::string& existingMediaPath, + const std::string& mediaType, const bool resizeFile, bool& savedNewMedia); @@ -231,9 +228,6 @@ std::unique_ptr<MediaDownloadHandle> downloadMediaAsync( std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result, const ScraperSearchParams& search); -// You can pass 0 for maxWidth or maxHeight to automatically keep the aspect ratio. -// It will overwrite the image at [path] with the new resized one. -// Returns true if successful, false otherwise. -bool resizeImage(const std::string& path, int maxWidth, int maxHeight); +bool resizeImage(const std::string& path, const std::string& mediaType); #endif // ES_APP_SCRAPERS_SCRAPER_H diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index ea05b6ea7..e2e3317a9 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -301,8 +301,7 @@ void Settings::setDefaults() // mStringMap["ROMDirectory"] = { "", "" }; - mIntMap["ScraperResizeMaxWidth"] = { 600, 600 }; - mIntMap["ScraperResizeMaxHeight"] = { 0, 0 }; + mStringMap["UIMode_passkey"] = { "uuddlrlrba", "uuddlrlrba" }; // // Hardcoded or program-internal settings. @@ -313,7 +312,6 @@ void Settings::setDefaults() mBoolMap["DebugImage"] = { false, false }; mBoolMap["SplashScreenProgress"] = { true, true }; mIntMap["ScraperFilter"] = { 0, 0 }; - mStringMap["UIMode_passkey"] = { "uuddlrlrba", "uuddlrlrba" }; } template <typename K, typename V>