Source

sphinx / sphinx / util / png.py

Full commit
# -*- coding: utf-8 -*-
"""
    sphinx.util.png
    ~~~~~~~~~~~~~~~

    PNG image manipulation helpers.

    :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

import struct
import binascii

LEN_IEND = 12
LEN_DEPTH = 22

DEPTH_CHUNK_LEN = struct.pack('!i', 10)
DEPTH_CHUNK_START = 'tEXtDepth\x00'
IEND_CHUNK = '\x00\x00\x00\x00IEND\xAE\x42\x60\x82'


def read_png_depth(filename):
    """
    Read the special tEXt chunk indicating the depth from a PNG file.
    """
    result = None
    f = open(filename, 'rb')
    try:
        f.seek(- (LEN_IEND + LEN_DEPTH), 2)
        depthchunk = f.read(LEN_DEPTH)
        if not depthchunk.startswith(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START):
            # either not a PNG file or not containing the depth chunk
            return None
        result = struct.unpack('!i', depthchunk[14:18])[0]
    finally:
        f.close()
    return result


def write_png_depth(filename, depth):
    """
    Write the special tEXt chunk indicating the depth to a PNG file.
    The chunk is placed immediately before the special IEND chunk.
    """
    data = struct.pack('!i', depth)
    f = open(filename, 'r+b')
    try:
        # seek to the beginning of the IEND chunk
        f.seek(-LEN_IEND, 2)
        # overwrite it with the depth chunk
        f.write(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START + data)
        # calculate the checksum over chunk name and data
        f.write(struct.pack('!i', binascii.crc32(DEPTH_CHUNK_START + data)))
        # replace the IEND chunk
        f.write(IEND_CHUNK)
    finally:
        f.close()