s o m e t h i n g a b o u t m e

PNG chunks removing with Python

# working on pyips

I’ve already have the post about chunk removing in Java. But how to remove chunk from PNG file data stream in python?


maxs:/usr/local/www/eth0less.com/pyips>cat ./pngutils.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
 PyIPS - Python image processing server/script

 author: Sergey Polzunov aka Traut
 email: traut.box[at]gmail.com
 blog: http://out.com.ua/blog

 Version 0.1
'''

import string

chunk_min_length = 4 + 4 + 4 # data_length, chunk_name, crc

main_chunks = ["IHDR", "PLTE", "IDAT", "IEND"]
other_chunks = ["tRNS",                                 # transparency
                "cHRM", "gAMA", "iCCP", "sBIT", "sRGB", # colorspace
                "iTXt", "tEXt", "zTXt", "bKGD",         # textual info
                "hIST", "pHYs", "sPLT",                 # miscellaneous things
                "tIME"]                                 # time stamp

def compute_chunk_length(data, i):
    return (ord(data[i]) << 3) | (ord(data[i + 1]) << 2) | (ord(data[i + 2]) << 1) | ord(data[i + 3])

def remove_chunk(data, chunk_name):
    for i in range(0, len(data) - chunk_min_length + 1):
        j = i + 4
        maybe_chunk = data[j] + data[j + 1] + data[j + 2] + data[j + 3]
        if maybe_chunk == chunk_name and (main_chunks + other_chunks).count(maybe_chunk) == 1:
            chunk_data_length = compute_chunk_length(data, i);

            #print "removing %d blocks" % (chunk_min_length + chunk_data_length)

            return data[:i] + data[i + chunk_min_length + chunk_data_length:]
    print "Cannot find chunk with name", chunk_name

def browse_chunks(data):
    found_chunks = []
    for i in range(0, len(data) - chunk_min_length + 1):
        j = i + 4
        maybe_chunk = data[j] + data[j + 1] + data[j + 2] + data[j + 3]
        if (main_chunks + other_chunks).count(maybe_chunk) == 1:
            chunk_data_length = compute_chunk_length(data, i);
            found_chunks.append((maybe_chunk, chunk_data_length))
            i += chunk_data_length + chunk_min_length

    #return found_chunks

    for chunk_name, chunk_length in found_chunks:
       print "Chunk %s founded. Data length is %d" % (chunk_name, chunk_length)

def test():
    image_file = open("test.png", "rb")
    image_raw_data = image_file.read()
    browse_chunks(image_raw_data)
    chunk = "gAMA"
    print "Removing", chunk
    new_image_data = remove_chunk(image_raw_data, chunk)
    new_image_file = open("test2.png", "wb")
    new_image_file.write(new_image_data)

    image_file.close()
    new_image_file.close()
    print "Edited file:"
    image_file = open("test2.png", "rb")
    image_raw_data = image_file.read()
    browse_chunks(image_raw_data)
    image_file.close()

if __name__ == "__main__":
    test()


PyIPS aka Python Image Processing Server/Script

PyIPS (Python Image Processing Server/Script) - standalone server/script behind lighttpd/apache server that provides image processing service (PIL, Imagemagick as engines). The server caches results on file system (local, mogilefs, etc). PyIPS uses file storage specified by home directory property.

Project is in the early stage of development.

example urls:

http://eth0less.com/pyips/main.py/process?name=pic1.jpg&width=200&height=200&crop_type=top
http://eth0less.com/pyips/main.py/process?name=pic1.jpg&width=200&height=200&crop_type=center
http://eth0less.com/pyips/main.py/process?name=pic2.jpg&width=500&height=400
http://eth0less.com/pyips/main.py/process?name=pic2.jpg&width=600&height=600&scale_up_allowed=true
http://eth0less.com/pyips/main.py/process?name=pic3.jpg&width=500&height=400&crop_type=center

Soon I’ll add cache function (with ability to refresh/clean image cache), ImageMagick engine (currently PyIPS works only with PIL engine) and maybe mogilefs filestorage manager.

There are some additional files in repository - main.py and main.fcgi - these are for apache+mod_python and for lighttpd+FastCGI correspondingly.