[Peek] show thumbnail and fallback to icon on unsupported files (#27979)

This commit is contained in:
Pedro Lamas
2023-08-24 11:10:45 +01:00
committed by GitHub
parent efee03eb99
commit c1316fc9f8
3 changed files with 41 additions and 14 deletions

View File

@@ -17,12 +17,23 @@ namespace Peek.FilePreviewer.Previewers.Helpers
{
public static async Task<BitmapSource> GetBitmapFromHBitmapAsync(IntPtr hbitmap, bool isSupportingTransparency, CancellationToken cancellationToken)
{
Bitmap? bitmap = null;
try
{
var bitmap = Image.FromHbitmap(hbitmap);
if (isSupportingTransparency)
bitmap = Image.FromHbitmap(hbitmap);
cancellationToken.ThrowIfCancellationRequested();
if (isSupportingTransparency && bitmap.PixelFormat == PixelFormat.Format32bppRgb)
{
bitmap.MakeTransparent();
var bitmapRectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
var bitmapData = bitmap.LockBits(bitmapRectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);
var transparentBitmap = new Bitmap(bitmapData.Width, bitmapData.Height, bitmapData.Stride, PixelFormat.Format32bppArgb, bitmapData.Scan0);
bitmap.Dispose();
bitmap = transparentBitmap;
}
var bitmapImage = new BitmapImage();
@@ -41,6 +52,8 @@ namespace Peek.FilePreviewer.Previewers.Helpers
}
finally
{
bitmap?.Dispose();
// delete HBitmap to avoid memory leaks
NativeMethods.DeleteObject(hbitmap);
}
@@ -50,8 +63,8 @@ namespace Peek.FilePreviewer.Previewers.Helpers
{
try
{
var icon = (Icon)Icon.FromHandle(hicon).Clone();
var bitmap = icon.ToBitmap();
using var icon = (Icon)Icon.FromHandle(hicon).Clone();
using var bitmap = icon.ToBitmap();
var bitmapImage = new BitmapImage();

View File

@@ -7,9 +7,7 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using Peek.Common;
using Peek.Common.Extensions;
using Peek.Common.Models;
namespace Peek.FilePreviewer.Previewers.Helpers
@@ -20,6 +18,16 @@ namespace Peek.FilePreviewer.Previewers.Helpers
private const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C93";
public static async Task<ImageSource?> GetIconAsync(string fileName, CancellationToken cancellationToken)
{
return await GetImageAsync(fileName, ThumbnailOptions.BiggerSizeOk | ThumbnailOptions.IconOnly, true, cancellationToken);
}
public static async Task<ImageSource?> GetThumbnailAsync(string fileName, CancellationToken cancellationToken)
{
return await GetImageAsync(fileName, ThumbnailOptions.ThumbnailOnly, true, cancellationToken);
}
public static async Task<ImageSource?> GetImageAsync(string fileName, ThumbnailOptions options, bool isSupportingTransparency, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(fileName))
{
@@ -28,6 +36,7 @@ namespace Peek.FilePreviewer.Previewers.Helpers
ImageSource? imageSource = null;
IShellItem? nativeShellItem = null;
IntPtr hbitmap = IntPtr.Zero;
try
{
@@ -40,16 +49,22 @@ namespace Peek.FilePreviewer.Previewers.Helpers
}
NativeSize large = new NativeSize { Width = 256, Height = 256 };
var options = ThumbnailOptions.BiggerSizeOk | ThumbnailOptions.IconOnly;
HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(large, options, out IntPtr hbitmap);
HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(large, options, out hbitmap);
cancellationToken.ThrowIfCancellationRequested();
imageSource = hr == HResult.Ok ? await BitmapHelper.GetBitmapFromHBitmapAsync(hbitmap, true, cancellationToken) : null;
imageSource = hr == HResult.Ok ? await BitmapHelper.GetBitmapFromHBitmapAsync(hbitmap, isSupportingTransparency, cancellationToken) : null;
hbitmap = IntPtr.Zero;
}
finally
{
if (hbitmap != IntPtr.Zero)
{
NativeMethods.DeleteObject(hbitmap);
}
if (nativeShellItem != null)
{
Marshal.ReleaseComObject(nativeShellItem);

View File

@@ -4,11 +4,9 @@
using System;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Media.Imaging;
using Peek.Common.Extensions;
@@ -99,7 +97,8 @@ namespace Peek.FilePreviewer.Previewers
{
cancellationToken.ThrowIfCancellationRequested();
var iconBitmap = await IconHelper.GetIconAsync(Item.Path, cancellationToken);
var iconBitmap = await IconHelper.GetThumbnailAsync(Item.Path, cancellationToken)
?? await IconHelper.GetIconAsync(Item.Path, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();