from UniTAP.common import VideoMode, VideoFrame, ColorInfo, Timing, ImageFileFormat, DataInfo from .uicl_types import UICL_Image, UICL_ImageParameters, UICL_Colorimetry, UICL_Sampling,\ UICL_Colorspace, UICL_Packing, UICL_Alignment, UICL_ComponentOrder, UICL_SUCCESS,\ UICL_ImageFileFormat from .uicl import UICL_Convert, UICL_GetRequiredBufferSize, UICL_SaveToFile, UICL_CRC16, UICL_CalculateCRC16 from typing import Tuple from ctypes import c_uint8 def uicl_cf_from_vm(color_format: ColorInfo.ColorFormat) -> UICL_Colorspace: if color_format == ColorInfo.ColorFormat.CF_RGB: return UICL_Colorspace.Colorspace_RGB elif color_format in [ColorInfo.ColorFormat.CF_YCbCr_444, ColorInfo.ColorFormat.CF_YCbCr_422, ColorInfo.ColorFormat.CF_YCbCr_420]: return UICL_Colorspace.Colorspace_YCbCr else: return UICL_Colorspace.Colorspace_Unknown def uicl_sampling_from_vm(color_format: ColorInfo.ColorFormat) -> UICL_Sampling: if color_format in [ColorInfo.ColorFormat.CF_RGB, ColorInfo.ColorFormat.CF_YCbCr_444]: return UICL_Sampling.Sampling_444 elif color_format == ColorInfo.ColorFormat.CF_YCbCr_422: return UICL_Sampling.Sampling_422 elif color_format == ColorInfo.ColorFormat.CF_YCbCr_420: return UICL_Sampling.Sampling_420 else: return UICL_Sampling.Sampling_Unknown def uicl_colorimetry_from_ci_colorimetry(colorimetry: ColorInfo.Colorimetry) -> UICL_Colorimetry: if colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT601: return UICL_Colorimetry.Colorimetry_ITU_R_BT601 elif colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT709: return UICL_Colorimetry.Colorimetry_ITU_R_BT709 elif colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT2020_YCbCr: return UICL_Colorimetry.Colorimetry_ITU_R_BT2020 else: return UICL_Colorimetry.Colorimetry_Unknown def uicl_colorimetry_to_ci_colorimetry(colorimetry: UICL_Colorimetry) -> ColorInfo.Colorimetry: if colorimetry == UICL_Colorimetry.Colorimetry_ITU_R_BT601: return ColorInfo.Colorimetry.CM_ITUR_BT601 elif colorimetry == UICL_Colorimetry.Colorimetry_ITU_R_BT709: return ColorInfo.Colorimetry.CM_ITUR_BT709 elif colorimetry == UICL_Colorimetry.Colorimetry_ITU_R_BT2020: return ColorInfo.Colorimetry.CM_ITUR_BT2020_YCbCr else: return ColorInfo.Colorimetry.CM_NONE def uicl_parameters_from_vm(vm: VideoMode) -> UICL_ImageParameters: parameters = UICL_ImageParameters() parameters.Width = vm.timing.hactive parameters.Height = vm.timing.vactive parameters.BitsPerColor = vm.color_info.bpc parameters.Colorimetry = uicl_colorimetry_from_ci_colorimetry(vm.color_info.colorimetry) if vm.color_info.color_format == ColorInfo.ColorFormat.CF_RGB: parameters.Colorspace = UICL_Colorspace.Colorspace_RGB parameters.ComponentOrder = UICL_ComponentOrder.Order_RGB parameters.Sampling = UICL_Sampling.Sampling_444 parameters.Packing = UICL_Packing.Packing_Packed parameters.Alignment = UICL_Alignment.Alignment_LSB parameters.IsFullRange = vm.color_info.DynamicRange == ColorInfo.DynamicRange.DR_VESA elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_444: parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr parameters.ComponentOrder = UICL_ComponentOrder.Order_YCbCr parameters.Sampling = UICL_Sampling.Sampling_444 parameters.Packing = UICL_Packing.Packing_Packed parameters.Alignment = UICL_Alignment.Alignment_LSB parameters.IsFullRange = False elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_422: parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr parameters.ComponentOrder = UICL_ComponentOrder.Order_CbY0CrY1 parameters.Sampling = UICL_Sampling.Sampling_422 parameters.Packing = UICL_Packing.Packing_Packed parameters.Alignment = UICL_Alignment.Alignment_LSB parameters.IsFullRange = False elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_420: parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr parameters.ComponentOrder = UICL_ComponentOrder.Order_YCbCr parameters.Sampling = UICL_Sampling.Sampling_420 parameters.Packing = UICL_Packing.Packing_Planar parameters.Alignment = UICL_Alignment.Alignment_LSB parameters.IsFullRange = False return parameters def uicl_image_from_vm_and_data(video_mode: VideoMode, data: bytearray) -> UICL_Image: image = UICL_Image() image.DataPtr = (c_uint8 * len(data))(*data) image.DataSize = len(data) image.Parameters = uicl_parameters_from_vm(video_mode) return image def uicl_image_convert_to_vm(src_image: UICL_Image, video_mode: VideoMode) -> bytearray: dest_image = UICL_Image() dest_image.Parameters = uicl_parameters_from_vm(video_mode) result = UICL_GetRequiredBufferSize(dest_image) assert result >= UICL_SUCCESS, f"Calculation required buffer size failed with error {result}" dest_image.DataPtr = (c_uint8 * result)() dest_image.DataSize = result result = UICL_Convert(src_image, dest_image) assert result == UICL_SUCCESS, f"Image conversion failed with error {result}" return bytearray(dest_image.DataPtr[:dest_image.DataSize]) def image_from_vf(video_frame: VideoFrame) -> UICL_Image: image = UICL_Image() image.Parameters = image_params_from_size_and_ci(video_frame.width, video_frame.height, video_frame.color_info, video_frame.data_info) image.DataSize = len(video_frame.data) image.DataPtr = (c_uint8 * len(video_frame.data)).from_buffer(video_frame.data) return image def image_to_vf(image: UICL_Image) -> VideoFrame: video_frame = VideoFrame() video_frame.width, video_frame.height, video_frame.color_info, video_frame.data_info = image_params_to_size_and_ci(image.Parameters) video_frame.data = bytearray(image.DataPtr[:image.DataSize]) return video_frame def uicl_image_calculate_crc(src_vf: VideoFrame) -> tuple: crc = UICL_CRC16() src_image = image_from_vf(src_vf) result = UICL_CalculateCRC16(src_image, crc) assert result >= UICL_SUCCESS, f"Calculation CRC failed with error {result}" return crc.R, crc.G, crc.B def image_params_to_vm(image_params: UICL_ImageParameters) -> VideoMode: pass def image_params_to_size_and_ci(image_params: UICL_ImageParameters) -> Tuple[int, int, ColorInfo, DataInfo]: width = image_params.Width height = image_params.Height color_info = ColorInfo() color_info.bpc = image_params.BitsPerColor color_info.colorimetry = uicl_colorimetry_to_ci_colorimetry(image_params.Colorimetry) color_info.dynamic_range = ColorInfo.DynamicRange.DR_VESA if image_params.IsFullRange else ColorInfo.DynamicRange.DR_CTA if image_params.Colorspace == UICL_Colorspace.Colorspace_RGB: color_info.color_format = ColorInfo.ColorFormat.CF_RGB elif image_params.Colorspace == UICL_Colorspace.Colorspace_YCbCr: if image_params.Sampling == UICL_Sampling.Sampling_444: color_info.color_format = ColorInfo.ColorFormat.CF_YCbCr_444 elif image_params.Sampling == UICL_Sampling.Sampling_422: color_info.color_format = ColorInfo.ColorFormat.CF_YCbCr_422 elif image_params.Sampling == UICL_Sampling.Sampling_420: color_info.color_format = ColorInfo.ColorFormat.CF_YCbCr_420 else: color_info.color_format = ColorInfo.ColorFormat.CF_UNKNOWN elif image_params.Colorspace == UICL_Colorspace.Colorspace_Y: color_info.color_format = ColorInfo.ColorFormat.CF_Y_ONLY elif image_params.Colorspace == UICL_Colorspace.Colorspace_Raw: color_info.color_format = ColorInfo.ColorFormat.CF_RAW data_info = DataInfo() data_info.alignment = uicl_alignment_to_vf_alignment(image_params.Alignment) data_info.component_order = uicl_com_order_to_vf_com_order(image_params.ComponentOrder) data_info.packing = uicl_packing_to_vf_packing(image_params.Packing) return width, height, color_info, data_info def vf_com_order_to_uicl_com_order(component_order: DataInfo.ComponentOrder) -> UICL_ComponentOrder: if component_order == DataInfo.ComponentOrder.CO_UCDRX: return UICL_ComponentOrder.Order_UCDRX elif component_order == DataInfo.ComponentOrder.CO_RGB: return UICL_ComponentOrder.Order_RGB elif component_order == DataInfo.ComponentOrder.CO_RGBA: return UICL_ComponentOrder.Order_RGBA elif component_order == DataInfo.ComponentOrder.CO_BGR: return UICL_ComponentOrder.Order_BGR elif component_order == DataInfo.ComponentOrder.CO_BGRA: return UICL_ComponentOrder.Order_BGRA elif component_order == DataInfo.ComponentOrder.CO_YCbCr: return UICL_ComponentOrder.Order_YCbCr elif component_order == DataInfo.ComponentOrder.CO_CbY0CrY1: return UICL_ComponentOrder.Order_CbY0CrY1 else: return UICL_ComponentOrder.Order_Unknown def uicl_com_order_to_vf_com_order(component_order: UICL_ComponentOrder) -> DataInfo.ComponentOrder: if component_order == UICL_ComponentOrder.Order_UCDRX: return DataInfo.ComponentOrder.CO_UCDRX elif component_order == UICL_ComponentOrder.Order_RGB: return DataInfo.ComponentOrder.CO_RGB elif component_order == UICL_ComponentOrder.Order_RGBA: return DataInfo.ComponentOrder.CO_RGBA elif component_order == UICL_ComponentOrder.Order_BGR: return DataInfo.ComponentOrder.CO_BGR elif component_order == UICL_ComponentOrder.Order_BGRA: return DataInfo.ComponentOrder.CO_BGRA elif component_order == UICL_ComponentOrder.Order_YCbCr: return DataInfo.ComponentOrder.CO_YCbCr elif component_order == UICL_ComponentOrder.Order_CbY0CrY1: return DataInfo.ComponentOrder.CO_CbY0CrY1 else: return DataInfo.ComponentOrder.CO_UNKNOWN def vf_packing_to_uicl_packing(packing: DataInfo.Packing) -> UICL_Packing: if packing == DataInfo.Packing.P_PLANAR: return UICL_Packing.Packing_Planar elif packing == DataInfo.Packing.P_PACKED: return UICL_Packing.Packing_Packed else: return UICL_Packing.Packing_Unknown def uicl_packing_to_vf_packing(packing: UICL_Packing) -> DataInfo.Packing: if packing == UICL_Packing.Packing_Planar: return DataInfo.Packing.P_PLANAR elif packing == UICL_Packing.Packing_Packed: return DataInfo.Packing.P_PACKED else: return DataInfo.Packing.P_UNKNOWN def vf_alignment_to_uicl_alignment(alignment: DataInfo.Alignment) -> UICL_Alignment: if alignment == DataInfo.Alignment.A_LSB: return UICL_Alignment.Alignment_LSB elif alignment == DataInfo.Alignment.A_MSB: return UICL_Alignment.Alignment_MSB else: return UICL_Alignment.Alignment_Unknown def uicl_alignment_to_vf_alignment(alignment: UICL_Alignment) -> DataInfo.Alignment: if alignment == UICL_Alignment.Alignment_LSB: return DataInfo.Alignment.A_LSB elif alignment == UICL_Alignment.Alignment_MSB: return DataInfo.Alignment.A_MSB else: return DataInfo.Alignment.A_UNKNOWN def image_params_from_vm(video_mode: VideoMode) -> UICL_ImageParameters: pass def image_params_from_size_and_ci(width: int, height: int, color_info: ColorInfo, data_info: DataInfo) -> UICL_ImageParameters: parameters = UICL_ImageParameters() parameters.Width = width parameters.Height = height parameters.BitsPerColor = color_info.bpc parameters.Colorimetry = uicl_colorimetry_from_ci_colorimetry(color_info.colorimetry) parameters.ComponentOrder = vf_com_order_to_uicl_com_order(data_info.component_order) parameters.Packing = vf_packing_to_uicl_packing(data_info.packing) parameters.Alignment = vf_alignment_to_uicl_alignment(data_info.alignment) if color_info.color_format == ColorInfo.ColorFormat.CF_RGB: parameters.Colorspace = UICL_Colorspace.Colorspace_RGB parameters.Sampling = UICL_Sampling.Sampling_444 parameters.IsFullRange = color_info.DynamicRange == ColorInfo.DynamicRange.DR_VESA elif color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_444: parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr parameters.Sampling = UICL_Sampling.Sampling_444 parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False elif color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_422: parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr parameters.Sampling = UICL_Sampling.Sampling_422 parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False elif color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_420: parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr parameters.Sampling = UICL_Sampling.Sampling_420 parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False else: parameters.Colorspace = UICL_Colorspace.Colorspace_Unknown parameters.Sampling = UICL_Sampling.Sampling_Unknown parameters.IsFullRange = True if data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX else False return parameters def image_convert_to_parameters(src_image: UICL_Image, parameters: UICL_ImageParameters) -> UICL_Image: dst_image = UICL_Image() dst_image.Parameters = parameters result = UICL_GetRequiredBufferSize(dst_image) assert result >= UICL_SUCCESS, f"Calculation required buffer size failed with error {result}" dst_image.DataSize = result dst_image.DataPtr = (c_uint8 * result)() result = UICL_Convert(src_image, dst_image) assert result >= UICL_SUCCESS, f"Image conversion failed with error {result}" return dst_image def image_save_to_file(image: UICL_Image, path: str, image_format: UICL_ImageFileFormat) -> bool: return UICL_SaveToFile(image, path, image_format)