aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Rector <rmrector@gmail.com>2023-08-02 18:53:32 -0600
committerGitHub <noreply@github.com>2023-08-02 18:53:32 -0600
commit89cc33615d0c755daa69adb4ae4b583d80bb6eac (patch)
tree2e3f73b742ea45a3def2f26d4bcc6a1b6c49e92f
parente9718f7ef9e663f7bc5bf97a6369697cad74e69b (diff)
parent5ae6b0fa1302894f30913634242ca6510a62fd13 (diff)
Merge pull request #23517 from rmrector/picturefolder-thumbnails
[guilib][vfs][imagecache] Load picture folder images into texture cache when viewed, like standard images
-rw-r--r--xbmc/TextureCache.cpp3
-rw-r--r--xbmc/TextureCacheJob.cpp3
-rw-r--r--xbmc/imagefiles/SpecialImageFileLoader.h6
-rw-r--r--xbmc/imagefiles/SpecialImageLoaderFactory.cpp2
-rw-r--r--xbmc/imagefiles/SpecialImageLoaderFactory.h2
-rw-r--r--xbmc/music/MusicEmbeddedImageFileLoader.cpp6
-rw-r--r--xbmc/music/MusicEmbeddedImageFileLoader.h6
-rw-r--r--xbmc/pictures/CMakeLists.txt2
-rw-r--r--xbmc/pictures/Picture.cpp85
-rw-r--r--xbmc/pictures/Picture.h3
-rw-r--r--xbmc/pictures/PictureFolderImageFileLoader.cpp63
-rw-r--r--xbmc/pictures/PictureFolderImageFileLoader.h27
-rw-r--r--xbmc/pictures/PictureThumbLoader.cpp24
-rw-r--r--xbmc/video/VideoEmbeddedImageFileLoader.cpp6
-rw-r--r--xbmc/video/VideoEmbeddedImageFileLoader.h6
-rw-r--r--xbmc/video/VideoGeneratedImageFileLoader.cpp8
-rw-r--r--xbmc/video/VideoGeneratedImageFileLoader.h6
17 files changed, 207 insertions, 51 deletions
diff --git a/xbmc/TextureCache.cpp b/xbmc/TextureCache.cpp
index 0ddccb727d..e0a5e2d906 100644
--- a/xbmc/TextureCache.cpp
+++ b/xbmc/TextureCache.cpp
@@ -97,7 +97,8 @@ std::string CTextureCache::GetCachedImage(const std::string &image, CTextureDeta
bool CTextureCache::CanCacheImageURL(const CURL &url)
{
return url.GetUserName().empty() || url.GetUserName() == "music" ||
- url.GetUserName() == "video" || StringUtils::StartsWith(url.GetUserName(), "video_") ||
+ url.GetUserName() == "video" || url.GetUserName() == "picturefolder" ||
+ StringUtils::StartsWith(url.GetUserName(), "video_") ||
StringUtils::StartsWith(url.GetUserName(), "pvr") ||
StringUtils::StartsWith(url.GetUserName(), "epg");
}
diff --git a/xbmc/TextureCacheJob.cpp b/xbmc/TextureCacheJob.cpp
index 7a7c555532..cc9eb4e34d 100644
--- a/xbmc/TextureCacheJob.cpp
+++ b/xbmc/TextureCacheJob.cpp
@@ -149,7 +149,8 @@ std::string CTextureCacheJob::DecodeImageURL(const std::string &url, unsigned in
if (!CTextureCache::CanCacheImageURL(thumbURL))
return "";
- if (thumbURL.GetUserName() == "music" || thumbURL.GetUserName() == "video")
+ if (thumbURL.GetUserName() == "music" || thumbURL.GetUserName() == "video" ||
+ thumbURL.GetUserName() == "picturefolder")
additional_info = thumbURL.GetUserName();
if (StringUtils::StartsWith(thumbURL.GetUserName(), "video_") ||
StringUtils::StartsWith(thumbURL.GetUserName(), "pvr") ||
diff --git a/xbmc/imagefiles/SpecialImageFileLoader.h b/xbmc/imagefiles/SpecialImageFileLoader.h
index 18b3b03655..b409c9fbd6 100644
--- a/xbmc/imagefiles/SpecialImageFileLoader.h
+++ b/xbmc/imagefiles/SpecialImageFileLoader.h
@@ -25,9 +25,9 @@ namespace IMAGE_FILES
class ISpecialImageFileLoader
{
public:
- virtual bool CanLoad(std::string specialType) const = 0;
- virtual std::unique_ptr<CTexture> Load(std::string specialType,
- std::string filePath,
+ virtual bool CanLoad(const std::string& specialType) const = 0;
+ virtual std::unique_ptr<CTexture> Load(const std::string& specialType,
+ const std::string& filePath,
unsigned int preferredWidth,
unsigned int preferredHeight) const = 0;
virtual ~ISpecialImageFileLoader() = default;
diff --git a/xbmc/imagefiles/SpecialImageLoaderFactory.cpp b/xbmc/imagefiles/SpecialImageLoaderFactory.cpp
index 639a4c1cd4..0fae961884 100644
--- a/xbmc/imagefiles/SpecialImageLoaderFactory.cpp
+++ b/xbmc/imagefiles/SpecialImageLoaderFactory.cpp
@@ -10,6 +10,7 @@
#include "guilib/Texture.h"
#include "music/MusicEmbeddedImageFileLoader.h"
+#include "pictures/PictureFolderImageFileLoader.h"
#include "video/VideoEmbeddedImageFileLoader.h"
#include "video/VideoGeneratedImageFileLoader.h"
@@ -20,6 +21,7 @@ CSpecialImageLoaderFactory::CSpecialImageLoaderFactory()
m_specialImageLoaders[0] = std::make_unique<VIDEO::CVideoEmbeddedImageFileLoader>();
m_specialImageLoaders[1] = std::make_unique<MUSIC_INFO::CMusicEmbeddedImageFileLoader>();
m_specialImageLoaders[2] = std::make_unique<VIDEO::CVideoGeneratedImageFileLoader>();
+ m_specialImageLoaders[3] = std::make_unique<CPictureFolderImageFileLoader>();
}
std::unique_ptr<CTexture> CSpecialImageLoaderFactory::Load(const std::string& specialType,
diff --git a/xbmc/imagefiles/SpecialImageLoaderFactory.h b/xbmc/imagefiles/SpecialImageLoaderFactory.h
index 3bf8f3ed5b..d633c617f1 100644
--- a/xbmc/imagefiles/SpecialImageLoaderFactory.h
+++ b/xbmc/imagefiles/SpecialImageLoaderFactory.h
@@ -29,6 +29,6 @@ public:
unsigned int preferredHeight) const;
private:
- std::array<std::unique_ptr<ISpecialImageFileLoader>, 3> m_specialImageLoaders{};
+ std::array<std::unique_ptr<ISpecialImageFileLoader>, 4> m_specialImageLoaders{};
};
} // namespace IMAGE_FILES
diff --git a/xbmc/music/MusicEmbeddedImageFileLoader.cpp b/xbmc/music/MusicEmbeddedImageFileLoader.cpp
index c93ee2bc46..212f51823f 100644
--- a/xbmc/music/MusicEmbeddedImageFileLoader.cpp
+++ b/xbmc/music/MusicEmbeddedImageFileLoader.cpp
@@ -17,7 +17,7 @@
using namespace MUSIC_INFO;
-bool CMusicEmbeddedImageFileLoader::CanLoad(std::string specialType) const
+bool CMusicEmbeddedImageFileLoader::CanLoad(const std::string& specialType) const
{
return specialType == "music";
}
@@ -36,8 +36,8 @@ bool GetEmbeddedThumb(const std::string& path, EmbeddedArt& art)
}
} // namespace
-std::unique_ptr<CTexture> CMusicEmbeddedImageFileLoader::Load(std::string specialType,
- std::string filePath,
+std::unique_ptr<CTexture> CMusicEmbeddedImageFileLoader::Load(const std::string& specialType,
+ const std::string& filePath,
unsigned int preferredWidth,
unsigned int preferredHeight) const
{
diff --git a/xbmc/music/MusicEmbeddedImageFileLoader.h b/xbmc/music/MusicEmbeddedImageFileLoader.h
index 95a2db7e12..45381edde8 100644
--- a/xbmc/music/MusicEmbeddedImageFileLoader.h
+++ b/xbmc/music/MusicEmbeddedImageFileLoader.h
@@ -19,9 +19,9 @@ public:
CMusicEmbeddedImageFileLoader() = default;
~CMusicEmbeddedImageFileLoader() override = default;
- bool CanLoad(std::string specialType) const override;
- std::unique_ptr<CTexture> Load(std::string specialType,
- std::string filePath,
+ bool CanLoad(const std::string& specialType) const override;
+ std::unique_ptr<CTexture> Load(const std::string& specialType,
+ const std::string& filePath,
unsigned int preferredWidth,
unsigned int preferredHeight) const override;
};
diff --git a/xbmc/pictures/CMakeLists.txt b/xbmc/pictures/CMakeLists.txt
index a6895a075a..fe4601aa07 100644
--- a/xbmc/pictures/CMakeLists.txt
+++ b/xbmc/pictures/CMakeLists.txt
@@ -7,6 +7,7 @@ set(SOURCES ExifParse.cpp
JpegParse.cpp
libexif.cpp
Picture.cpp
+ PictureFolderImageFileLoader.cpp
PictureInfoLoader.cpp
PictureInfoTag.cpp
PictureScalingAlgorithm.cpp
@@ -18,6 +19,7 @@ set(HEADERS GUIDialogPictureInfo.h
GUIWindowPictures.h
GUIWindowSlideShow.h
Picture.h
+ PictureFolderImageFileLoader.h
PictureInfoLoader.h
PictureInfoTag.h
PictureScalingAlgorithm.h
diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp
index 9c7ec1e377..ceeb515a9d 100644
--- a/xbmc/pictures/Picture.cpp
+++ b/xbmc/pictures/Picture.cpp
@@ -6,20 +6,22 @@
* See LICENSES/README.md for more information.
*/
-#include <algorithm>
-
#include "Picture.h"
-#include "URL.h"
+
+#include "FileItem.h"
#include "ServiceBroker.h"
+#include "URL.h"
+#include "filesystem/File.h"
+#include "guilib/Texture.h"
+#include "guilib/imagefactory.h"
#include "settings/AdvancedSettings.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
-#include "FileItem.h"
-#include "filesystem/File.h"
-#include "utils/log.h"
+#include "utils/MemUtils.h"
#include "utils/URIUtils.h"
-#include "guilib/Texture.h"
-#include "guilib/imagefactory.h"
+#include "utils/log.h"
+
+#include <algorithm>
extern "C" {
#include <libswscale/swscale.h>
@@ -277,6 +279,73 @@ bool CPicture::CacheTexture(uint8_t *pixels, uint32_t width, uint32_t height, ui
return false;
}
+std::unique_ptr<CTexture> CPicture::CreateTiledThumb(const std::vector<std::string>& files)
+{
+ if (!files.size())
+ return {};
+
+ unsigned int num_across =
+ static_cast<unsigned int>(std::ceil(std::sqrt(static_cast<float>(files.size()))));
+ unsigned int num_down = (files.size() + num_across - 1) / num_across;
+
+ unsigned int imageRes = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_imageRes;
+
+ unsigned int tile_width = imageRes / num_across;
+ unsigned int tile_height = imageRes / num_down;
+ unsigned int tile_gap = 1;
+ bool success = false; // Flag that we at least had one successful image processed
+
+ // create a buffer for the resulting thumb
+ std::unique_ptr<uint32_t[]> buffer = std::make_unique<uint32_t[]>(imageRes * imageRes);
+ if (!buffer)
+ return {};
+ for (unsigned int i = 0; i < files.size(); ++i)
+ {
+ int x = i % num_across;
+ int y = i / num_across;
+ // load in the image
+ unsigned int width = tile_width - 2 * tile_gap, height = tile_height - 2 * tile_gap;
+ std::unique_ptr<CTexture> texture = CTexture::LoadFromFile(files[i], width, height, true);
+ if (texture && texture->GetWidth() && texture->GetHeight())
+ {
+ GetScale(texture->GetWidth(), texture->GetHeight(), width, height);
+
+ // scale appropriately
+ std::unique_ptr<uint32_t[]> scaled = std::make_unique<uint32_t[]>(width * height);
+ if (ScaleImage(texture->GetPixels(), texture->GetWidth(), texture->GetHeight(),
+ texture->GetPitch(), AV_PIX_FMT_BGRA, reinterpret_cast<uint8_t*>(scaled.get()),
+ width, height, width * 4, AV_PIX_FMT_BGRA))
+ {
+ unsigned int stridePixels{width};
+ uint32_t* scaledL = scaled.get();
+ if (!texture->GetOrientation() ||
+ OrientateImage(scaledL, width, height, texture->GetOrientation(), stridePixels))
+ {
+ success = true;
+ // drop into the texture
+ unsigned int posX = x * tile_width + (tile_width - width) / 2;
+ unsigned int posY = y * tile_height + (tile_height - height) / 2;
+ uint32_t* dest = buffer.get() + posX + posY * imageRes;
+ const uint32_t* src = scaled.get();
+ for (unsigned int y = 0; y < height; ++y)
+ {
+ memcpy(dest, src, width * 4);
+ dest += imageRes;
+ src += stridePixels;
+ }
+ }
+ }
+ }
+ }
+
+ std::unique_ptr<CTexture> result = CTexture::CreateTexture();
+ if (success)
+ result->LoadFromMemory(imageRes, imageRes, imageRes * 4, XB_FMT_A8R8G8B8, true,
+ reinterpret_cast<unsigned char*>(buffer.get()));
+
+ return result;
+}
+
bool CPicture::CreateTiledThumb(const std::vector<std::string> &files, const std::string &thumb)
{
if (!files.size())
diff --git a/xbmc/pictures/Picture.h b/xbmc/pictures/Picture.h
index 192982aa1a..e3d02011b5 100644
--- a/xbmc/pictures/Picture.h
+++ b/xbmc/pictures/Picture.h
@@ -13,6 +13,7 @@
#include <cstddef>
#include <cstdint>
+#include <memory>
#include <string>
#include <vector>
@@ -35,6 +36,8 @@ public:
*/
static bool CreateTiledThumb(const std::vector<std::string> &files, const std::string &thumb);
+ static std::unique_ptr<CTexture> CreateTiledThumb(const std::vector<std::string>& files);
+
static bool ResizeTexture(
const std::string& image,
CTexture* texture,
diff --git a/xbmc/pictures/PictureFolderImageFileLoader.cpp b/xbmc/pictures/PictureFolderImageFileLoader.cpp
new file mode 100644
index 0000000000..1eb58f21b0
--- /dev/null
+++ b/xbmc/pictures/PictureFolderImageFileLoader.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "PictureFolderImageFileLoader.h"
+
+#include "FileItem.h"
+#include "Picture.h"
+#include "ServiceBroker.h"
+#include "TextureCache.h"
+#include "filesystem/Directory.h"
+#include "guilib/Texture.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "utils/FileExtensionProvider.h"
+
+using namespace XFILE;
+
+bool CPictureFolderImageFileLoader::CanLoad(const std::string& specialType) const
+{
+ return specialType == "picturefolder";
+}
+
+std::unique_ptr<CTexture> CPictureFolderImageFileLoader::Load(const std::string& specialType,
+ const std::string& filePath,
+ unsigned int preferredWidth,
+ unsigned int preferredHeight) const
+{
+ CFileItemList imagesInFolder;
+ CDirectory::GetDirectory(filePath, imagesInFolder,
+ CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(),
+ DIR_FLAG_NO_FILE_DIRS);
+
+ for (int i = 0; i < imagesInFolder.Size();)
+ {
+ if (!imagesInFolder[i]->IsPicture() || imagesInFolder[i]->IsZIP() ||
+ imagesInFolder[i]->IsRAR() || imagesInFolder[i]->IsPlayList())
+ {
+ imagesInFolder.Remove(i);
+ }
+ else
+ i++;
+ }
+ if (imagesInFolder.IsEmpty())
+ {
+ return {};
+ }
+
+ imagesInFolder.Randomize();
+ std::vector<std::string> imagesToTile;
+ int size = std::min(4, imagesInFolder.Size());
+ imagesToTile.reserve(size);
+ for (int thumb = 0; thumb < size; thumb++)
+ {
+ imagesToTile.push_back(imagesInFolder[thumb]->GetPath());
+ }
+
+ return CPicture::CreateTiledThumb(imagesToTile);
+}
diff --git a/xbmc/pictures/PictureFolderImageFileLoader.h b/xbmc/pictures/PictureFolderImageFileLoader.h
new file mode 100644
index 0000000000..aa5fb52678
--- /dev/null
+++ b/xbmc/pictures/PictureFolderImageFileLoader.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "imagefiles/SpecialImageFileLoader.h"
+
+/*!
+ * @brief Generates a thumbnail for a folder in the picture browser, tile 4 images inside the folder.
+*/
+class CPictureFolderImageFileLoader : public IMAGE_FILES::ISpecialImageFileLoader
+{
+public:
+ CPictureFolderImageFileLoader() = default;
+ ~CPictureFolderImageFileLoader() override = default;
+
+ bool CanLoad(const std::string& specialType) const override;
+ std::unique_ptr<CTexture> Load(const std::string& specialType,
+ const std::string& filePath,
+ unsigned int preferredWidth,
+ unsigned int preferredHeight) const override;
+};
diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp
index 755c7df0c2..97114e304e 100644
--- a/xbmc/pictures/PictureThumbLoader.cpp
+++ b/xbmc/pictures/PictureThumbLoader.cpp
@@ -39,6 +39,11 @@ CPictureThumbLoader::~CPictureThumbLoader()
void CPictureThumbLoader::OnLoaderFinish()
{
+ if (m_regenerateThumbs)
+ {
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
+ CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg);
+ }
m_regenerateThumbs = false;
CThumbLoader::OnLoaderFinish();
}
@@ -195,24 +200,9 @@ void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem)
}
else
{
- // ok, now we've got the files to get the thumbs from, lets create it...
- // we basically load the 4 images and combine them
- std::vector<std::string> files;
- files.reserve(4);
- for (int thumb = 0; thumb < 4; thumb++)
- files.push_back(items[thumb]->GetPath());
std::string thumb = CTextureUtils::GetWrappedImageURL(pItem->GetPath(), "picturefolder");
- std::string relativeCacheFile = CTextureCache::GetCacheFile(thumb) + ".png";
- if (CPicture::CreateTiledThumb(files, CTextureCache::GetCachedPath(relativeCacheFile)))
- {
- CTextureDetails details;
- details.file = relativeCacheFile;
- details.width = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_imageRes;
- details.height = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_imageRes;
- CServiceBroker::GetTextureCache()->AddCachedTexture(thumb, details);
- db.SetTextureForPath(pItem->GetPath(), "thumb", thumb);
- pItem->SetArt("thumb", CTextureCache::GetCachedPath(relativeCacheFile));
- }
+ db.SetTextureForPath(pItem->GetPath(), "thumb", thumb);
+ pItem->SetArt("thumb", thumb);
}
}
// refill in the icon to get it to update
diff --git a/xbmc/video/VideoEmbeddedImageFileLoader.cpp b/xbmc/video/VideoEmbeddedImageFileLoader.cpp
index 3fe3d04650..f5f9c813b2 100644
--- a/xbmc/video/VideoEmbeddedImageFileLoader.cpp
+++ b/xbmc/video/VideoEmbeddedImageFileLoader.cpp
@@ -18,7 +18,7 @@
using namespace VIDEO;
-bool CVideoEmbeddedImageFileLoader::CanLoad(std::string specialType) const
+bool CVideoEmbeddedImageFileLoader::CanLoad(const std::string& specialType) const
{
return StringUtils::StartsWith(specialType, "video_");
}
@@ -47,8 +47,8 @@ bool GetEmbeddedThumb(const std::string& path, const std::string& type, Embedded
}
} // namespace
-std::unique_ptr<CTexture> CVideoEmbeddedImageFileLoader::Load(std::string specialType,
- std::string filePath,
+std::unique_ptr<CTexture> CVideoEmbeddedImageFileLoader::Load(const std::string& specialType,
+ const std::string& filePath,
unsigned int preferredWidth,
unsigned int preferredHeight) const
{
diff --git a/xbmc/video/VideoEmbeddedImageFileLoader.h b/xbmc/video/VideoEmbeddedImageFileLoader.h
index c73ba5964a..2467adf9db 100644
--- a/xbmc/video/VideoEmbeddedImageFileLoader.h
+++ b/xbmc/video/VideoEmbeddedImageFileLoader.h
@@ -19,9 +19,9 @@ public:
CVideoEmbeddedImageFileLoader() = default;
~CVideoEmbeddedImageFileLoader() override = default;
- bool CanLoad(std::string specialType) const override;
- std::unique_ptr<CTexture> Load(std::string specialType,
- std::string filePath,
+ bool CanLoad(const std::string& specialType) const override;
+ std::unique_ptr<CTexture> Load(const std::string& specialType,
+ const std::string& filePath,
unsigned int preferredWidth,
unsigned int preferredHeight) const override;
};
diff --git a/xbmc/video/VideoGeneratedImageFileLoader.cpp b/xbmc/video/VideoGeneratedImageFileLoader.cpp
index 3cc6be8d3c..72ec950e16 100644
--- a/xbmc/video/VideoGeneratedImageFileLoader.cpp
+++ b/xbmc/video/VideoGeneratedImageFileLoader.cpp
@@ -16,7 +16,7 @@
#include "utils/URIUtils.h"
#include "video/VideoInfoTag.h"
-bool VIDEO::CVideoGeneratedImageFileLoader::CanLoad(std::string specialType) const
+bool VIDEO::CVideoGeneratedImageFileLoader::CanLoad(const std::string& specialType) const
{
return specialType == "video";
}
@@ -45,10 +45,8 @@ void SetupRarOptions(CFileItem& item, const std::string& path)
}
} // namespace
-std::unique_ptr<CTexture> VIDEO::CVideoGeneratedImageFileLoader::Load(std::string specialType,
- std::string filePath,
- unsigned int,
- unsigned int) const
+std::unique_ptr<CTexture> VIDEO::CVideoGeneratedImageFileLoader::Load(
+ const std::string& specialType, const std::string& filePath, unsigned int, unsigned int) const
{
CFileItem item{filePath, false};
diff --git a/xbmc/video/VideoGeneratedImageFileLoader.h b/xbmc/video/VideoGeneratedImageFileLoader.h
index 6ddc7ff67f..d25dfe6f27 100644
--- a/xbmc/video/VideoGeneratedImageFileLoader.h
+++ b/xbmc/video/VideoGeneratedImageFileLoader.h
@@ -18,9 +18,9 @@ namespace VIDEO
class CVideoGeneratedImageFileLoader : public IMAGE_FILES::ISpecialImageFileLoader
{
public:
- bool CanLoad(std::string specialType) const override;
- std::unique_ptr<CTexture> Load(std::string specialType,
- std::string filePath,
+ bool CanLoad(const std::string& specialType) const override;
+ std::unique_ptr<CTexture> Load(const std::string& specialType,
+ const std::string& filePath,
unsigned int preferredWidth,
unsigned int preferredHeight) const override;
};