Изменение палитры 8-битной.png изображения с использованием python PIL
Я ищу быстрый способ применить новую палитру к существующей 8-битной .изображения PNG. Как я могу это сделать? Это.png перекодируется, когда я сохраняю изображение? (Собственный ответ: похоже на то)
Что я пробовал (редактировал):
import Image, ImagePalette
output = StringIO.StringIO()
palette = (.....) #long palette of 768 items
im = Image.open('test_palette.png') #8 bit image
im.putpalette(palette)
im.save(output, format='PNG')
С моим свидетельством функция сохранения занимает около 65 миллисекунд. Моя мысль: без декодирования и кодирования, это может быть намного быстрее??
3 ответа:
Если вы хотите изменить только палитру, то 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 на месте.
->