summaryrefslogtreecommitdiff
path: root/src/infiray_irg.py
blob: 80d04b3838be91b77951f476b9e62bee351e05e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from PIL import Image
import numpy as np
import struct
import io

def load(data):
    def consume(n):
        nonlocal data
        out, data = data[:n], data[n:]
        if len(out) < n:
            raise ValueError(f'File is truncated, tried to read {n} bytes, but only {len(out)} bytes remain.')
        return out
        
    header = consume(128)
    if header[:2] not in [
            bytes([0xca, 0xac]),
            bytes([0xba, 0xab])
            ] or header[-2:] != bytes([0xac, 0xca]):
        raise ValueError('Header magic not found.')

    _unk0, coarse_section_length, y_res, x_res,\
    _zero0, _unk1, _zero1, fine_offset, _unk2, jpeg_length,\
    y_res_2, x_res_2, _unk3, = struct.unpack('<HIHHHHHHHIHHI', header[2:34])

    _zero_celsius0, _zero_celsius1, *rest, high_gain_mode_flag = struct.unpack('<11I', header[34:78])
    
    if (x_res, y_res) != (x_res_2, y_res_2):
        raise ValueError(f'Resolution mismatch in header: {x_res}*{y_res} != {x_res_2}*{y_res_2}')

    if x_res*y_res != coarse_section_length:
        raise ValueError('Resolution mismatch in header')
        
    coarse_img = np.frombuffer(consume(coarse_section_length), dtype=np.uint8).reshape((y_res, x_res))
    if header[:2] == bytes([0xca, 0xac]):
        # 1/16th Kelvin steps
        fine_img = np.frombuffer(consume(x_res*y_res*2), dtype=np.uint16).reshape((y_res, x_res))
        fine_img = (fine_img / 16) - 273

        vis_jpg = Image.open(io.BytesIO(consume(jpeg_length)))

    else: # 0xbaac variant
        # 0.1 Kelvin steps
        fine_img = np.frombuffer(consume(x_res*y_res*2), dtype=np.uint16).reshape((y_res, x_res))
        fine_img = fine_img / 10 - 273

        vis_jpg = Image.open(io.BytesIO(data))
    
    return coarse_img, fine_img, vis_jpg