Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Peek] add extra logic to properly render PNG files with transparency #22613

Merged
merged 6 commits into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace Peek.FilePreviewer.Previewers
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.UI.Xaml.Media.Imaging;
using Peek.Common;
using Peek.Common.Models;

Expand Down Expand Up @@ -59,5 +61,32 @@ public static HResult GetThumbnail(string filename, out IntPtr hbitmap, NativeSi

return hr;
}

public static async Task<BitmapImage?> GetThumbnailAsync(string path, uint size)
{
BitmapImage? bitmapImage = null;

// preview image
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(path);
if (file == null)
{
return bitmapImage;
}

var imageStream = await file.GetThumbnailAsync(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the performance on this? If I recall correctly, the first iteration of the migration used the Windows Storage API and it was much slower than what we have currently

Windows.Storage.FileProperties.ThumbnailMode.SingleItem,
size,
Windows.Storage.FileProperties.ThumbnailOptions.None);

if (imageStream == null)
{
return bitmapImage;
}

bitmapImage = new BitmapImage();
bitmapImage.SetSource(imageStream);

return bitmapImage;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace Peek.FilePreviewer.Previewers
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
using Peek.Common;
using Peek.Common.Extensions;
Expand Down Expand Up @@ -233,7 +232,8 @@ public static bool IsFileTypeSupported(string fileExt)
".jif",
".jpeg",
".jpe",
".png",

// ".png", // The current ImagePreviewer logic does not support transparency so PNG has it's own logic in PngPreviewer
".tif",
".tiff",
".dib",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Peek.FilePreviewer.Previewers
{
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Media.Imaging;
using Peek.Common;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using File = Peek.Common.Models.File;

public partial class PngPreviewer : ObservableObject, IBitmapPreviewer
{
private readonly uint _png_image_size = 1280;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsPreviewLoaded))]
private BitmapSource? preview;

[ObservableProperty]
private PreviewState state;

public PngPreviewer(File file)
{
File = file;
Dispatcher = DispatcherQueue.GetForCurrentThread();

PropertyChanged += OnPropertyChanged;
}

public bool IsPreviewLoaded => preview != null;

private File File { get; }

private DispatcherQueue Dispatcher { get; }

private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

private CancellationToken CancellationToken => _cancellationTokenSource.Token;

public void Dispose()
{
_cancellationTokenSource.Dispose();
GC.SuppressFinalize(this);
}

public async Task<Size> GetPreviewSizeAsync()
{
var propertyImageSize = await PropertyHelper.GetImageSize(File.Path);
if (propertyImageSize != Size.Empty)
{
return propertyImageSize;
}

return await WICHelper.GetImageSize(File.Path);
}

public async Task LoadPreviewAsync()
{
State = PreviewState.Loading;

var previewTask = LoadPreviewImageAsync();

await Task.WhenAll(previewTask);

if (Preview == null)
{
State = PreviewState.Error;
}
}

public static bool IsFileTypeSupported(string fileExt)
{
return fileExt == ".png" ? true : false;
}

private void OnPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Preview))
{
if (Preview != null)
{
State = PreviewState.Loaded;
}
}
}

private Task LoadPreviewImageAsync()
{
var thumbnailTCS = new TaskCompletionSource();
Dispatcher.TryEnqueue(async () =>
{
if (CancellationToken.IsCancellationRequested)
{
_cancellationTokenSource = new CancellationTokenSource();
return;
}

Preview = await ThumbnailHelper.GetThumbnailAsync(File.Path, _png_image_size);

thumbnailTCS.SetResult();
});

return thumbnailTCS.Task;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ public class PreviewerFactory
{
public IPreviewer Create(File file)
{
if (ImagePreviewer.IsFileTypeSupported(file.Extension))
if (PngPreviewer.IsFileTypeSupported(file.Extension))
{
return new PngPreviewer(file);
}
else if (ImagePreviewer.IsFileTypeSupported(file.Extension))
{
return new ImagePreviewer(file);
}
Expand Down