ひさびさのPythonネタです。PILハンドブックによるとではICOは読み取り専用らしいので、BMPで書き出した後ヘッダを編集することでICOが作成できるようにしてみました。
PILはよく知らないので24ビットのBMPが作成されるものと決め打ちでやっています。
また、pack関数の仕様上、sizeof(long)が4でないLP64やILP64の処理系では正しいデータが生成できないと思われます。
いまどきsizeof(int) == 2 はないだろうということで32ビット符号無し整数のフォーマット文字をLからIに変更しました。
ソース:
#!/usr/bin/env python """Windows icon (.ico) maker using The Python Imaging Library """ from PIL import Image from cStringIO import StringIO from struct import pack def makeicon(infile, outfile=None, dimensions=(32, 32)): """Convert an image to Windows icon format """ # check image dimensions width, height = dimensions if width < 1 or width > 256 or height < 1 or height > 256: raise ValueError('Invalid image dimensions') # open the source image and resize im = Image.open(infile) im.thumbnail(dimensions, Image.BICUBIC) width, height = im.size # crate BMP bmp = StringIO() im.save(bmp, 'BMP') # get resource size image_size = bmp.tell() - 14 mask_size = ((width + 31) / 32) * 4 * height # write ICONDIR ico = StringIO() ico.write(pack('<3H', 0, 1, 1)) # write ICONDIRENTRY ico.write(pack('<BBBBHHII', width & 255, height & 255, 0, 0, 1, 24, image_size + mask_size, 6 + 16)) # write ICONIMAGE bmp.seek(14) ico.write(bmp.read(8)) ico.write(pack('<I', height * 2)) bmp.seek(4, 1) ico.write(bmp.read()) ico.write('\0' * mask_size) ico.reset() # output or return the icon data if (outfile): open(outfile, 'w').write(ico.read()) else: return ico.read() if __name__ == '__main__': import sys, os infile = sys.argv[1] name, ext = os.path.splitext(os.path.basename(infile)) outfile = name + '.ico' makeicon(infile, outfile, (48, 48)) #print Image.open(outfile).size