如果您只想更改调色板,那么 PIL 只会妨碍您。幸运的是,当您只对某些数据块感兴趣时,PNG 文件格式的设计很容易处理。PLTE 块的格式只是一个 RGB 三元组数组,末尾有一个 CRC。要就地更改文件上的调色板而不读取或写入整个文件:
import struct
from zlib import crc32
import os
# PNG file format signature
pngsig = '\x89PNG\r\n\x1a\n'
def swap_palette(filename):
# open in read+write mode
with open(filename, 'r+b') as f:
f.seek(0)
# verify that we have a PNG file
if f.read(len(pngsig)) != pngsig:
raise RuntimeError('not a png file!')
while True:
chunkstr = f.read(8)
if len(chunkstr) != 8:
# end of file
break
# decode the chunk header
length, chtype = struct.unpack('>L4s', chunkstr)
# we only care about palette chunks
if chtype == 'PLTE':
curpos = f.tell()
paldata = f.read(length)
# change the 3rd palette entry to cyan
paldata = paldata[:6] + '\x00\xff\xde' + paldata[9:]
# go back and write the modified palette in-place
f.seek(curpos)
f.write(paldata)
f.write(struct.pack('>L', crc32(chtype+paldata)&0xffffffff))
else:
# skip over non-palette chunks
f.seek(length+4, os.SEEK_CUR)
if __name__ == '__main__':
import shutil
shutil.copyfile('redghost.png', 'blueghost.png')
swap_palette('blueghost.png')
此代码将 redghost.png 复制到 blueghost.png 并就地修改 blueghost.png 的调色板。
->