From 2fea302654c9a49b0509377482346b0973a9ec79 Mon Sep 17 00:00:00 2001 From: Jeremy Kuhne Date: Thu, 12 Sep 2019 13:21:59 -0700 Subject: [PATCH] Fix icon entry selection (dotnet/corefx#41048) * We weren't checking the color depth properly when choosing an icon entry to extract from an icon file. Fix, and add a test. Commit migrated from https://github.com/dotnet/corefx/commit/3a5b86f21b498067fa920842adaf228e39b6e35a --- .../src/System/Drawing/Icon.Windows.cs | 2 +- .../System.Drawing.Common/tests/IconTests.cs | 52 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs index b354d4d..18e9132 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs @@ -525,7 +525,7 @@ namespace System.Drawing int thisDelta = Math.Abs(entry.bWidth - width) + Math.Abs(entry.bHeight - height); if ((thisDelta < bestDelta) || - (thisDelta == bestDelta && (0 <= s_bitDepth && 0 > _bestBitDepth || _bestBitDepth > s_bitDepth && 0 < _bestBitDepth))) + (thisDelta == bestDelta && (iconBitDepth <= s_bitDepth && iconBitDepth > _bestBitDepth || _bestBitDepth > s_bitDepth && iconBitDepth < _bestBitDepth))) { fUpdateBestFit = true; } diff --git a/src/libraries/System.Drawing.Common/tests/IconTests.cs b/src/libraries/System.Drawing.Common/tests/IconTests.cs index 51b7642..6263f93 100644 --- a/src/libraries/System.Drawing.Common/tests/IconTests.cs +++ b/src/libraries/System.Drawing.Common/tests/IconTests.cs @@ -26,6 +26,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing.Imaging; using System.IO; +using System.Reflection; using System.Runtime.InteropServices; using Microsoft.DotNet.RemoteExecutor; using Xunit; @@ -827,5 +828,56 @@ namespace System.Drawing.Tests } } } + + [ConditionalFact(Helpers.IsDrawingSupported)] + public void CorrectColorDepthExtracted() + { + using (var stream = File.OpenRead(Helpers.GetTestBitmapPath("pngwithheight_icon.ico"))) + { + using (var icon = new Icon(stream, new Size(32, 32))) + { + // The first 32x32 icon isn't 32 bit. Checking a few pixels that are in the 32 bit entry. + using (Bitmap bitmap = icon.ToBitmap()) + { + Assert.Equal(new Size(32, 32), bitmap.Size); + + int expectedBitDepth; + if (!PlatformDetection.IsWindows) + { + // The Unix implementation currently doesn't try to match the display, + // it will just pick the highest color depth when creating the bitmap. + // (see SaveBestSingleIcon()). + expectedBitDepth = 32; + } + else + { + string fieldName = PlatformDetection.IsFullFramework ? "bitDepth" : "s_bitDepth"; + FieldInfo fi = typeof(Icon).GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic); + expectedBitDepth = (int)fi.GetValue(null); + } + + // If the first icon entry was picked, the color would be black: 0xFF000000? + + switch (expectedBitDepth) + { + case 32: + Assert.Equal(0x879EE532u, (uint)bitmap.GetPixel(0, 0).ToArgb()); + Assert.Equal(0x661CD8B7u, (uint)bitmap.GetPixel(0, 31).ToArgb()); + break; + case 16: + case 8: + // There is no 16 bit 32x32 icon in this file, 8 will be picked + // as the closest match. + Assert.Equal(0x00000000u, (uint)bitmap.GetPixel(0, 0).ToArgb()); + Assert.Equal(0xFF000000u, (uint)bitmap.GetPixel(0, 31).ToArgb()); + break; + default: + Assert.False(true, $"Unexpected bitmap depth: {expectedBitDepth}"); + break; + } + } + } + } + } } } -- 2.7.4