Last active
February 10, 2017 09:51
-
-
Save harjitmoe/d877966247098c37b5d1b6c209a5dac6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) Secret Labs AB 1997-2003. | |
# Copyright (c) Fredrik Lundh 1995-2003. | |
# | |
# By obtaining, using, and/or copying this software and/or its | |
# associated documentation, you agree that you have read, understood, | |
# and will comply with the following terms and conditions: | |
# | |
# Permission to use, copy, modify, and distribute this software and its | |
# associated documentation for any purpose and without fee is hereby | |
# granted, provided that the above copyright notice appears in all | |
# copies, and that both that copyright notice and this permission notice | |
# appear in supporting documentation, and that the name of Secret Labs | |
# AB or the author not be used in advertising or publicity pertaining to | |
# distribution of the software without specific, written prior | |
# permission. | |
# | |
# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO | |
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
# FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR | |
# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
# | |
# To any copyright-eligible contributions by Thomas Hori (HarJIT), | |
# the following applies: | |
# | |
# Copyright (c) Thomas Hori. | |
# Contributions written 2012, 2015, 2016. | |
# | |
# THIS WORK IS PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, | |
# INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
# FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL THE AUTHORS OR CONTRIBUTORS | |
# BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
# CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE), | |
# ARISING IN ANY WAY OUT OF THE USE OF THIS WORK, EVEN IF ADVISED OF THE | |
# POSSIBILITY OF SUCH DAMAGE. | |
# | |
# Permission is granted to anyone to use this work for any purpose, including | |
# commercial applications, and to alter it and/or redistribute it freely in any | |
# form, with or without modification, subject to the following restrictions: | |
# | |
# 1. The origin of this work must not be misrepresented; you must not claim that | |
# you authored the original work. If you use this work in a product, an | |
# acknowledgment in the product documentation would be appreciated but is not | |
# required. | |
# | |
# 2. Altered versions in any form must not be misrepresented as being the | |
# original work, and neither the name of HarJIT nor the names of authors or | |
# contributors may be used to endorse or promote products derived from this | |
# work without specific prior written permission. | |
# | |
# 3. The text of this notice must be included, unaltered, with any distribution. | |
# | |
# | |
# The Python Imaging Library. | |
# $Id$ | |
# | |
# Windows Icon support for PIL | |
# | |
# Notes: | |
# uses BmpImagePlugin.py to read the bitmap data. | |
# | |
# History: | |
# 1996-05-27 fl Created | |
# 2012-04-21 HarJIT <FORKED> | |
# 2012-04-21 HarJIT Added write code | |
# 2012-04-23 HarJIT Adjusted info header write code | |
# 2015-06-20 HarJIT Looked up about ico masks, fixes | |
# 2016-03-05 HarJIT Added mask generation. | |
# | |
# Write code by HarJIT derived from BmpImagePlugin. | |
# History of BmpImagePlugin: | |
# 1995-09-01 fl Created | |
# 1996-04-30 fl Added save | |
# 1997-08-27 fl Fixed save of 1-bit images | |
# 1998-03-06 fl Load P images as L where possible | |
# 1998-07-03 fl Load P images as 1 where possible | |
# 1998-12-29 fl Handle small palettes | |
# 2002-12-30 fl Fixed load of 1-bit palette images | |
# 2003-04-21 fl Fixed load of 1-bit monochrome images | |
# 2003-04-23 fl Added limited support for BI_BITFIELDS compression | |
# | |
__version__ = "0.1" | |
from PIL import Image, BmpImagePlugin | |
# | |
# -------------------------------------------------------------------- | |
def i16(c): | |
return ord(c[0]) + (ord(c[1])<<8) | |
def i32(c): | |
return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24) | |
def _accept(prefix): | |
return prefix[:4] == "\0\0\1\0" | |
## | |
# Image plugin for Windows Icon files. | |
class IcoImageFile(BmpImagePlugin.BmpImageFile): | |
format = "ICO" | |
format_description = "Windows Icon" | |
def _open(self): | |
# check magic | |
s = self.fp.read(6) | |
if not _accept(s): | |
raise SyntaxError, "not an ICO file" | |
# pick the largest icon in the file | |
m = "" | |
for i in range(i16(s[4:])): | |
s = self.fp.read(16) | |
if not m: | |
m = s | |
elif ord(s[0]) > ord(m[0]) and ord(s[1]) > ord(m[1]): | |
m = s | |
print "width", ord(s[0]) | |
print "height", ord(s[1]) | |
print "colors", ord(s[2]) | |
print "reserved", ord(s[3]) | |
print "planes", i16(s[4:]) | |
print "bitcount", i16(s[6:]) | |
print "bytes", i32(s[8:]) | |
print "offset", i32(s[12:]) | |
# load as bitmap | |
self._bitmap(i32(m[12:])) | |
# patch up the bitmap height | |
self.size = self.size[0], self.size[1]/2 | |
d, e, o, a = self.tile[0] | |
self.tile[0] = d, (0,0)+self.size, o, a | |
return | |
# | |
# -------------------------------------------------------------------- | |
# Write ICO file | |
def genmask(i): | |
i=i.convert("RGBA") | |
width,height=i.size | |
j=Image.new("RGBA",(width,2*height)) | |
k=Image.new("RGB",(width,height)) | |
for x in range(width): | |
for y in range(height): | |
a=255-i.getpixel((x,y))[3] | |
k.putpixel((x,y),(a,a,a)) | |
j.paste(k.convert("RGBA"),(0,0)) | |
j.paste(i.convert("RGB").convert("RGBA"),(0,height)) | |
return j | |
from PIL import ImageFile | |
def o16(i): | |
return chr(i&255) + chr(i>>8&255) | |
def o32(i): | |
return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255) | |
SAVE = { | |
# "1": ("1", 1, 2), | |
# "L": ("L", 8, 0),#256), | |
# "P": ("P", 8, 0),#256), | |
"RGB": ("BGR", 24, 0), | |
"RGBA": ("BGRA", 32, 0), | |
} | |
def SaveAsICO(ims, fp, filename=None, check=0): | |
if not hasattr(ims,"__len__"): #Quack typing | |
ims=(ims,) | |
for im in ims: | |
try: | |
rawmode, bits, colors = SAVE[im.mode] | |
except KeyError: | |
raise IOError("cannot write mode %s as ICO" % im.mode) | |
if check: | |
return check | |
ims=map(genmask,ims) | |
if not filename: | |
#fp could be *either* fp *or* (otherwise disused) filename here | |
try: | |
buffer(fp) | |
except TypeError: | |
pass | |
else: | |
fp=open(fp,"wb") | |
# ICO header | |
fp.write("\0\0" + # file type (magic) | |
o16(1) + # version (1=icon 2=cursor) | |
o16(len(ims))) # Number of images | |
# ICO directory | |
dirsize=len(ims)*16 | |
running_offset=6+dirsize | |
for imno,im in enumerate(ims): | |
rawmode, bits, colors = SAVE[im.mode] | |
stride = ((im.size[0]*bits+7)/8+3)&(~3) | |
image = stride * im.size[1] | |
wid,hei = im.size | |
if wid>=256: | |
wid=0 | |
if hei>=256: | |
hei=0 | |
fp.write(chr(wid) + # width | |
chr(hei) + # height | |
chr(colors) + # colors used | |
"\0" + # reserved | |
o16(1) + # planes | |
o16(bits) + # BPP (depth) | |
o32(image) + # size of bitmap | |
o32(running_offset)) # offset of icon | |
running_offset+=image+40 | |
# BMP info header (main BMP header must be absent) | |
for im in ims: | |
rawmode, bits, colors = SAVE[im.mode] | |
stride = ((im.size[0]*bits+7)/8+3)&(~3) | |
image = stride * im.size[1] | |
fp.write(o32(40) + # info header size | |
o32(im.size[0]) + # width | |
o32(im.size[1]) + # height including mask | |
o16(1) + # planes | |
o16(bits) + # depth (BPP) | |
o32(0) + # compression (0=uncompressed) | |
o32(image) + # size of bitmap | |
o32(1) + o32(1) + # resolution | |
o32(colors) + # colors used | |
o32(colors)) # colors important | |
if im.mode == "1": | |
for i in (0, 255): | |
fp.write(chr(i) * 4) | |
elif im.mode == "L": | |
for i in range(256): | |
fp.write(chr(i) * 4) | |
elif im.mode == "P": | |
fp.write(im.im.getpalette("RGB", "BGRX")) | |
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))]) | |
# | |
# -------------------------------------------------------------------- | |
Image.register_open("ICO", IcoImageFile, _accept) | |
Image.register_save("ICO", SaveAsICO) | |
Image.register_extension("ICO", ".ico") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment