2
# This Source Code Form is subject to the terms of the Mozilla Public
3
# License, v. 2.0. If a copy of the MPL was not distributed with this
4
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
12
# ref: http://msdn.microsoft.com/en-us/library/ms997538
13
class ICONDIR(ctypes.LittleEndianStructure):
15
_fields_ = [("idReserved", ctypes.c_ushort),
16
("idType", ctypes.c_ushort),
17
("idCount", ctypes.c_ushort)]
19
class ICONDIRENTRY(ctypes.LittleEndianStructure):
21
_fields_ = [("bWidth", ctypes.c_byte),
22
("bHeight", ctypes.c_byte),
23
("bColorCount", ctypes.c_byte),
24
("bReserved", ctypes.c_byte),
25
("wPlanes", ctypes.c_ushort),
26
("wBitCount", ctypes.c_ushort),
27
("dwBytesInRes", ctypes.c_ulong),
28
("dwImageOffset", ctypes.c_ulong)]
30
# R, G, B, A, so 4 columns per pixel
33
def main(infile, left, top, size, outfile):
34
img = png.Reader(filename=infile)
35
pixels = list(img.asRGBA()[2])
36
# Take the subarray out. This is the ugliest but probably most efficient way
38
outpixels = [[0] * (size * COLS_PP) for x in xrange(size)]
39
for row in xrange(size):
40
for col in xrange(size * COLS_PP):
41
outpixels[row][col] = pixels[top + row][left * COLS_PP + col]
43
# Set up a 32bpp RGBA PNG.
44
writer = png.Writer(size=(size, size), bitdepth=8, alpha=True)
45
# Write to a memory buffer
46
outpng = StringIO.StringIO()
47
writer.write(outpng, outpixels)
48
outpngbuf = outpng.getvalue()
51
# Set up an icon header
53
icondir.idReserved = 0
58
iconentry = ICONDIRENTRY()
59
iconentry.bWidth = size
60
iconentry.bHeight = size
61
# Truecolor images have color count set to 0
62
iconentry.bColorCount = 0
63
iconentry.bReserved = 0
64
# PNGs have 1 color plane
66
# We're RGBA, so 32 bits per pixel
67
iconentry.wBitCount = 32
68
# Length of the buffer
69
iconentry.dwBytesInRes = len(outpngbuf)
70
# The data will be right after the icondir and iconentry
71
iconentry.dwImageOffset = ctypes.sizeof(icondir) + ctypes.sizeof(iconentry)
73
# Time to write everything out
74
out = open(outfile, "wb")
80
if __name__ == "__main__":
81
# Convert left, top and size into integers
82
main(*([sys.argv[1]] + [int(val) for val in sys.argv[2:5]] + [sys.argv[5]]))