60 lines
1.5 KiB
Python
60 lines
1.5 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# ev-to-dicom
|
||
|
# Copyright © 2023 Lee Yingtong Li
|
||
|
#
|
||
|
# This program is free software: you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU Affero General Public License as published by
|
||
|
# the Free Software Foundation, either version 3 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU Affero General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU Affero General Public License
|
||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
|
||
|
import msgpack
|
||
|
|
||
|
from collections import OrderedDict
|
||
|
|
||
|
def read_ev_tlv(data: bytes):
|
||
|
"""Read an Enhanced Viewer tag-length-value image payload"""
|
||
|
|
||
|
i = 0
|
||
|
|
||
|
def read_u16():
|
||
|
nonlocal i
|
||
|
i += 2
|
||
|
return (data[i - 2] << 8) | data[i - 1]
|
||
|
|
||
|
def read_u32():
|
||
|
nonlocal i
|
||
|
i += 4
|
||
|
return (data[i - 4] << 24) | (data[i - 3] << 16) | (data[i - 2] << 8) | data[i - 1]
|
||
|
|
||
|
metadata = OrderedDict()
|
||
|
pixel_data = None
|
||
|
|
||
|
while i < len(data):
|
||
|
typ = read_u16()
|
||
|
if typ == 0x0101:
|
||
|
length = read_u32()
|
||
|
|
||
|
payload = msgpack.unpackb(data[i:i+length])
|
||
|
metadata.update(payload)
|
||
|
|
||
|
i += length
|
||
|
elif typ == 0x0202:
|
||
|
length = read_u32()
|
||
|
|
||
|
payload = data[i:i+length]
|
||
|
pixel_data = payload
|
||
|
|
||
|
i += length
|
||
|
else:
|
||
|
raise Exception('Unknown type 0x{:04x}'.format(typ))
|
||
|
|
||
|
return metadata, pixel_data
|