Абдикашева Вилена Ринатовна, 411 группа BmpParser 16302
Алдабергенов Руслан Даниярович, 411 BmpParser 16038
f1import sysf1import sys
22
n3def read_input_data():n3def read_bmp_data():
4    return sys.stdin.buffer.read()4    return sys.stdin.buffer.read()
55
n6def validate_header(data):n6def validate_bmp_header(data):
7    if len(data) < 14:7    if len(data) < 14:
n8        return 'Invalid file size'n8        return 'Incorrect size'
9    if data[:2] != b'BM':9    if data[:2] != b'BM':
10        return 'Not a Windows BMP'10        return 'Not a Windows BMP'
n11    total_size = int.from_bytes(data[2:6], 'little')n11    file_size = int.from_bytes(data[2:6], 'little')
12    if total_size != len(data):12    if file_size != len(data):
13        return 'Incorrect size'13        return 'Incorrect size'
14    if len(data) < 18:14    if len(data) < 18:
n15        return 'Incomplete BMP header'n15        return 'Incorrect size'
16    return total_size16    return file_size
1717
n18def analyze_dib_header(data, start_offset):n18def parse_dib_header(data, offset):
19    dib_size = int.from_bytes(data[start_offset:start_offset + 4], 'litt19    header_size = int.from_bytes(data[offset:offset + 4], 'little')
>le') 
20    valid_sizes = [12, 16, 40, 52, 56, 64, 108, 124]20    valid_sizes = [12, 16, 40, 52, 56, 64, 108, 124]
n21    if dib_size not in valid_sizes:n21    if header_size not in valid_sizes:
22        return ('Incorrect header size', None, None, None, None, None)22        return ('Incorrect header size', None, None, None, None, None)
n23    dib_end = start_offset + dib_sizen23    end_offset = offset + header_size
24    if len(data) < dib_end:24    if len(data) < end_offset:
25        return ('Incomplete DIB header', None, None, None, None, None)25        return ('Incorrect size', None, None, None, None, None)
26    if dib_size == 12:26    if header_size == 12:
27        img_width = int.from_bytes(data[start_offset + 4:start_offset + 27        width = int.from_bytes(data[offset + 4:offset + 6], 'little')
>6], 'little') 
28        img_height = int.from_bytes(data[start_offset + 6:start_offset +28        height = int.from_bytes(data[offset + 6:offset + 8], 'little')
> 8], 'little') 
29        bpp = int.from_bytes(data[start_offset + 10:start_offset + 12], 29        bpp = int.from_bytes(data[offset + 10:offset + 12], 'little')
>'little') 
30        compression = 030        compression = 0
n31        img_size = 0n31        image_size = 0
32    elif dib_size == 16:32    elif header_size == 16:
33        img_width = int.from_bytes(data[start_offset + 4:start_offset + 33        width = int.from_bytes(data[offset + 4:offset + 6], 'little', si
>6], 'little', signed=True)>gned=True)
34        img_height = int.from_bytes(data[start_offset + 6:start_offset +34        height = int.from_bytes(data[offset + 6:offset + 8], 'little', s
> 8], 'little', signed=True)>igned=True)
35        bpp = int.from_bytes(data[start_offset + 10:start_offset + 12], 35        bpp = int.from_bytes(data[offset + 10:offset + 12], 'little')
>'little') 
36        compression = int.from_bytes(data[start_offset + 12:start_offset36        compression = int.from_bytes(data[offset + 12:offset + 16], 'lit
> + 16], 'little')>tle')
37        img_size = 037        image_size = 0
38    else:38    else:
n39        img_width = int.from_bytes(data[start_offset + 4:start_offset + n39        width = int.from_bytes(data[offset + 4:offset + 8], 'little', si
>8], 'little', signed=True)>gned=True)
40        img_height = int.from_bytes(data[start_offset + 8:start_offset +40        height = int.from_bytes(data[offset + 8:offset + 12], 'little', 
> 12], 'little', signed=True)>signed=True)
41        bpp = int.from_bytes(data[start_offset + 14:start_offset + 16], 41        bpp = int.from_bytes(data[offset + 14:offset + 16], 'little')
>'little') 
42        compression = int.from_bytes(data[start_offset + 16:start_offset42        compression = int.from_bytes(data[offset + 16:offset + 20], 'lit
> + 20], 'little')>tle')
43        img_size = int.from_bytes(data[start_offset + 20:start_offset + 43        image_size = int.from_bytes(data[offset + 20:offset + 24], 'litt
>24], 'little')>le')
44    return (None, img_width, img_height, bpp, compression, img_size)44    return (None, width, height, bpp, compression, image_size)
4545
n46def compute_image_size(width, height, bits_per_pixel):n46def calculate_image_size(width, height, bpp):
47    absolute_width = abs(width)47    abs_width = abs(width)
48    absolute_height = abs(height)48    abs_height = abs(height)
49    bits_in_row = absolute_width * bits_per_pixel49    bits_per_row = abs_width * bpp
50    bytes_in_row = (bits_in_row + 7) // 850    bytes_per_row = (bits_per_row + 7) // 8
51    row_padding = (4 - bytes_in_row % 4) % 451    padding = (4 - bytes_per_row % 4) % 4
52    total_row_size = bytes_in_row + row_padding52    total_row_bytes = bytes_per_row + padding
53    return (absolute_width, absolute_height, total_row_size * absolute_h53    return (abs_width, abs_height, total_row_bytes * abs_height)
>eight) 
5454
n55def resolve_placeholder(img_size_actual, img_size_expected):n55def determine_placeholder(actual_size, expected_size):
56    if img_size_actual == img_size_expected + 2:56    if actual_size == expected_size + 2:
57        return 257        return 2
n58    if img_size_actual in {0, img_size_expected}:n58    if actual_size in {0, expected_size}:
59        return 059        return 0
60    return None60    return None
61if __name__ == '__main__':61if __name__ == '__main__':
n62    bmp_content = read_input_data()n62    bmp_data = read_bmp_data()
63    header_validation = validate_header(bmp_content)63    file_validation = validate_bmp_header(bmp_data)
64    if isinstance(header_validation, str):64    if isinstance(file_validation, str):
65        print(header_validation)65        print(file_validation)
66        sys.exit(0)66        sys.exit(0)
n67    err_msg, img_w, img_h, bpp, compress, img_size = analyze_dib_header(n67    error, width, height, bits_per_pixel, compression_method, image_size
>bmp_content, 14)> = parse_dib_header(bmp_data, 14)
68    if err_msg:68    if error:
69        print(err_msg)69        print(error)
70        sys.exit(0)70        sys.exit(0)
n71    width_abs, height_abs, computed_size = compute_image_size(img_w, imgn71    width_abs, height_abs, calculated_size = calculate_image_size(width,
>_h, bpp)> height, bits_per_pixel)
72    placeholder_result = resolve_placeholder(img_size, computed_size)72    placeholder_size = determine_placeholder(image_size, calculated_size
 >)
73    if placeholder_result is None:73    if placeholder_size is None:
74        print('Incorrect image size')74        print('Incorrect image size')
75        sys.exit(0)75        sys.exit(0)
t76    print(f'{width_abs} {height_abs} {bpp} {compress} {placeholder_result76    print(f'{width_abs} {height_abs} {bits_per_pixel} {compression_metho
>t}')>d} {placeholder_size}')
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op