比这篇新的文章: Codee#6095
比这篇旧的文章: Codee#6093

ICON Creater from RGBa array-生成图标文件,支持24位和32位图片

语言: Python, 标签: icon ico 图标 2009/09/15发布 4个月前更新 更新记录
作者: 半瓶墨水, 点击344次, 评论(0), 收藏者(1), , 打分:

背景
主题: 字体:
001 #! /usr/bin/env python
002 # -*- coding: utf-8 -*-
003 #
004 # windows icon file(.ico) and cursor file(.cur) generator/writer from RGB(a) array
005 #
006 #    NOTICE: one image per file *only*, 16x16 or 32x32 or 48x48 or 64x64 *only*
007 #    Support 24 bit & 32 bit(RGB + alpha)
008 #
009 # Copyright 2009 半瓶墨水
010 # 署名 & 非商业性使用 & 相同方式共享 ( http://creativecommons.org/licenses/by-nc-sa/2.5/cn/ )
011 #
012 # About Author
013 #   Blog( http://2maomao.com/blog/ )
014 #   Website( http://fayaa.com/tool/favicon/ )
015 #   Contact me via email
016 #
017 # References:
018 #  [1] http://en.wikipedia.org/wiki/Ico_Format
019 #  [2] http://en.wikipedia.org/wiki/Windows_and_OS/2_bitmap
020 #  [3] http://support.microsoft.com/kb/83034
021 #  [4] http://msdn.microsoft.com/en-us/library/ms997538(loband).aspx
022 #  [5] http://www.martinreddy.net/gfx/2d/BMP.txt
023 #  [6] http://code.google.com/p/casadebender/source/browse/python/PIL/Win32IconImagePlugin.py
024 #  [7] http://www.osphp.com.cn/read.php/290.htm
025
026
027 # data: a size*size of (r,g,b,t) tuples, t for tansparency(if True)
028 #       (r,g,b,a) if bpp is 32
029 # size: could be 16 or 32 or 48 or 64, other value NOT supported
030 # bpp: bits per pixel, could *only* be 24 or 32!
031 # return: an "array" of BYTES which, if write to file, is a size*size ico file
032 def genico(data, size=16, bpp=24):
033   from array import array
034   a = array('B')
035   #header(ref1&5)
036   a.extend((0,0, 1,0, 1,0)) #reserved*2, icon,0, 1 image per-file,0
037   #directory(ref1&5&7)
038   imglen = 40+size*(size*3 + (size+16)/32*32/8) #image-part length in bytes
039                                                 #!hack! AND bits align to 32 bits per line
040                                                 #!shit! MSDN says nothing about this
041   if bpp == 32:
042     imglen += size*size #1 more byte for alpha value of each pixel
043   a.extend((size,size, 0,0, 1,0, bpp,0)) #w,h, reserved*2, 1plane*2, bpp*2
044   a.extend((imglen&0xff,imglen>>8,0,0, 22,0,0,0)) #bitmap-size*4,22B-offset*4
045   #image BITMAPINFOHEADER(ref5)
046   a.extend((40,0,0,0)) #size of data(contains header)*4
047   a.extend((size,0,0,0, size*2,0,0,0))#w*4, (h+h)*4 (!shit hack! XOR+AND)
048   a.extend((1,0, bpp,0, 0,0,0,0, 0,0,0,0)) #1 plane*2, 24 bits*2, no compress*4, rawBMPsize(no compress so 0)*4
049   a.extend((0,1,0,0, 0,1,0,0)) #horizontal*4/vertical*4 resolution pixels/meter(WTF?)
050   a.extend((0,0,0,0, 0,0,0,0)) #colors fully used, all are important
051   #!no planes
052   #image content(ref1&5), XOR+AND bitmaps
053   AND = array('B')
054   vand = 0
055   vcnt = 0
056   #remember that bitmap format is reversed in y-axis
057   for y in range(size-1,-1,-1):
058     for x in range(0, size):
059       b,g,r,t_or_a = data[y*size+x]
060       a.extend((r,g,b))
061       if bpp == 32:
062         a.append(t_or_a)
063       vcnt+=1
064       vand<<=1
065       if (bpp==24 and t_or_a) or (bpp==32 and t_or_a<128):
066         vand |= 1
067       if vcnt==8:
068         AND.append(vand)
069         vcnt=0
070         vand=0
071     #!hack! AND bits align to 32 bits per line, !shit! MSDN says nothing about this
072     AND.extend([0] * ((32-size%32)%32/8))
073   a.extend(AND)
074   return a
075
076 # x,y indicate the hotspot position
077 # simply set the type/hotspot(x&y) after generates the icon
078 def gencur(data, size=16, bpp=24, x=0, y=0):
079   a = genico(data, size, bpp)
080   a[3], a[10], a[12] = 2, x, y
081   return a
082
083 #---------------testing-------------------
084
085 def test_ico(fn, cofunc, wh, bpp=24):
086   data = []
087   for i in range(wh*wh):
088     data.append(cofunc(i))
089   icoflow = genico(data, wh, bpp)
090   f = open(fn, "wb")
091   icoflow.tofile(f)
092   f.close()
093  
094 # test it!
095 if __name__ == "__main__":
096   wh = 16
097   av = lambda i: i/wh*256/wh
098   #16x16 red
099   test_ico("red_green_16.ico", lambda i: (av(i), (i%wh)*256/wh, 0, 0), wh)
100   #16x16 green and transparent
101   test_ico("green_16.ico", lambda i: (0, av(i), 0, (i%wh)>wh/2), wh)
102   wh = 32
103   #32x32 blue
104   test_ico("blue_32_trans.ico", lambda i: (0, 0, av(i), (i%wh)<wh/2), wh)
105   #32x32 gray and transparent
106   test_ico("gray_32.ico", lambda i: (av(i), av(i), av(i), 0), wh)
107   #32x32 blue and alpha
108   test_ico("blue_32_alpha.ico", lambda i: (0, 0, av(i), av(i)), wh, 32)


所有评论,共0条:( 我也来说两句)


发表评论

注册登录后再发表评论