Closed elachlan closed 1 month ago
@MichalStrehovsky here is a PR with all the ico files converted. It resulted in errors in ToolboxBitmapAttribute
, this pr just adds try catch to swallow those as there was a fallback mechanism already in place. But I suspect we can improve the code to check the file header to check its format to avoid the exception.
Winforms team might be able to help there.
Attention: Patch coverage is 82.60870%
with 12 lines
in your changes missing coverage. Please review.
Project coverage is 74.36247%. Comparing base (
0aa3a4d
) to head (3da25ab
). Report is 110 commits behind head on main.
@merriemcgaw Are embedded resources considered a part of the public API? Would a change like this be a breaking change?
Are embedded resources considered a part of the public API? Would a change like this be a breaking change?
No, it shouldn't be considered a breaking change. These may be helpful:
It resulted in errors in
ToolboxBitmapAttribute
, this pr just adds try catch to swallow those as there was a fallback mechanism already in place. But I suspect we can improve the code to check the file header to check its format to avoid the exception.
What were the errors? It feels like the code this is touching should already handle PNG. Icon.ToBitmap used to throw but support for this was added long time ago (there was even a breaking change notice because the compat bar on .NET Framework is so high that even "something throwing a non-sensical exception" to "something working" is a breaking change, but fortunately we don't have to worry about that here).
@LeafShi1 / @Olina-Zhang can your team please test this? The main test would be to open the new icon and compare it to the old icon. Also if you can trigger the CI to run the tests again that would be great.
/azp run
Thanks for taking this on @elachlan! I did a look through and compared the icons before/after change and AFAICT visually the icons look the same. I did, however, spot some differences when comparing sizes and perhaps some of them are expected:
colorDialog.ico
, RichEdit.ico
, RichTextBox.ico
, ShieldIcon.ico
, Close_left.ico
, Open_left.ico
, DummyNodeImage.ico
256_1.ico
and 256_2.ico
overflowButton.ico
, ToolBarGrip.ico
, OrderImages.ico
@lonitra thank you so much for reviewing these. How are you checking the bit depth and sizing?
@lonitra thank you so much for reviewing these. How are you checking the bit depth and sizing?
I had opened the icons in Visual Studio and there was a bar on the side that showed the sizing and bits
Thanks! When I run the ImageMagick Identify command I get different results. It says RichEdit.ico
is strangley 8bit before and after the conversion.
here is what it looks like from my VS Before: After:
VS seems to have issues displaying the original?
256_1.ico
is strange, 148x148
and 47x47
look corrupted when viewed in VS for me. The meta data exists in the original ico file, but with zero file size. 202x123
has a zero size but somehow works in the original and converted versions.
Before:
256_1.ico[0] PNG 505x308 505x308+0+0 8-bit sRGB 13030B 0.000u 0:00.009
256_1.ico[1] ICO 202x123 202x123+0+0 8-bit sRGB 0.000u 0:00.009
256_1.ico[2] PNG 707x431 707x431+0+0 8-bit sRGB 16711B 0.000u 0:00.005
256_1.ico[3] ICO 148x148 148x148+0+0 8-bit sRGB 0.000u 0:00.004
256_1.ico[4] PNG 606x370 606x370+0+0 8-bit sRGB 13120B 0.000u 0:00.002
256_1.ico[5] ICO 47x47 47x47+0+0 8-bit sRGB 0.000u 0:00.002
256_1.ico[6] PNG 808x492 808x492+0+0 8-bit sRGB 805702B 0.000u 0:00.000
After:
256_1.ico[0] PNG 505x308 505x308+0+0 8-bit sRGB 7339B 0.000u 0:00.004
256_1.ico[1] PNG 202x123 202x123+0+0 8-bit sRGB 2277B 0.000u 0:00.003
256_1.ico[2] PNG 707x431 707x431+0+0 8-bit sRGB 10520B 0.000u 0:00.003
256_1.ico[3] PNG 148x148 148x148+0+0 8-bit sRGB 1466B 0.000u 0:00.002
256_1.ico[4] PNG 606x370 606x370+0+0 8-bit sRGB 7745B 0.000u 0:00.001
256_1.ico[5] PNG 47x47 47x47+0+0 8-bit sRGB 449B 0.000u 0:00.001
256_1.ico[6] PNG 808x492 808x492+0+0 8-bit sRGB 40338B 0.000u 0:00.000
If I use Icon tool on the orginal:
--icon --index=1 --width=505 --height=308 --bit-depth=32 --palette-size=0
--icon --index=2 --width=202 --height=123 --bit-depth=32 --palette-size=0
--icon --index=3 --width=707 --height=431 --bit-depth=32 --palette-size=0
--icon --index=4 --width=404 --height=246 --bit-depth=32 --palette-size=0
--icon --index=5 --width=606 --height=370 --bit-depth=32 --palette-size=0
--icon --index=6 --width=303 --height=185 --bit-depth=32 --palette-size=0
--icon --index=7 --width=808 --height=492 --bit-depth=32 --palette-size=0
Edit:
ImageMagick
is misinterpreting the resolution, which is causing issues.
I'll do some more work on identifying making the conversion script more error tolerant and add some verification using icontool
.
I've raised an ImageMagick issue at: https://github.com/ImageMagick/ImageMagick/issues/7341
icotool
can extract some of the icons, but errors on a few. I'll put together a new script and push through the changes when I have it sorted.
Hi @elachlan, we tested this PR by checking all ico files in your repo: Icon-Resize branch and Winforms repo: Main branch to compare them, found following result:
@Olina-Zhang I think the designer issue will need to be looked at by the team. I don't have access to the source code for the designer.
ImageMagick are fixing one of the issues which should resolve some of the sizing corruption.
@merriemcgaw changing the underlying BMP format to PNG in the ICO files is a breaking change if a user is creating a bitmap directly instead of first creating an Icon. Are we sure that changing resources is not a breaking change?
@Olina-Zhang I think the designer issue will need to be looked at by the team. I don't have access to the source code for the designer.
If we didn't replace the binaries built from your PR, that issue doesn't repro.
ImageMagick fixed the sizing issue. So now the icons have appropriate sizes.
The bit depth is changed on purpose by ImageMagick to save space when there are limited colors in an image.
The artifacts we are seeing look like they are caused by icotool
. I am investigating how to use ImageMagick to combine the png files to the ico without converting back to bmp.
Looks like ImageMagick might not support PNG in ICO files because of specification reasons: https://github.com/ImageMagick/ImageMagick/issues/2394
@MichalStrehovsky could you live with bitmap based ICO files? Bitmap: ToolStripDropDown.ico 54kb->22kb PNG: 54kb->5kb
Looks like ImageMagick might not support PNG in ICO files because of specification reasons: ImageMagick/ImageMagick#2394
@MichalStrehovsky could you live with bitmap based ICO files? Bitmap: ToolStripDropDown.ico 54kb->22kb PNG: 54kb->5kb
In a blank WinForms app, we currently have 48 icons that take over 51 kB each (plus some smaller ones I'm not counting). That's 2.4 MB. A blank WinForms app with AOT and a couple size savings options is 9.2 MB. So these icons are more than 25% of the blank app. If we make them 15% of the blank app, it's certainly an improvement. Still feels a bit excessive. In other places (ASP.NET, Blazor, etc.) we jump on and try to fix anything above 1%.
First thing I'm getting from this is that the VS icon designer cannot be trusted (it shows various artifacts in both before and after versions). I'd ignore the VS icon designer completely and focus on differences that matter - e.g. load the icons as a .NET Icon
and save everything as a Bitmap
. Compare the Bitmap
s. Then look if we can fix the bug where someone tries to open an icon as a Bitmap (the bug you're working around in the code changes here) - can Bitmap detect trying to open an icon and instead open it as Icon and call ToBitmap on it (i.e. move the workaround from there to Bitmap - I assume that would fix the designer issue)?
If the above fails or we don't want to go in that direction - can we instead get the icons out of the app? Then it doesn't matter how big they are. E.g. are these Designer icons? Could they be moved to the Designer assembly? Or could we instruct trimming to drop them based on some condition? What are they used for?
15% leaves a lot on the table. Last week I converted one of my WinForms apps to Native AOT. It's a fully functional and useful app. These icons would still constitute 10% of the app even if we cut their size in half because the whole app size was a little over 10 MB.
Thinking about it more, even in the best case 4+% of the executable size would be icons. It might be the best to look for ways to trim these out of the app. A 4% size saving is still pretty interesting. Assuming these are actually not normally needed - understanding what they are used for would be the best.
@Olina-Zhang could your team please report the VS artifact issue?
I'll whip up a quick program to do the icon to bitmap conversion and see what before/after renders out to.
With regards to trimming out resources, I am unsure how the trimmer works or how the compiler handles resources. Someone much more skilled them myself would need to investigate that.
@Olina-Zhang could your team please report the VS artifact issue?
You mean this problem I listed: An exception pops up when adding ToolStrip/MenuStrip/StatusStrip/ContextMenuStrip control from toolBox to form designer? I'm not quite sure what you mean. Do you request a details about how to repro it or others?
Sorry about that. Can you please report the issue when viewing the existing icons in visual studio? Visual Studio should display the icons properly.
You mean open a Winforms designer bug in Winforms designer repo? That issue just reproduces when replaced these three binaries: System.Drawing.Common.dll, System.Windows.Forms.Design.dll and System.Windows.Forms.dll built from this PR, I am not sure if our testing is a valid validation.
The icon display issue in visual studio. Not the exception. I am unsure if winforms designer handles viewing/editing icon files.
Haha, I see the problem you're referring to. I will open an issue for Visual Studio.
Opened an internal VS artifact issue: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2067266.
With regards to trimming out resources, I am unsure how the trimmer works or how the compiler handles resources. Someone much more skilled them myself would need to investigate that.
A couple options, not sure which one is applicable.
Did another quick test, these artifacts are VS specific and don't show if using a browser to display the ico file:
Additionally, if I convert the ico to bmp via .NET and open in VS it displays fine:
@merriemcgaw changing the underlying BMP format to PNG in the ICO files is a breaking change if a user is creating a bitmap directly instead of first creating an Icon. Are we sure that changing resources is not a breaking change?
I am concerned, to be honest. @merriemcgaw.
@KlausLoeffelmann I think we can adjust Bitmap to check the streams leading bytes to establish what file type it is then create the bitmap accordingly.
Changes to
ToolboxBitmapAttribute
were to avoid errors when a bitmap was expected but the icon file was a png based icon. The try catch method was used elsewhere in the class to avoid similar errors.Used the method outlined in the linked issue and wrote the following python script to automate:
Microsoft Reviewers: Open in CodeFlow