// 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. using System; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using Common.ComInterlop; using Common.Utilities; using Windows.Data.Pdf; using Windows.Storage.Streams; namespace Microsoft.PowerToys.ThumbnailHandler.Pdf { /// /// PDF Thumbnail Provider. /// public class PdfThumbnailProvider { public PdfThumbnailProvider(string filePath) { FilePath = filePath; Stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); } /// /// Gets the file path to the file creating thumbnail for. /// public string FilePath { get; private set; } /// /// Gets the stream object to access file. /// public Stream Stream { get; private set; } /// /// The maximum dimension (width or height) thumbnail we will generate. /// private const uint MaxThumbnailSize = 10000; /// /// Generate thumbnail bitmap for provided Pdf file/stream. /// /// Maximum thumbnail size, in pixels. /// Generated bitmap public Bitmap GetThumbnail(uint cx) { if (cx == 0 || cx > MaxThumbnailSize) { return null; } if (global::PowerToys.GPOWrapper.GPOWrapper.GetConfiguredPdfThumbnailsEnabledValue() == global::PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) { // GPO is disabling this utility. return null; } using var memStream = new MemoryStream(); this.Stream.CopyTo(memStream); memStream.Position = 0; // AsRandomAccessStream() extension method from System.Runtime.WindowsRuntime var pdf = PdfDocument.LoadFromStreamAsync(memStream.AsRandomAccessStream()).GetAwaiter().GetResult(); if (pdf.PageCount > 0) { using var page = pdf.GetPage(0); var image = PageToImage(page, cx); using Bitmap thumbnail = new Bitmap(image); return (Bitmap)thumbnail.Clone(); } return null; } /// /// Transform the PdfPage to an Image. /// /// The page to transform to an Image. /// The height of the page. /// An object of type private static Image PageToImage(PdfPage page, uint height) { Image imageOfPage; using var stream = new InMemoryRandomAccessStream(); page.RenderToStreamAsync(stream, new PdfPageRenderOptions() { DestinationHeight = height, }).GetAwaiter().GetResult(); imageOfPage = Image.FromStream(stream.AsStream()); return imageOfPage; } } }