BgcodeThumbnailProvider.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 using System.Drawing.Drawing2D; 5 using System.Drawing.Imaging; 6 7 using Microsoft.PowerToys.FilePreviewCommon; 8 9 namespace Microsoft.PowerToys.ThumbnailHandler.Bgcode 10 { 11 /// <summary> 12 /// Binary G-code Thumbnail Provider. 13 /// </summary> 14 public class BgcodeThumbnailProvider 15 { 16 public BgcodeThumbnailProvider(string filePath) 17 { 18 FilePath = filePath; 19 Stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); 20 } 21 22 /// <summary> 23 /// Gets the file path to the file creating thumbnail for. 24 /// </summary> 25 public string FilePath { get; private set; } 26 27 /// <summary> 28 /// Gets the stream object to access file. 29 /// </summary> 30 public Stream Stream { get; private set; } 31 32 /// <summary> 33 /// The maximum dimension (width or height) thumbnail we will generate. 34 /// </summary> 35 private const uint MaxThumbnailSize = 10000; 36 37 /// <summary> 38 /// Reads the Binary G-code content searching for thumbnails and returns the largest. 39 /// </summary> 40 /// <param name="reader">The BinaryReader instance for the Binary G-code content.</param> 41 /// <param name="cx">The maximum thumbnail size, in pixels.</param> 42 /// <returns>A thumbnail extracted from the Binary G-code content.</returns> 43 public static Bitmap GetThumbnail(BinaryReader reader, uint cx) 44 { 45 if (cx > MaxThumbnailSize || reader == null || reader.BaseStream.Length == 0) 46 { 47 return null; 48 } 49 50 Bitmap thumbnail = null; 51 52 try 53 { 54 var bgcodeThumbnail = BgcodeHelper.GetBestThumbnail(reader); 55 56 thumbnail = bgcodeThumbnail?.GetBitmap(); 57 } 58 catch (Exception) 59 { 60 // TODO: add logger 61 } 62 63 if (thumbnail != null && ( 64 ((thumbnail.Width != cx || thumbnail.Height > cx) && (thumbnail.Height != cx || thumbnail.Width > cx)) || 65 thumbnail.PixelFormat != PixelFormat.Format32bppArgb)) 66 { 67 // We are not the appropriate size for caller. Resize now while 68 // respecting the aspect ratio. 69 float scale = Math.Min((float)cx / thumbnail.Width, (float)cx / thumbnail.Height); 70 int scaleWidth = (int)(thumbnail.Width * scale); 71 int scaleHeight = (int)(thumbnail.Height * scale); 72 thumbnail = ResizeImage(thumbnail, scaleWidth, scaleHeight); 73 } 74 75 return thumbnail; 76 } 77 78 /// <summary> 79 /// Resize the image with high quality to the specified width and height. 80 /// </summary> 81 /// <param name="image">The image to resize.</param> 82 /// <param name="width">The width to resize to.</param> 83 /// <param name="height">The height to resize to.</param> 84 /// <returns>The resized image.</returns> 85 public static Bitmap ResizeImage(Image image, int width, int height) 86 { 87 if (width <= 0 || 88 height <= 0 || 89 width > MaxThumbnailSize || 90 height > MaxThumbnailSize || 91 image == null) 92 { 93 return null; 94 } 95 96 Bitmap destImage = new Bitmap(width, height, PixelFormat.Format32bppArgb); 97 98 destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); 99 100 using (var graphics = Graphics.FromImage(destImage)) 101 { 102 graphics.CompositingMode = CompositingMode.SourceCopy; 103 graphics.CompositingQuality = CompositingQuality.HighQuality; 104 graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 105 graphics.SmoothingMode = SmoothingMode.HighQuality; 106 graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; 107 108 graphics.DrawImage(image, 0, 0, width, height); 109 } 110 111 image.Dispose(); 112 113 return destImage; 114 } 115 116 /// <summary> 117 /// Generate thumbnail bitmap for provided Bgcode file/stream. 118 /// </summary> 119 /// <param name="cx">Maximum thumbnail size, in pixels.</param> 120 /// <returns>Generated bitmap</returns> 121 public Bitmap GetThumbnail(uint cx) 122 { 123 if (cx == 0 || cx > MaxThumbnailSize) 124 { 125 return null; 126 } 127 128 if (global::PowerToys.GPOWrapper.GPOWrapper.GetConfiguredBgcodeThumbnailsEnabledValue() == global::PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) 129 { 130 // GPO is disabling this utility. 131 return null; 132 } 133 134 using (var reader = new BinaryReader(this.Stream)) 135 { 136 Bitmap thumbnail = GetThumbnail(reader, cx); 137 if (thumbnail != null && thumbnail.Size.Width > 0 && thumbnail.Size.Height > 0) 138 { 139 return thumbnail; 140 } 141 } 142 143 return null; 144 } 145 } 146 }