📜 ⬆️ ⬇️

Build ICO file with icons in PNG format using FASM

Sometimes I write small programs in C ++, and often it turns out that the program icon “weighs” more than the program itself. It also happened when writing Sound Keeper : the program is 14KB, the icon is 16 × 16 + 32 × 32 + 48 × 48 pixels - 15KB. What a waste! Fortunately, it turned out that Windows (starting with Vista) supports PNG inside ICO. This is exactly what you need! But for some reason there was no program that would allow most to optimize PNG files and build an ICO file from them. Since ICO files have a very simple format, we will assemble it using FASM . This non-standard use of the "flat" assembler shows that it can be used in the most unexpected situations, and it works!

Let's get started


1. Create images for icons in PNG format. For example, we will make two images with sizes of 16 × 16 and 32 × 32 pixels. Save them in the icon16.png and icon32.png files, respectively. Optimize to your taste with your favorite tools.

2. Following the documentation , create the file icopng.asm with something like this:
dw 0 ; reserved, must be 0 dw 1 ; icon type, must be 1 dw 2 ; number of images in file ; 1st icon header db 32 ; width db 32 ; height db 0 ; no color palette db 0 ; reserved, must be 0 dw 1 ; planes dw 32 ; bits per pixel dd icon32_end-icon32_start ; length dd icon32_start ; offset ; 2nd icon header db 16 ; width db 16 ; height db 0 ; no color palette db 0 ; reserved, must be 0 dw 1 ; planes dw 32 ; bits per pixel dd icon16_end-icon16_start ; length dd icon16_start ; offset ; 1st icon body icon32_start: file 'icon32.png' icon32_end: ; 2nd icon body icon16_start: file 'icon16.png' icon16_end: 
It was experimentally established that it is better to connect the images in the reverse order, from large to smaller ones. When adding more icons, do not forget to correct the field with the total number of images in the header. An error here can lead to unexpected consequences.

3. Build the icon with the command:
 fasm icopng.asm icopng.ico 

4. As a result, we received an icon with images in PNG format. Instead of 15KB, I got a file of only 3KB in size.
')

PNG8 support with alpha channel


According to scanty documentation , only PNG32 images should be supported. In practice, the system easily decodes PNG8 images even with an alpha channel. Unless only the Windows image viewer does not understand PNG8 in icons, apparently it does not use system functions for decoding and drawing the icon. But you are not making icons to look at them in the image viewer, right? :) Everywhere, where standard Windows functions are used for loading and displaying the icon - PNG8 with alpha channel is displayed in the same way as PNG32.

Important note: even PNG8 images in the header should have no palette, because the PNG decoder at the output gives TrueColor an image with an alpha channel where any colors can occur. That is, in the example you will only need to change the width and height fields. The rest is not necessary to touch.

Problem in PNG system decoder


PNG support for icons in Windows Vista and later is used by default to save only large 256 × 256 icons. Apparently, PNG support inside the ICO was poorly tested, so there are some problems and workarounds for them.

Some kind of error was detected in the PNG system decoder, which is why a particular icon file may not appear correctly in some places (for example, in the file properties dialog). Moreover, the minimum change in compression parameters easily solves the problem.

I did a little research on the icon file , which was incorrectly displayed in the file properties dialog. The DrawIconEx system function has 3 icon drawing modes: DI_NORMAL (with alpha), DI_IMAGE (without alpha), and DI_MASK (mask only).



In this image you can see how the same icon was rendered in different modes, and under the name RESULT what this icon looks like in the file properties. It can be seen that in DI_NORMAL and DI_IMAGE modes the system draws the icon correctly. However, in the DI_MASK mode, the mask computed with a view to compatibility is somehow shifted three pixels to the right, and some garbage appeared in the first column of pixels — probably due to incorrect buffer handling. The icon in the file properties, as you can see, has serious artifacts just in the shape of an incorrect mask. It would be nice to report this problem to the Microsoft developers, but unfortunately, I did not find any open bug tracker.

PNG Optimization Tips


I recommend using the Color Quantizer program to convert files from PNG32 to PNG8 with alpha channel. The resulting file, among other things, is compressed by a very efficient algorithm, so usually additional optimization is not required.



In the screenshot, a block is highlighted in red with a choice of the number of colors and a coefficient of allowable quantization errors. If the above problem occurs with incorrect display of the icon in the file properties dialog, simply change the quantization parameters. For example, slightly change the value of the ratio of allowable quantization errors.

That's all


Now your compact programs can be with colorful icons of all necessary sizes. No need to sacrifice transparency or the number of options for the icon. There is only one drawback - users of Windows XP will not see such an icon. But if you consider that the official support for Windows XP has long been over, and fewer computers are running this operating system, then everything is not so bad. Moreover, the authors of small programs often do not add an icon at all to save.

Source: https://habr.com/ru/post/247425/


All Articles