f | import sys | f | import sys |
| | | |
n | def read_bmp_data(): | n | def read_input_data(): |
| return sys.stdin.buffer.read() | | return sys.stdin.buffer.read() |
| | | |
n | def validate_bmp_header(data): | n | def validate_header(data): |
| if len(data) < 14: | | if len(data) < 14: |
n | return 'Incorrect size' | n | return 'Invalid file size' |
| if data[:2] != b'BM': | | if data[:2] != b'BM': |
| return 'Not a Windows BMP' | | return 'Not a Windows BMP' |
n | file_size = int.from_bytes(data[2:6], 'little') | n | total_size = int.from_bytes(data[2:6], 'little') |
| if file_size != len(data): | | if total_size != len(data): |
| return 'Incorrect size' | | return 'Incorrect size' |
| if len(data) < 18: | | if len(data) < 18: |
n | return 'Incorrect size' | n | return 'Incomplete BMP header' |
| return file_size | | return total_size |
| | | |
n | def parse_dib_header(data, offset): | n | def analyze_dib_header(data, start_offset): |
| header_size = int.from_bytes(data[offset:offset + 4], 'little') | | dib_size = int.from_bytes(data[start_offset:start_offset + 4], 'litt |
| | | le') |
| valid_sizes = [12, 16, 40, 52, 56, 64, 108, 124] | | valid_sizes = [12, 16, 40, 52, 56, 64, 108, 124] |
n | if header_size not in valid_sizes: | n | if dib_size not in valid_sizes: |
| return ('Incorrect header size', None, None, None, None, None) | | return ('Incorrect header size', None, None, None, None, None) |
n | end_offset = offset + header_size | n | dib_end = start_offset + dib_size |
| if len(data) < end_offset: | | if len(data) < dib_end: |
| return ('Incorrect size', None, None, None, None, None) | | return ('Incomplete DIB header', None, None, None, None, None) |
| if header_size == 12: | | if dib_size == 12: |
| width = int.from_bytes(data[offset + 4:offset + 6], 'little') | | img_width = int.from_bytes(data[start_offset + 4:start_offset + |
| | | 6], 'little') |
| height = int.from_bytes(data[offset + 6:offset + 8], 'little') | | img_height = int.from_bytes(data[start_offset + 6:start_offset + |
| | | 8], 'little') |
| bpp = int.from_bytes(data[offset + 10:offset + 12], 'little') | | bpp = int.from_bytes(data[start_offset + 10:start_offset + 12], |
| | | 'little') |
| compression = 0 | | compression = 0 |
n | image_size = 0 | n | img_size = 0 |
| elif header_size == 16: | | elif dib_size == 16: |
| width = int.from_bytes(data[offset + 4:offset + 6], 'little', si | | img_width = int.from_bytes(data[start_offset + 4:start_offset + |
| gned=True) | | 6], 'little', signed=True) |
| height = int.from_bytes(data[offset + 6:offset + 8], 'little', s | | img_height = int.from_bytes(data[start_offset + 6:start_offset + |
| igned=True) | | 8], 'little', signed=True) |
| bpp = int.from_bytes(data[offset + 10:offset + 12], 'little') | | bpp = int.from_bytes(data[start_offset + 10:start_offset + 12], |
| | | 'little') |
| compression = int.from_bytes(data[offset + 12:offset + 16], 'lit | | compression = int.from_bytes(data[start_offset + 12:start_offset |
| tle') | | + 16], 'little') |
| image_size = 0 | | img_size = 0 |
| else: | | else: |
n | width = int.from_bytes(data[offset + 4:offset + 8], 'little', si | n | img_width = int.from_bytes(data[start_offset + 4:start_offset + |
| gned=True) | | 8], 'little', signed=True) |
| height = int.from_bytes(data[offset + 8:offset + 12], 'little', | | img_height = int.from_bytes(data[start_offset + 8:start_offset + |
| signed=True) | | 12], 'little', signed=True) |
| bpp = int.from_bytes(data[offset + 14:offset + 16], 'little') | | bpp = int.from_bytes(data[start_offset + 14:start_offset + 16], |
| | | 'little') |
| compression = int.from_bytes(data[offset + 16:offset + 20], 'lit | | compression = int.from_bytes(data[start_offset + 16:start_offset |
| tle') | | + 20], 'little') |
| image_size = int.from_bytes(data[offset + 20:offset + 24], 'litt | | img_size = int.from_bytes(data[start_offset + 20:start_offset + |
| le') | | 24], 'little') |
| return (None, width, height, bpp, compression, image_size) | | return (None, img_width, img_height, bpp, compression, img_size) |
| | | |
n | def calculate_image_size(width, height, bpp): | n | def compute_image_size(width, height, bits_per_pixel): |
| abs_width = abs(width) | | absolute_width = abs(width) |
| abs_height = abs(height) | | absolute_height = abs(height) |
| bits_per_row = abs_width * bpp | | bits_in_row = absolute_width * bits_per_pixel |
| bytes_per_row = (bits_per_row + 7) // 8 | | bytes_in_row = (bits_in_row + 7) // 8 |
| padding = (4 - bytes_per_row % 4) % 4 | | row_padding = (4 - bytes_in_row % 4) % 4 |
| total_row_bytes = bytes_per_row + padding | | total_row_size = bytes_in_row + row_padding |
| return (abs_width, abs_height, total_row_bytes * abs_height) | | return (absolute_width, absolute_height, total_row_size * absolute_h |
| | | eight) |
| | | |
n | def determine_placeholder(actual_size, expected_size): | n | def resolve_placeholder(img_size_actual, img_size_expected): |
| if actual_size == expected_size + 2: | | if img_size_actual == img_size_expected + 2: |
| return 2 | | return 2 |
n | if actual_size in {0, expected_size}: | n | if img_size_actual in {0, img_size_expected}: |
| return 0 | | return 0 |
| return None | | return None |
| if __name__ == '__main__': | | if __name__ == '__main__': |
n | bmp_data = read_bmp_data() | n | bmp_content = read_input_data() |
| file_validation = validate_bmp_header(bmp_data) | | header_validation = validate_header(bmp_content) |
| if isinstance(file_validation, str): | | if isinstance(header_validation, str): |
| print(file_validation) | | print(header_validation) |
| sys.exit(0) | | sys.exit(0) |
n | error, width, height, bits_per_pixel, compression_method, image_size | n | err_msg, img_w, img_h, bpp, compress, img_size = analyze_dib_header( |
| = parse_dib_header(bmp_data, 14) | | bmp_content, 14) |
| if error: | | if err_msg: |
| print(error) | | print(err_msg) |
| sys.exit(0) | | sys.exit(0) |
n | width_abs, height_abs, calculated_size = calculate_image_size(width, | n | width_abs, height_abs, computed_size = compute_image_size(img_w, img |
| height, bits_per_pixel) | | _h, bpp) |
| placeholder_size = determine_placeholder(image_size, calculated_size | | placeholder_result = resolve_placeholder(img_size, computed_size) |
| ) | | |
| if placeholder_size is None: | | if placeholder_result is None: |
| print('Incorrect image size') | | print('Incorrect image size') |
| sys.exit(0) | | sys.exit(0) |
t | print(f'{width_abs} {height_abs} {bits_per_pixel} {compression_metho | t | print(f'{width_abs} {height_abs} {bpp} {compress} {placeholder_resul |
| d} {placeholder_size}') | | t}') |