PNG chunks removing with Python |
Mar 11 |
# 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()
there is a bug:
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])
should be:
def compute_chunk_length(data, i):
return (ord(data[i]) << 24) | (ord(data[i + 1]) << 16) | (ord(data[i + 8]) << 1) | ord(data[i + 3])
thanks for share your code
there’s a bug in my comment:
def compute_chunk_length(data, i):
| ord(data[i + 3])
return (ord(data[i]) << 24) | (ord(data[i + 1]) << 16) | (ord(data[i + 2]) <<
thank you for your fix
yeah, I forgot that we need to get bytes