#!/usr/bin/python3
# ===============================================================
# interpret/display GIF file header information
#
# en.wikipedia.org/wiki/GIF
#
# Note: test file mona_lisa_small_a.gif contains only one image
# ===============================================================
import hex_dump as hxd
# ---------------------------------------------------------------
# ---- give a color table index, display its red,gree,blue
# ---- values
# ---------------------------------------------------------------
def display_color_table_pixel(gif_bytes:str,off:int,idx:int) -> None:
r = int.from_bytes(gif_bytes[idx :idx+1],'little')
g = int.from_bytes(gif_bytes[idx+1:idx+2],'little')
b = int.from_bytes(gif_bytes[idx+2:idx+3],'little')
print(f'[{off:02X}] = {r:02X},{g:02X},{b:02X}')
return
# ---------------------------------------------------------------
# ---- display gif file header
# ---------------------------------------------------------------
def display_gif_header(file_path,gif_bytes:str) -> None:
print()
print('---- gif Header -------------------------------')
char1 = str(gif_bytes[0:6].decode('UTF-8'))
width = int.from_bytes(gif_bytes[6:8],'little')
height = int.from_bytes(gif_bytes[8:10],'little')
gct = int.from_bytes(gif_bytes[10:12],'little')
bak_color_index = int.from_bytes(gif_bytes[12:13],'little')
aspect_ratio = int.from_bytes(gif_bytes[13:14],'little')
print(f'file = {file_path}')
print(f'width = {width}')
print(f'height = {height}')
print(f'GCT = {gct:02X}')
print(f'bg color index = {bak_color_index}')
print(f'aspect ratio = {aspect_ratio}')
print()
print('---- Global Color Table - first six picels ----')
idx = 14 # byte array index (0xD)
offset = 0 # color table offset (index)
display_color_table_pixel(gif_bytes,offset,idx)
idx += 3
offset += 1
display_color_table_pixel(gif_bytes,offset,idx)
idx += 3
offset += 1
display_color_table_pixel(gif_bytes,offset,idx)
idx += 3
offset += 1
display_color_table_pixel(gif_bytes,offset,idx)
idx += 3
offset += 1
display_color_table_pixel(gif_bytes,offset,idx)
idx += 3
offset += 1
display_color_table_pixel(gif_bytes,offset,idx)
print('...')
print('...')
print()
print('---- Graphics Extention Block -----------------')
idx = 781 # byte array index (0x30D)
ext_blk = chr(int.from_bytes(gif_bytes[idx:idx+1],'little'))
print(f'extension block = {ext_blk}')
print()
print('---- Image Descriptor -------------------------')
idx = 789 # byte array index (0x315)
desc = chr(int.from_bytes(gif_bytes[idx:idx+1],'little'))
nw_x = int.from_bytes(gif_bytes[idx+1:idx+3],'little')
nw_y = int.from_bytes(gif_bytes[idx+3:idx+5],'little')
width = int.from_bytes(gif_bytes[idx+5:idx+7],'little')
height = int.from_bytes(gif_bytes[idx+7:idx+9],'little')
print(f'img descriptor = {desc}')
print(f'nw corner = {nw_x},{nw_y}')
print(f'width = {width}')
print(f'height = {height}')
print()
print('---- Image Data -------------------------------')
idx = 799 # byte array index (0x31F)
lzwmin = int.from_bytes(gif_bytes[idx:idx+1],'little')
# ---- skip the image data sub blocks
idx += 1
sub_blk_count = 0
while True:
sub_blk_size = int.from_bytes(gif_bytes[idx:idx+1],'little')
##print(f'sub blk size = {sub_blk_size:02X}')
sub_blk_count += 1
if sub_blk_size == 0: break
idx += sub_blk_size + 1 # skip image data sub block
print(f'minimun LZW code {lzwmin}')
print(f'last sub block size={sub_blk_size}')
print(f'last sub block index={idx}')
print(f'sub block count {sub_blk_count}')
# ---------------------------------------------------------------
# ---- open gif and read it directly into a byte array
# ----
# ---- It is not necessary to read in the complete file
# ---- if you are only accessing the headers. For example,
# ---- read the first 1000 bytes?
# ----
# ---- def load_gif_to_array(gif_file_path):
# ---- f = open(gif_file_path,'rb')
# ---- gif_bytes = f.read(1000)
# ---- close(f)
# ---- return gif_bytes
# ----
# ---- or
# ----
# ---- def load_gif_to_array(gif_file_path):
# ---- with open(gif_file_path,'rb') as f:
# ---- gif_bytes = f.read(1000)
# ---- return gif_bytes
# ----
# ---------------------------------------------------------------
def load_gif_to_array(gif_file_path:str) -> bytearray:
with open(gif_file_path,'rb') as file:
gif_bytes = file.read()
return gif_bytes
# ---------------------------------------------------------------
# ---- main
# ---------------------------------------------------------------
if __name__ == '__main__':
gif_file_paths = [ 'mona_lisa_small_a.gif',
##'mona_lisa_small_b.gif'
]
for file_path in gif_file_paths:
print()
gif_bytes = load_gif_to_array(file_path)
display_gif_header(file_path,gif_bytes)
print()