בדיוק לפני כמה זמן הייתי צריך לכתוב קוד שמחלץ תמונה ממוזערת מקובץ וידיאו, אז כתבתי את זה (וזה מתאים לכל סוגי הקבצים, גם לכוננים), היתרון שאפשר לקבל את התמונה בגודל שתרצה ועם עוד enum של אפשרויות.
זה הקוד:
public static class Shell
{
private static readonly Guid _s_imageFactoryShellId = new("BCC18B79-BA16-442F-80C4-8A59C30C463B");
public static byte[] GetImage(string path, ImageSize size, ShellItemGetImageOptions options)
{
if (OperatingSystem.IsWindows())
{
if (SHCreateItemFromParsingName(path, 0, _s_imageFactoryShellId, out var imageFactory) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (imageFactory.GetImage(size, (int)options, out var hBitmap) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try
{
using var stream = new MemoryStream();
var bitmap = Image.FromHbitmap(hBitmap);
bitmap.Save(stream, ImageFormat.Jpeg);
return stream.ToArray();
}
finally
{
DeleteObject(hBitmap);
}
}
throw new PlatformNotSupportedException();
}
}
public enum ShellItemGetImageOptions
{
ResizeToFit = 0,
BiggerSizeOk = 1,
MemoryOnly = 2,
IconOnly = 4,
ThumbnailOnly = 8,
InCacheOnly = 0x10,
CropToSquare = 0x20,
WideThumbnails = 0x40,
IconBackground = 0x80,
ScaleUp = 0x100
}
public readonly struct ImageSize(int width, int height)
{
public int Width { get; } = width;
public int Height { get; } = height;
}
internal static partial class Unmanaged
{
[GeneratedComInterface]
[Guid("BCC18B79-BA16-442F-80C4-8A59C30C463B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface IShellItemImageFactory
{
[PreserveSig]
int GetImage(ImageSize size, int flags, out nint hBitmap);
}
[LibraryImport("Shell32", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
public static partial int SHCreateItemFromParsingName(string pszPath, nint pbc, Guid riid, out IShellItemImageFactory ppv);
[LibraryImport("Gdi32", SetLastError = true)]
public static partial int DeleteObject(nint hObject);
}
נ.ב.
זה הקוד הבסיסי, אפשר לשנות ולהתאים אותו למה שאתה צריך.
לא בדקתי אם זה עובד גם על מערכות windows יותר ישנות.
הקוד תואם ל NativeAOT (אם תשתמש בו בעתיד)
לא יודע אם הקוד הזה יעבוד ב net-framework.