<PackageReference Include="System.Drawing.Common" Version="10.0.0-preview.6.25358.103" />

DpiHelper

static class DpiHelper
using System.Diagnostics.CodeAnalysis; using System.Drawing.Drawing2D; using System.Runtime.CompilerServices; using Windows.Win32; using Windows.Win32.Graphics.Gdi; namespace System.Drawing { [NullableContext(1)] [Nullable(0)] internal static class DpiHelper { private const double LogicalDpi = 96; private static bool s_isInitialized; private static double s_deviceDpiX = 96; private static double s_deviceDpiY = 96; private static double s_logicalToDeviceUnitsScalingFactorX; private static double s_logicalToDeviceUnitsScalingFactorY; private static InterpolationMode s_interpolationMode = InterpolationMode.Invalid; private static double LogicalToDeviceUnitsScalingFactorX { get { if (s_logicalToDeviceUnitsScalingFactorX == 0) { Initialize(); s_logicalToDeviceUnitsScalingFactorX = s_deviceDpiX / 96; } return s_logicalToDeviceUnitsScalingFactorX; } } private static double LogicalToDeviceUnitsScalingFactorY { get { if (s_logicalToDeviceUnitsScalingFactorY == 0) { Initialize(); s_logicalToDeviceUnitsScalingFactorY = s_deviceDpiY / 96; } return s_logicalToDeviceUnitsScalingFactorY; } } private static InterpolationMode InterpolationMode { get { if (s_interpolationMode == InterpolationMode.Invalid) { int num = (int)Math.Round(LogicalToDeviceUnitsScalingFactorX * 100); if (num % 100 == 0) s_interpolationMode = InterpolationMode.NearestNeighbor; else if (num < 100) { s_interpolationMode = InterpolationMode.HighQualityBilinear; } else { s_interpolationMode = InterpolationMode.HighQualityBicubic; } } return s_interpolationMode; } } public static bool IsScalingRequired { get { Initialize(); if (s_deviceDpiX == 96) return s_deviceDpiY != 96; return true; } } private static void Initialize() { if (!s_isInitialized) { GetDcScope scope = GetDcScope.ScreenDC; try { s_deviceDpiX = (double)PInvokeCore.GetDeviceCaps((HDC)ref scope, GET_DEVICE_CAPS_INDEX.LOGPIXELSX); s_deviceDpiY = (double)PInvokeCore.GetDeviceCaps((HDC)ref scope, GET_DEVICE_CAPS_INDEX.LOGPIXELSY); s_isInitialized = true; } finally { scope.Dispose(); } } } private static Bitmap ScaleBitmapToSize(Bitmap logicalImage, Size deviceImageSize) { Bitmap bitmap = new Bitmap(deviceImageSize.Width, deviceImageSize.Height, logicalImage.PixelFormat); using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.InterpolationMode = InterpolationMode; Size size = logicalImage.Size; float width = (float)size.Width; size = logicalImage.Size; RectangleF srcRect = new RectangleF(0, 0, width, (float)size.Height); RectangleF destRect = new RectangleF(0, 0, (float)deviceImageSize.Width, (float)deviceImageSize.Height); srcRect.Offset(-0.5, -0.5); graphics.DrawImage(logicalImage, destRect, srcRect, GraphicsUnit.Pixel); return bitmap; } } private static Bitmap CreateScaledBitmap(Bitmap logicalImage) { Size deviceImageSize = LogicalToDeviceUnits(logicalImage.Size); return ScaleBitmapToSize(logicalImage, deviceImageSize); } public static int LogicalToDeviceUnitsX(int value) { return (int)Math.Round(LogicalToDeviceUnitsScalingFactorX * (double)value); } public static int ScaleToInitialSystemDpi(int value) { return (int)Math.Round(LogicalToDeviceUnitsScalingFactorY * (double)value); } public static Size LogicalToDeviceUnits(Size logicalSize) { return new Size(LogicalToDeviceUnitsX(logicalSize.Width), ScaleToInitialSystemDpi(logicalSize.Height)); } [NullableContext(2)] [return: NotNullIfNotNull("logicalImage")] public static Bitmap CreateResizedBitmap(Bitmap logicalImage, Size targetImageSize) { if (logicalImage == null) return null; return ScaleBitmapToSize(logicalImage, targetImageSize); } [NullableContext(2)] public static void ScaleBitmapLogicalToDevice([NotNullIfNotNull("logicalBitmap")] ref Bitmap logicalBitmap) { if (logicalBitmap != null) { Bitmap bitmap = CreateScaledBitmap(logicalBitmap); logicalBitmap.Dispose(); logicalBitmap = bitmap; } } } }