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