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