195 lines
7.4 KiB
Python
195 lines
7.4 KiB
Python
|
|
import os
|
||
|
|
from typing import Optional
|
||
|
|
|
||
|
|
from .dscl_types import *
|
||
|
|
from UniTAP.libs.lib_uicl.uicl_types import UICL_Image, UICL_ImageParameters
|
||
|
|
from UniTAP.libs.lib_helper import OS_Requirements, lib_method_wrapper
|
||
|
|
|
||
|
|
DSCL_CURRENT_VERSION = 1
|
||
|
|
DSCL = OS_Requirements("DSCL").get_lib()
|
||
|
|
DSCL_PATH = OS_Requirements("DSCL").get_path_to_lib()
|
||
|
|
DSC_TOOLS_FOLDER = os.path.dirname(DSCL_PATH)
|
||
|
|
|
||
|
|
|
||
|
|
def from_cstr(src_str):
|
||
|
|
try:
|
||
|
|
return src_str.value.decode('cp1252')
|
||
|
|
except BaseException:
|
||
|
|
return src_str.value.decode('utf-8')
|
||
|
|
|
||
|
|
|
||
|
|
class DSCLError(Exception):
|
||
|
|
def __init__(self, message, errors=None):
|
||
|
|
super().__init__(message)
|
||
|
|
self.errors = errors
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_GetRequiredBufferSize(image_to_encode: DSCL_Image):
|
||
|
|
_DSCL_GetRequiredBufferSize = lib_method_wrapper(DSCL.DSCL_GetRequiredBufferSize,
|
||
|
|
[POINTER(DSCL_Image)],
|
||
|
|
c_uint64)
|
||
|
|
|
||
|
|
return _DSCL_GetRequiredBufferSize(byref(image_to_encode))
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_GetRequiredBufferSizeFromPPS(pps: DSCL_PPS):
|
||
|
|
_DSCL_GetRequiredBufferSizeFromPPS = lib_method_wrapper(DSCL.DSCL_GetRequiredBufferSizeFromPPS,
|
||
|
|
[POINTER(DSCL_PPS)],
|
||
|
|
c_uint64)
|
||
|
|
|
||
|
|
return _DSCL_GetRequiredBufferSizeFromPPS(byref(pps))
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_Encode(image: UICL_Image, pps: DSCL_PPS) -> DSCL_Image:
|
||
|
|
_DSCL_Encode = lib_method_wrapper(DSCL.DSCL_Encode,
|
||
|
|
[POINTER(UICL_Image), POINTER(DSCL_PPS), POINTER(DSCL_Image),
|
||
|
|
POINTER(DSCL_EncoderConfig), c_char_p, c_int],
|
||
|
|
DSCL_RESULT)
|
||
|
|
|
||
|
|
max_enc_image_size = DSCL_GetRequiredBufferSizeFromPPS(pps)
|
||
|
|
|
||
|
|
if max_enc_image_size <= 132:
|
||
|
|
raise DSCLError("Failed to calculate buffer size for DSC encoding!")
|
||
|
|
|
||
|
|
encoded_image = DSCL_Image()
|
||
|
|
encoded_image.DataPtr = (c_uint8 * max_enc_image_size)()
|
||
|
|
encoded_image.DataSize = max_enc_image_size
|
||
|
|
|
||
|
|
_log_struct = DSCL_EncoderConfig()
|
||
|
|
_log_string_size = 65536
|
||
|
|
_log_string = create_string_buffer(_log_string_size)
|
||
|
|
|
||
|
|
result = _DSCL_Encode(byref(image), byref(pps), byref(encoded_image), byref(_log_struct),
|
||
|
|
_log_string, _log_string_size)
|
||
|
|
|
||
|
|
log = str(from_cstr(_log_string))
|
||
|
|
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Encoding finished with error: {result}. Error log: {log}", result)
|
||
|
|
|
||
|
|
return encoded_image
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_Decode(encoded_image: DSCL_Image, decode_simple422_to_444: Optional[bool] = False) -> UICL_Image:
|
||
|
|
_DSCL_Decode = lib_method_wrapper(DSCL.DSCL_Decode,
|
||
|
|
[POINTER(DSCL_Image), POINTER(UICL_Image),
|
||
|
|
POINTER(DSCL_DecoderConfig)],
|
||
|
|
DSCL_RESULT)
|
||
|
|
|
||
|
|
decoded_image = UICL_Image()
|
||
|
|
decoded_image.Parameters = UICL_ImageParameters()
|
||
|
|
decoded_image.DataPtr = POINTER(c_uint8)()
|
||
|
|
decoded_image.DataSize = 0
|
||
|
|
|
||
|
|
decoder_config = DSCL_DecoderConfig()
|
||
|
|
decoder_config.decodeSimple422to444 = False if decode_simple422_to_444 is None else decode_simple422_to_444
|
||
|
|
|
||
|
|
result = _DSCL_Decode(byref(encoded_image), byref(decoded_image), byref(decoder_config))
|
||
|
|
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Decoding failed with error code: {result}", result)
|
||
|
|
|
||
|
|
return decoded_image
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_ResultToString(result):
|
||
|
|
_DSCL_ResultToString = lib_method_wrapper(DSCL.DSCL_ResultToString,
|
||
|
|
[DSCL_RESULT, c_char_p, c_uint64],
|
||
|
|
c_uint64)
|
||
|
|
|
||
|
|
_error_string = create_string_buffer(1024)
|
||
|
|
_DSCL_ResultToString(result, _error_string, 1024)
|
||
|
|
return from_cstr(_error_string)
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_CalculateDSCCRC(image: DSCL_Image):
|
||
|
|
_DSCL_CalculateDSCCRC = lib_method_wrapper(DSCL.DSCL_CalculateDSCCRC,
|
||
|
|
[POINTER(DSCL_Image), POINTER(DSCL_CRC16)],
|
||
|
|
c_uint64)
|
||
|
|
crc_value = DSCL_CRC16()
|
||
|
|
result = _DSCL_CalculateDSCCRC(byref(image), byref(crc_value))
|
||
|
|
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Calculate DSC CRC: Failed to calculate CRC", result)
|
||
|
|
|
||
|
|
return crc_value
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_ExtractPPSFromData(data):
|
||
|
|
_DSCL_ExtractPPSFromData = lib_method_wrapper(DSCL.DSCL_ExtractPPSFromData,
|
||
|
|
[POINTER(c_uint8), c_uint64, POINTER(DSCL_PPS)],
|
||
|
|
c_uint64)
|
||
|
|
_pps = DSCL_PPS()
|
||
|
|
_size = len(data)
|
||
|
|
_data = (c_uint8 * _size)(*data)
|
||
|
|
result = _DSCL_ExtractPPSFromData(_data, _size, byref(_pps))
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Cannot extract PPS from data. Code: {result}")
|
||
|
|
|
||
|
|
return _pps
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_ExtractPPS(image: DSCL_Image):
|
||
|
|
_DSCL_ExtractPPS = lib_method_wrapper(DSCL.DSCL_ExtractPPS,
|
||
|
|
[POINTER(DSCL_Image), POINTER(DSCL_PPS)],
|
||
|
|
c_uint64)
|
||
|
|
_pps = DSCL_PPS()
|
||
|
|
result = _DSCL_ExtractPPS(byref(image), byref(_pps))
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Cannot extract PPS from DSCL Image. Code: {result}")
|
||
|
|
|
||
|
|
return _pps
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_VerifyPPS(image: DSCL_Image):
|
||
|
|
_DSCL_VerifyPPS = lib_method_wrapper(DSCL.DSCL_VerifyPPS,
|
||
|
|
[POINTER(DSCL_Image), c_char_p, c_uint64],
|
||
|
|
c_bool)
|
||
|
|
|
||
|
|
_error_string = create_string_buffer(1024)
|
||
|
|
return _DSCL_VerifyPPS(byref(image), _error_string, 1024)
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_GeneratePPS(decoded_image_parameters: UICL_ImageParameters,
|
||
|
|
is_simple_422: bool, is_block_prediction_enabled: bool, bits_per_pixel: int,
|
||
|
|
horizontal_slice_count: int, vertical_slice_count: int, buffer_bit_depth: int,
|
||
|
|
dsc_version: DSCL_DscVersion) -> DSCL_PPS:
|
||
|
|
_DSCL_GeneratePPS = lib_method_wrapper(DSCL.DSCL_GeneratePPS,
|
||
|
|
[POINTER(DSCL_PPS), POINTER(UICL_ImageParameters), c_bool, c_bool,
|
||
|
|
c_uint16, c_uint16, c_uint16, c_uint8, DSCL_DscVersion],
|
||
|
|
c_bool)
|
||
|
|
_pps = DSCL_PPS()
|
||
|
|
result = _DSCL_GeneratePPS(byref(_pps), byref(decoded_image_parameters), is_simple_422,
|
||
|
|
is_block_prediction_enabled, bits_per_pixel, horizontal_slice_count,
|
||
|
|
vertical_slice_count, buffer_bit_depth, dsc_version)
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Cannot generate PPS. Error code {result}")
|
||
|
|
|
||
|
|
return _pps
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_LoadFromFile(file_name: str) -> DSCL_RESULT:
|
||
|
|
_DSCL_LoadFromFile = lib_method_wrapper(DSCL.DSCL_LoadFromFile,
|
||
|
|
[c_char_p, POINTER(DSCL_Image)],
|
||
|
|
DSCL_Image)
|
||
|
|
image = DSCL_Image()
|
||
|
|
image.DataPtr = POINTER(c_uint8)()
|
||
|
|
image.DataSize = 0
|
||
|
|
|
||
|
|
result = _DSCL_LoadFromFile(c_char_p(file_name.encode('utf-8')), byref(image))
|
||
|
|
|
||
|
|
if result < DSCL_SUCCESS:
|
||
|
|
raise DSCLError(f"Cannot load image from file. Error code {result}.")
|
||
|
|
|
||
|
|
return result
|
||
|
|
|
||
|
|
|
||
|
|
def DSCL_FreeImage(image: DSCL_Image) -> DSCL_RESULT:
|
||
|
|
_DSCL_FreeImage = lib_method_wrapper(DSCL.DSCL_FreeImage,
|
||
|
|
[POINTER(POINTER(DSCL_Image))],
|
||
|
|
c_uint64)
|
||
|
|
|
||
|
|
result = _DSCL_FreeImage(byref(byref(image)))
|
||
|
|
|
||
|
|
return result
|