#!/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()