| f | import sys | f | import sys | 
            |  |  |  |  | 
            | n | def parse_file_header(data): | n | def extract_bmp_header(content): | 
            |  | if len(data) < 14: |  | if len(content) < 14: | 
            |  | return (None, 'Invalid BMP file') |  | return (None, 'Invalid BMP file') | 
            | n | if data[:2] != b'BM': | n | if content[:2] != b'BM': | 
            |  | return (None, 'Not a Windows BMP') |  | return (None, 'Not a Windows BMP') | 
            | n | file_size = int.from_bytes(data[2:6], 'little') | n | bmp_size = int.from_bytes(content[2:6], 'little') | 
            |  | offset_to_pixels = int.from_bytes(data[10:14], 'little') |  | pixel_offset = int.from_bytes(content[10:14], 'little') | 
            |  | return ((file_size, offset_to_pixels), None) |  | return ((bmp_size, pixel_offset), None) | 
            |  |  |  |  | 
            | n | def check_file_size(data, declared_size): | n | def validate_bmp_size(content, expected_size): | 
            |  | if declared_size != len(data): |  | return (True, None) if len(content) == expected_size else (False, 'I | 
            |  |  |  | ncorrect size') | 
            |  | return (False, 'Incorrect size') |  |  | 
            |  | return (True, None) |  |  | 
            |  |  |  |  | 
            | n | def parse_dib_header(data): | n | def extract_dib_info(content): | 
            |  | if len(data) < 18: |  | if len(content) < 18: | 
            |  | return (None, 'Incomplete DIB header') |  | return (None, 'Incomplete DIB header') | 
            | n | dib_size = int.from_bytes(data[14:18], 'little') | n | header_length = int.from_bytes(content[14:18], 'little') | 
            |  | if dib_size not in {12, 40, 56, 108, 124}: |  | if header_length not in {12, 40, 56, 108, 124}: | 
            |  | return (None, 'Incorrect header size') |  | return (None, 'Incorrect header size') | 
            | n | return (dib_size, None) | n | return (header_length, None) | 
            |  |  |  |  | 
            | n | def retrieve_image_info(data, dib_size): | n | def get_image_metadata(content, header_length): | 
            |  | if dib_size == 12: |  | if header_length == 12: | 
            |  | if len(data) < 26: |  | if len(content) < 26: | 
            |  | return (None, 'DIB header too short') |  | return (None, 'DIB header too short') | 
            | n | width = int.from_bytes(data[18:20], 'little') | n | w = int.from_bytes(content[18:20], 'little') | 
            |  | height = int.from_bytes(data[20:22], 'little', signed=True) |  | h = int.from_bytes(content[20:22], 'little', signed=True) | 
            |  | planes = int.from_bytes(data[22:24], 'little') |  | color_planes = int.from_bytes(content[22:24], 'little') | 
            |  | bit_depth = int.from_bytes(data[24:26], 'little') |  | bit_depth = int.from_bytes(content[24:26], 'little') | 
            |  | compression_method = 0 |  | compression = 0 | 
            |  | else: |  | else: | 
            | n | if len(data) < 34: | n | if len(content) < 34: | 
            |  | return (None, 'Incomplete DIB header') |  | return (None, 'Incomplete DIB header') | 
            | n | width = int.from_bytes(data[18:22], 'little', signed=True) | n | w = int.from_bytes(content[18:22], 'little', signed=True) | 
            |  | height = int.from_bytes(data[22:26], 'little', signed=True) |  | h = int.from_bytes(content[22:26], 'little', signed=True) | 
            |  | planes = int.from_bytes(data[26:28], 'little') |  | color_planes = int.from_bytes(content[26:28], 'little') | 
            |  | bit_depth = int.from_bytes(data[28:30], 'little') |  | bit_depth = int.from_bytes(content[28:30], 'little') | 
            |  | compression_method = int.from_bytes(data[30:34], 'little') |  | compression = int.from_bytes(content[30:34], 'little') | 
            |  | return ((width, height, bit_depth, compression_method), None) |  | return ((w, h, bit_depth, compression), None) | 
            |  |  |  |  | 
            | n | def calculate_pixel_data_size(width, height, bit_depth): | n | def compute_pixel_storage(w, h, bit_depth): | 
            |  | height = abs(height) |  | h = abs(h) | 
            |  | row_width = (width * bit_depth + 31) // 32 * 4 |  | row_size = (w * bit_depth + 31) // 32 * 4 | 
            |  | return row_width * height |  | return row_size * h | 
            |  |  |  |  | 
            | n | def verify_image_size(data, dib_size, expected_pixel_data_size): | n | def validate_image_size(content, header_length, computed_size): | 
            |  | if dib_size >= 40 and len(data) >= 38: |  | if header_length >= 40 and len(content) >= 38: | 
            |  | declared_image_size = int.from_bytes(data[34:38], 'little') |  | stated_size = int.from_bytes(content[34:38], 'little') | 
            |  | else: |  | else: | 
            | n | declared_image_size = 0 | n | stated_size = 0 | 
            |  | if declared_image_size == 0: |  | if stated_size == 0: | 
            |  | declared_image_size = expected_pixel_data_size |  | stated_size = computed_size | 
            |  | elif declared_image_size not in {expected_pixel_data_size, expected_ |  | elif stated_size not in {computed_size, computed_size + 2}: | 
            |  | pixel_data_size + 2}: |  |  | 
            |  | return (False, 'Incorrect image size') |  | return (False, 'Incorrect image size') | 
            | n | extra_bytes = 2 if declared_image_size > expected_pixel_data_size el | n | pad = 2 if stated_size > computed_size else 0 | 
            |  | se 0 |  |  | 
            |  | return (extra_bytes, None) |  | return (pad, None) | 
            |  |  |  |  | 
            | n | def analyze_bmp(data): | n | def parse_bmp(content): | 
            |  | try: |  | try: | 
            | n | header, error = parse_file_header(data) | n | header, err = extract_bmp_header(content) | 
            |  | if error: |  | if err: | 
            |  | return error |  | return err | 
            |  | file_size, pixel_data_offset = header |  | bmp_size, pixel_offset = header | 
            |  | valid, error = check_file_size(data, file_size) |  | is_valid, err = validate_bmp_size(content, bmp_size) | 
            |  | if not valid: |  | if not is_valid: | 
            |  | return error |  | return err | 
            |  | dib_size, error = parse_dib_header(data) |  | dib_length, err = extract_dib_info(content) | 
            |  | if error: |  | if err: | 
            |  | return error |  | return err | 
            |  | image_data, error = retrieve_image_info(data, dib_size) |  | metadata, err = get_image_metadata(content, dib_length) | 
            |  | if error: |  | if err: | 
            |  | return error |  | return err | 
            |  | width, height, bit_depth, compression = image_data |  | w, h, bit_depth, compression = metadata | 
            |  | expected_pixel_data_size = calculate_pixel_data_size(width, heig |  | required_size = compute_pixel_storage(w, h, bit_depth) | 
            |  | ht, bit_depth) |  |  | 
            |  | padding_bytes, error = verify_image_size(data, dib_size, expecte |  | pad_size, err = validate_image_size(content, dib_length, require | 
            |  | d_pixel_data_size) |  | d_size) | 
            |  | if error: |  | if err: | 
            |  | return error |  | return err | 
            |  | return f'{width} {abs(height)} {bit_depth} {compression} {paddin |  | return f'{w} {abs(h)} {bit_depth} {compression} {pad_size}' | 
            |  | g_bytes}' |  |  | 
            |  | except Exception as exc: |  | except Exception as ex: | 
            |  | return f'Unhandled error: {exc}' |  | return f'Unhandled error: {ex}' | 
            |  | if __name__ == '__main__': |  | if __name__ == '__main__': | 
            | t | bmp_content = sys.stdin.buffer.read() | t | bmp_data = sys.stdin.buffer.read() | 
            |  | analysis_result = analyze_bmp(bmp_content) |  | print(parse_bmp(bmp_data)) | 
            |  | print(analysis_result) |  |  |