|
1 # -*- coding: utf-8 -*- |
|
2 """ |
|
3 sphinx.util.png |
|
4 ~~~~~~~~~~~~~~~ |
|
5 |
|
6 PNG image manipulation helpers. |
|
7 |
|
8 :copyright: 2008 by Georg Brandl. |
|
9 :license: BSD. |
|
10 """ |
|
11 |
|
12 import struct |
|
13 import binascii |
|
14 |
|
15 LEN_IEND = 12 |
|
16 LEN_DEPTH = 22 |
|
17 |
|
18 DEPTH_CHUNK_LEN = struct.pack('!i', 10) |
|
19 DEPTH_CHUNK_START = 'tEXtDepth\x00' |
|
20 IEND_CHUNK = '\x00\x00\x00\x00IEND\xAE\x42\x60\x82' |
|
21 |
|
22 |
|
23 def read_png_depth(filename): |
|
24 """ |
|
25 Read the special tEXt chunk indicating the depth from a PNG file. |
|
26 """ |
|
27 result = None |
|
28 f = open(filename, 'rb') |
|
29 try: |
|
30 f.seek(- (LEN_IEND + LEN_DEPTH), 2) |
|
31 depthchunk = f.read(LEN_DEPTH) |
|
32 if not depthchunk.startswith(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START): |
|
33 # either not a PNG file or not containing the depth chunk |
|
34 return None |
|
35 result = struct.unpack('!i', depthchunk[14:18])[0] |
|
36 finally: |
|
37 f.close() |
|
38 return result |
|
39 |
|
40 |
|
41 def write_png_depth(filename, depth): |
|
42 """ |
|
43 Write the special tEXt chunk indicating the depth to a PNG file. |
|
44 The chunk is placed immediately before the special IEND chunk. |
|
45 """ |
|
46 data = struct.pack('!i', depth) |
|
47 f = open(filename, 'r+b') |
|
48 try: |
|
49 # seek to the beginning of the IEND chunk |
|
50 f.seek(-LEN_IEND, 2) |
|
51 # overwrite it with the depth chunk |
|
52 f.write(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START + data) |
|
53 # calculate the checksum over chunk name and data |
|
54 f.write(struct.pack('!i', binascii.crc32(DEPTH_CHUNK_START + data))) |
|
55 # replace the IEND chunk |
|
56 f.write(IEND_CHUNK) |
|
57 finally: |
|
58 f.close() |