PNGメタデータを簡単に表示するもの
#coding:utf-8 | |
#Print some infomation of a PNG file | |
import struct | |
import datetime | |
import binascii | |
def crcChecker(data, crc): | |
computedCRC = binascii.crc32(data) | |
crc = struct.unpack('> I', crc)[0] | |
return crc == computedCRC | |
filename = input('Filename: ') | |
data = open(filename, 'rb').read() | |
if data[:8] != bytes((0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)): | |
print('This is not a PNG file') | |
exit() | |
flag_len = 4 | |
seek = 8 | |
IDATCount = 0 | |
CRCError = 0 | |
while seek <= len(data): | |
body_len = struct.unpack('> I', data[seek:seek+flag_len])[0] | |
chunk_len = body_len + 8 | |
chunkName, chunkData, CRC = struct.unpack('> 4s {}s 4s'.format(body_len), | |
data[seek+flag_len:seek+flag_len+chunk_len]) | |
if not crcChecker(chunkName+chunkData, CRC): | |
CRCError += 1 | |
print('Broken chunk') | |
enc = 'ASCII' | |
chunkName = str(chunkName, enc) | |
#chunk specific process | |
if chunkName == 'IDAT': | |
IDATCount += 1 | |
else: | |
print('---{}'.format(chunkName)) | |
if chunkName == 'IHDR': | |
width, height, depth, colourType, compress, filterType, adam7 = \ | |
struct.unpack('> I I B B B B ?', chunkData) | |
print('size: {}x{}'.format(width, height)) | |
print('depth: {}'.format(depth)) | |
if colourType == 0: | |
colour = 'Gray' | |
elif colourType == 2: | |
colour = 'RGB' | |
elif colourType == 3: | |
colour = 'Palette' | |
elif colourType == 4: | |
colour = 'Gray + Alpha' | |
elif colourType == 6: | |
colour = 'RGB + Alpha' | |
print('colour: {}'.format(colour)) | |
print('Adam7: {}'.format(adam7)) | |
if chunkName == 'bKGD': | |
print('background colour') | |
if colourType in {0, 4}: | |
backGnd = struct.unpack('> H', chunkData) | |
print('Gray {}'.format(backGnd)) | |
elif colourType in {2, 6}: | |
backGnd = struct.unpack('> H H H', chunkData) | |
print('R: {},G: {},B:{}'.format(*backGnd)) | |
elif colourType == 3: | |
backGnd = struct.unpack('> B', chunkData) | |
print('PaletIndex: {}'.format(backGnd)) | |
if chunkName == 'tIME': | |
timestamp = struct.unpack('> H B B B B B', chunkData) | |
print(datetime.datetime(*timestamp).isoformat()) | |
if chunkName == 'pHYs': | |
ppuX, ppuY, spec = struct.unpack('> I I ?', chunkData) | |
if spec: | |
dpi = [round(i/100*2.54, 3) for i in (ppuX,ppuY)] | |
print('DPI: {}'.format(dpi)) | |
if chunkName == 'gAMA': | |
gamma = struct.unpack('> I', chunkData)[0]/100000 | |
print('gamma(file): {}, gamma(machine): {}'.format( | |
gamma, round(1/gamma, 4)) | |
) | |
seek += flag_len + chunk_len | |
if chunkName == 'IEND': | |
print('---IDAT chunk: {}'.format(IDATCount)) | |
print('---CRC Error: {}'.format(CRCError)) | |
break | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment