8

在使用以下代码处理先前优化的具有透明度的索引彩色 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 包,比如PyPNGor PurePNG

4

0 回答 0