[英]How to reduce the palette of PNG image in Python/Pillow to the colors being really used?
在使用以下代碼處理先前優化的具有透明度的索引彩色 PNG 圖像后( 有關某些背景,請參見此處,因為此問題涉及相同的圖像文件),PLTE 塊似乎使用比有效使用的顏色更多的顏色進行擴展。
畝電流代碼:
#!/usr/bin/env/python3
import os
from PIL import Image
source_file = os.path.expanduser("~/Desktop/prob.png")
dest_file = os.path.expanduser("~/Desktop/processed_img.png")
img = Image.open(source_file)
# Convert all colors in the palette to grayscale and save the new palette
pal = img.getpalette()
for i in range(len(pal) // 3):
# Using ITU-R 601-2 luma transform
g = (pal[3*i] * 299 + pal[3*i+1] * 587 + pal[3*i+2] * 114) // 1000
pal[3*i: 3*i+3] = [g, g, g]
img.putpalette(pal)
try:
img.save(dest_file, optimize=True, format="PNG")
except IOError:
ImageFile.MAXBLOCK = img.size[0] * img.size[1]
img.save(dest_file, optimize=True, format="PNG")
使用pngcheck
我為原始文件獲得了一個 16 色的小調色板:
$ pngcheck -tc7pv ~/Desktop/prob.png
File: /Users/victor/Desktop/prob.png (12562 bytes)
chunk IHDR at offset 0x0000c, length 13
825 x 825 image, 8-bit palette, non-interlaced
chunk PLTE at offset 0x00025, length 48: 16 palette entries
0: ( 0, 0, 0) = (0x00,0x00,0x00)
1: (230,230,230) = (0xe6,0xe6,0xe6)
2: (215,215,215) = (0xd7,0xd7,0xd7)
3: (199,199,199) = (0xc7,0xc7,0xc7)
4: (175,175,175) = (0xaf,0xaf,0xaf)
5: (143,143,143) = (0x8f,0x8f,0x8f)
6: (111,111,111) = (0x6f,0x6f,0x6f)
7: ( 79, 79, 79) = (0x4f,0x4f,0x4f)
8: ( 22, 22, 22) = (0x16,0x16,0x16)
9: ( 0, 0, 0) = (0x00,0x00,0x00)
10: ( 47, 47, 47) = (0x2f,0x2f,0x2f)
11: (254,254,254) = (0xfe,0xfe,0xfe)
12: (115, 89, 0) = (0x73,0x59,0x00)
13: (225,176, 0) = (0xe1,0xb0,0x00)
14: (255,211, 0) = (0xff,0xd3,0x00)
15: (254,204, 0) = (0xfe,0xcc,0x00)
chunk tRNS at offset 0x00061, length 1: 1 transparency entry
0: 0 = 0x00
chunk IDAT at offset 0x0006e, length 12432
zlib: deflated, 32K window, maximum compression
chunk IEND at offset 0x0310a, length 0
No errors detected in /Users/victor/Desktop/prob.png (5 chunks, 98.2% compression).
然后,在使用上面的代碼示例處理圖像之后, pngcheck
顯示一個更大的 PLTE 塊,其中填充了許多(可能未使用的)顏色值:
$ pngcheck -tc7pv ~/Desktop/processed_img.png
File: /Users/victor/Desktop/processed_img.png (14680 bytes)
chunk IHDR at offset 0x0000c, length 13
825 x 825 image, 8-bit palette, non-interlaced
chunk PLTE at offset 0x00025, length 768: 256 palette entries
0: ( 0, 0, 0) = (0x00,0x00,0x00)
1: (230,230,230) = (0xe6,0xe6,0xe6)
2: (215,215,215) = (0xd7,0xd7,0xd7)
3: (199,199,199) = (0xc7,0xc7,0xc7)
4: (175,175,175) = (0xaf,0xaf,0xaf)
5: (143,143,143) = (0x8f,0x8f,0x8f)
6: (111,111,111) = (0x6f,0x6f,0x6f)
7: ( 79, 79, 79) = (0x4f,0x4f,0x4f)
8: ( 22, 22, 22) = (0x16,0x16,0x16)
9: ( 0, 0, 0) = (0x00,0x00,0x00)
10: ( 47, 47, 47) = (0x2f,0x2f,0x2f)
11: (254,254,254) = (0xfe,0xfe,0xfe)
12: ( 86, 86, 86) = (0x56,0x56,0x56)
13: (170,170,170) = (0xaa,0xaa,0xaa)
14: (200,200,200) = (0xc8,0xc8,0xc8)
15: (195,195,195) = (0xc3,0xc3,0xc3)
16: ( 16, 16, 16) = (0x10,0x10,0x10)
17: ( 17, 17, 17) = (0x11,0x11,0x11)
18: ( 18, 18, 18) = (0x12,0x12,0x12)
19: ( 19, 19, 19) = (0x13,0x13,0x13)
20: ( 20, 20, 20) = (0x14,0x14,0x14)
(...) --- 它繼續列出所有高達 255 的值:
254: (254,254,254) = (0xfe,0xfe,0xfe)
255: (255,255,255) = (0xff,0xff,0xff)
chunk tRNS at offset 0x00331, length 1: 1 transparency entry
0: 0 = 0x00
chunk IDAT at offset 0x0033e, length 13830
zlib: deflated, 32K window, maximum compression
chunk IEND at offset 0x03950, length 0
No errors detected in /Users/victor/Desktop/processed_img.png (5 chunks, 97.8% compression).
這種行為在 Pillow 上正常嗎? 有什么方法可以保存更短的 PLTE 塊,類似於原始文件(我正在嘗試針對更小的文件大小進行優化)?
如果 Pillow 做不到,還有其他簡單的方法可以做到嗎? 最好使用純 Python,但也可以使用numpy
或其他一些純 Python 包,如PyPNG
或PurePNG
,如果有幫助的話。
我在帶有 Pillow 9.2.0 的蜜蜂 png 上運行了您的代碼,並且輸出 png 在其調色板中具有與原始顏色相同的數字顏色。 此外, Image.convert()
具有可用於控制輸出顏色的 args palette
和colors
。 例如,要保持與輸入圖像相同數量的顏色:
from PIL import Image
img = Image.open('bee.png')
num_pixels = img.size[0]*img.size[1]
num_colors = len(img.getcolors(num_pixels))
# Max palette size = 256
if num_colors > 256:
num_colors = 256
img = img.convert(mode='P', palette=1, colors=num_colors)
img.save('bee2.png', optimize=True, format="PNG")
或者,如果您對減小/管理圖像大小感興趣,我建議使用Image.save()
中的quality
參數壓縮圖像或使用 ExifTool 等其他工具來消除不必要的元數據(這些可能對蜜蜂.png)。
有關 Pillow 中圖像模式的更多信息,請參閱 Mark Setchell 的回答: PIL 中“P”和“L”模式中的圖像有什么區別?
討論使用 Pillow 減小文件大小的答案: 如何使用 PIL 減小圖像文件大小
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.