最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - How can I save the 32x32 icon from a .ico file that has the highest color depth possible as a .png using Pillow? - Stac

programmeradmin5浏览0评论

I'm trying to extract and save the 32x32 icon from a .ico file that contains multiple icons with multiple sizes and color depths using Pillow. The 32x32 icon is available in the following color depths: 32-bit, 8-bit and 4-bit.

I tried opening the icon file using Image.open(), then set its size to 32x32, and then save it as a .png file. I expect to get the icon with the highest color depth possible, but I'm getting the one with the lowest color depth possible.

Here's a minimal, reproducible example:

from PIL import Image

icon = Image.open("icon.ico")
icon.size = (32, 32)
icon.save("icon.png")

I'm expecting to get this:

But, I'm getting this:

You can get the .ico file here: .ico/file

I also tried looking for similar questions on the internet, but I didn't find anything.

Is there a way I can tell Pillow to extract the 32x32 icon from a .ico file at the highest color depth possible without modifying my .ico file to exclude icons with lower color depths?

I'm trying to extract and save the 32x32 icon from a .ico file that contains multiple icons with multiple sizes and color depths using Pillow. The 32x32 icon is available in the following color depths: 32-bit, 8-bit and 4-bit.

I tried opening the icon file using Image.open(), then set its size to 32x32, and then save it as a .png file. I expect to get the icon with the highest color depth possible, but I'm getting the one with the lowest color depth possible.

Here's a minimal, reproducible example:

from PIL import Image

icon = Image.open("icon.ico")
icon.size = (32, 32)
icon.save("icon.png")

I'm expecting to get this:

But, I'm getting this:

You can get the .ico file here: https://www.mediafire/file/uls693wvjn3njqa/icon.ico/file

I also tried looking for similar questions on the internet, but I didn't find anything.

Is there a way I can tell Pillow to extract the 32x32 icon from a .ico file at the highest color depth possible without modifying my .ico file to exclude icons with lower color depths?

Share Improve this question edited Feb 17 at 16:12 Valer asked Feb 16 at 23:30 ValerValer 731 silver badge6 bronze badges 2
  • please provide us with the .ico image. – Mohammed Almalki Commented Feb 16 at 23:36
  • @MohammedAlmalki You can get the .ico file here: mediafire/file/uls693wvjn3njqa/icon.ico/file – Valer Commented Feb 17 at 16:13
Add a comment  | 

2 Answers 2

Reset to default 3

WHile an ICO image loaded in PIL provide access to the individual images through the img.ico.frame call, there is one problem: upon loading, PIL will convert all loaded individual frames which are indexed into the RGBA format.

Fortunately, it will preserve a bpp attribute listing the original bitcount for each frame in a headers list stored in the img.ico.entry attribute.

Which means a small function which iterates the frame headers can find the needed information:

from PIL import Image

def get_max_bpp(ico, size=(32,32)):
    frames = [(index, header, ico.ico.frame(index))
        for index, header in enumerate(icon.ico.entry) 
        if header.width==size[0] and header.height == size[1]
    ] 
    frames.sort(key=lambda frame_info: frame_info[1].bpp, reverse=True)
    return frames[0][2]


icon = Image.open("icon.ico")

max_32 = get_max_bpp(icon)
max_32.save("icon.png")

So, a straight look at the .mode attribute of each frame won't help - all will show up as RGBA (at least for an ICO file which contains at least one 24 or 32bit frame. I had not tested with a file with indexed-only frames).

Your file contains your icon at 13 different sizes. You can tell that with ImageMagick like this:

magick identify icon.ico
icon.ico[0] ICO 32x32 32x32+0+0 4-bit sRGB 0.000u 0:00.003
icon.ico[1] ICO 16x16 16x16+0+0 4-bit sRGB 0.000u 0:00.002
icon.ico[2] ICO 48x48 48x48+0+0 8-bit sRGB 0.000u 0:00.002
icon.ico[3] ICO 32x32 32x32+0+0 8-bit sRGB 0.000u 0:00.002
icon.ico[4] ICO 16x16 16x16+0+0 8-bit sRGB 0.000u 0:00.002
icon.ico[5] PNG 256x256 256x256+0+0 8-bit sRGB 13527B 0.000u 0:00.002
icon.ico[6] ICO 64x64 64x64+0+0 8-bit sRGB 0.000u 0:00.002
icon.ico[7] ICO 48x48 48x48+0+0 8-bit sRGB 0.000u 0:00.001
icon.ico[8] ICO 40x40 40x40+0+0 8-bit sRGB 0.000u 0:00.001
icon.ico[9] ICO 32x32 32x32+0+0 8-bit sRGB 0.000u 0:00.000
icon.ico[10] ICO 24x24 24x24+0+0 8-bit sRGB 0.000u 0:00.000
icon.ico[11] ICO 20x20 20x20+0+0 8-bit sRGB 0.000u 0:00.000
icon.ico[12] ICO 16x16 16x16+0+0 8-bit sRGB 65021B 0.000u 0:00.000

When you open it with Pillow, you will get the highest (spatial) resolution, i.e. the 256x256 version.

If you want it at a different size, you will need to resize it:

from PIL import Image

im = Image.open('icon.ico')

# Check what Mark said is true
print(im)
# <PIL.IcoImagePlugin.IcoImageFile image mode=RGBA size=256x256 at 0x133D9AB10>

# Make 32x32 version
im32x32 = im.resize((32,32))

Note that you should use NEAREST NEIGHBOUR resampling when resizing if you do not wish to introduce new colours into your palette.

im32x32 = im.resize((32,32), Image.Resampling.NEAREST)

If you would like ImageMagick to tell you the scene/frame number, dimensions and number of unique colours in each icon in your file, use:

identify -format "%s %G %k\n" icon.ico 
0 32x32 10
1 16x16 10
2 48x48 253
3 32x32 190
4 16x16 115
5 256x256 1849
6 64x64 696
7 48x48 538
8 40x40 483
9 32x32 382
10 24x24 262
11 20x20 226
12 16x16 171

You can then extract icon 5 and save as a PNG with:

magick icon.ico[5] MostColours.png

Note that all ImageMagick operations I demonstrate above can be done equally with wand which is a Python binding to ImageMagick.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论