ファイルに対する画像を取得する(WPF)
WPFで、単にファイルに対する画像を取得しようとしたのですが、たったこれだけのことにも関わらず、
意外と、どこにもソースが落ちていない。
もちろん、 WindowsAPICodePack を使えば、簡単にできるんですが、大なた過ぎて、ちょっと・・・っていう感じだったり、あるいは、サムネイルを生成したいわけで、アイコン画像が欲しいわけじゃ無いとか、そういうカスタマイズ性がないみたいで、ちょっと困る感じ名部分があります。
というか、C++ならまだ良いんですが、C#だと、IExtractThumbnailとの戦いで消耗している人達ばっかりで、???って感じでした。
ということで、 IShellItemImageFactory を使ってサックリと作ってみました。
using System; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; namespace FileThumbnailExtractor { public static class FileThumbnailExtractor { [StructLayoutAttribute(LayoutKind.Sequential)] struct SIZE { public int cx; public int cy; } [Flags] enum SIIGBF { RESIZETOFIT = 0, BIGGERSIZEOK = 1, MEMORYONLY = 2, ICONONLY = 4, THUMBNAILONLY = 8, INCACHEONLY = 0x10, CROPTOSQUARE = 0x20, WIDETHUMBNAILS = 0x40, ICONBACKGROUND = 0x80, SCALEUP = 0x100, } [ComImport, Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IShellItemImageFactory { [PreserveSig] void GetImage(SIZE size, SIIGBF flags, out IntPtr phbm); } [DllImport("shell32"), PreserveSig] extern static void SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object iunk); [DllImport("gdi32")] extern static int DeleteObject(IntPtr hObject); public static BitmapSource GetThumbnail(string fileName, int desiredWidth, int desiredHeight, ThumbnailType type) { object iunk = null; IntPtr hBmp = IntPtr.Zero; try { var IID_IShellItemImageFactory = new Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b"); SHCreateItemFromParsingName(fileName, IntPtr.Zero, ref IID_IShellItemImageFactory, out iunk); var factory = (IShellItemImageFactory)iunk; SIIGBF flags = SIIGBF.BIGGERSIZEOK; if (type == ThumbnailType.Icon) flags |= SIIGBF.ICONONLY; else if (type == ThumbnailType.Thumbnail) flags |= SIIGBF.THUMBNAILONLY; factory.GetImage(new SIZE { cx = desiredWidth, cy = desiredHeight }, flags, out hBmp); var bmp = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBmp, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); bmp.Freeze(); return bmp; } finally { DeleteObject(hBmp); Marshal.ReleaseComObject(iunk); } } public static async Task<BitmapSource> GetThumbnailAsync(string fileName, int desiredWidth, int desiredHeight, ThumbnailType type) { return await Task.Run(() => GetThumbnail(fileName, desiredWidth, desiredHeight, type)); } } [Flags] public enum ThumbnailType { Icon = 1, Thumbnail = 2, Any = 3, } }