Fix icon entry selection (dotnet/corefx#41048)
authorJeremy Kuhne <jkuhne@microsoft.com>
Thu, 12 Sep 2019 20:21:59 +0000 (13:21 -0700)
committerGitHub <noreply@github.com>
Thu, 12 Sep 2019 20:21:59 +0000 (13:21 -0700)
* 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/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.cs
src/libraries/System.Drawing.Common/tests/IconTests.cs

index b354d4d..18e9132 100644 (file)
@@ -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;
                         }
index 51b7642..6263f93 100644 (file)
@@ -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;
+                        }
+                    }
+                }
+            }
+        }
     }
 }