From 44c0b7ebdd05a0e19f9d7cd4540644f5cf191bdf Mon Sep 17 00:00:00 2001 From: Karou Date: Fri, 26 Dec 2025 02:31:50 -0500 Subject: [PATCH] First try --- .../Internal/TextureManager.BlameTracker.cs | 2 +- .../Textures/Internal/TextureManager.cs | 50 ++++++++++++++++++- .../Internal/TextureManagerPluginScoped.cs | 9 ++++ Dalamud/Plugin/Services/ITextureProvider.cs | 5 ++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs b/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs index fde40d462..6e1e25314 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs @@ -59,7 +59,7 @@ internal sealed partial class TextureManager /// The texture. /// The plugin. /// Same . - public unsafe IDalamudTextureWrap Blame(IDalamudTextureWrap textureWrap, LocalPlugin? ownerPlugin) + public unsafe IDalamudTextureWrap Blame(IDalamudTextureWrap? textureWrap, LocalPlugin? ownerPlugin) { if (!this.dalamudConfiguration.UseTexturePluginTracking) return textureWrap; diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.cs b/Dalamud/Interface/Textures/Internal/TextureManager.cs index d0f0d8c07..c5b540f7a 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.cs @@ -1,5 +1,7 @@ +using System.Drawing; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -17,13 +19,21 @@ using Dalamud.Plugin.Services; using Dalamud.Storage.Assets; using Dalamud.Utility; using Dalamud.Utility.TerraFxCom; - using Lumina.Data; using Lumina.Data.Files; - using TerraFX.Interop.DirectX; using TerraFX.Interop.Windows; +using static TerraFX.Interop.Windows.COINIT; +using static TerraFX.Interop.Windows.SIIGBF; +using static TerraFX.Interop.Windows.Windows; + +using BitmapData = System.Drawing.Imaging.BitmapData; +using HBITMAP = TerraFX.Interop.Windows.HBITMAP; +using ImageLockMode = System.Drawing.Imaging.ImageLockMode; +using IShellItemImageFactory = TerraFX.Interop.Windows.IShellItemImageFactory; +using SIZE = TerraFX.Interop.Windows.SIZE; + namespace Dalamud.Interface.Textures.Internal; /// Service responsible for loading and disposing ImGui texture wraps. @@ -303,6 +313,42 @@ internal sealed partial class TextureManager return (supported & required) == required; } + /// + public unsafe IDalamudTextureWrap? TryGetFileThumbnail(string path) + { + const int size = 256; + HRESULT hr = CoInitializeEx(null, (uint)(COINIT_DISABLE_OLE1DDE | COINIT_MULTITHREADED)); + if (hr.FAILED) + return null; + + IShellItemImageFactory* imageFact; + fixed (char* pstr = path) + { + hr = SHCreateItemFromParsingName(pstr, null, __uuidof(), (void**)&imageFact); + } + + if (hr.FAILED) + return null; + + HBITMAP hbmp; + imageFact->GetImage(new SIZE(cx: size, cy: size), (int)SIIGBF_BIGGERSIZEOK, &hbmp); + var image = Image.FromHbitmap(hbmp); + BitmapData bd = image.LockBits(new(Point.Empty, image.Size), ImageLockMode.ReadOnly, image.PixelFormat); + var rowSize = bd.Stride < 0 ? -bd.Stride : bd.Stride; + var pixels = new byte[bd.Height * rowSize]; + var iptr = bd.Scan0; + + for (int y = 0; y < bd.Height; y++) + { + Marshal.Copy(IntPtr.Add(iptr, y * bd.Stride), + pixels, y * rowSize, + rowSize); + } + + image.UnlockBits(bd); + return this.CreateFromRaw(new RawImageSpecification(bd.Width, bd.Height, (int)DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM), pixels.AsSpan()); + } + /// internal unsafe IDalamudTextureWrap NoThrottleCreateFromRaw( RawImageSpecification specs, diff --git a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs index ac6de7dd7..e87d8af43 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs @@ -454,6 +454,15 @@ internal sealed class TextureManagerPluginScoped await manager.CopyToClipboardAsync(wrap, preferredFileNameWithoutExtension, leaveWrapOpen, cancellationToken); } + /// + public IDalamudTextureWrap? TryGetFileThumbnail(string path) + { + var manager = this.ManagerOrThrow; + var textureWrap = manager.TryGetFileThumbnail(path); + manager.Blame(textureWrap, this.plugin); + return textureWrap; + } + private void ResultOnInterceptTexDataLoad(string path, ref string? replacementPath) => this.InterceptTexDataLoad?.Invoke(path, ref replacementPath); } diff --git a/Dalamud/Plugin/Services/ITextureProvider.cs b/Dalamud/Plugin/Services/ITextureProvider.cs index dc0522aa8..83420f6c2 100644 --- a/Dalamud/Plugin/Services/ITextureProvider.cs +++ b/Dalamud/Plugin/Services/ITextureProvider.cs @@ -330,4 +330,9 @@ public interface ITextureProvider : IDalamudService /// ((delegate* unmanaged<nint, void>)(*(nint**)ptr)[3](ptr). /// nint ConvertToKernelTexture(IDalamudTextureWrap wrap, bool leaveWrapOpen = false); + + /// Tries to get a files thumbnail from the Win32 API + /// Path to file you want to preview. + /// A TextureWrap or null. + IDalamudTextureWrap? TryGetFileThumbnail(string filePath); }