213 lines
10 KiB
Python
213 lines
10 KiB
Python
# Copyright (c) 2023, Shukant Pal and Contributors
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from .ktx_astc_params import KtxAstcParams
|
|
from .ktx_basis_params import KtxBasisParams
|
|
from .ktx_error_code import KtxErrorCode, KtxError
|
|
from .ktx_supercmp_scheme import KtxSupercmpScheme
|
|
from .ktx_texture import KtxTexture, KtxVersionMismatchError
|
|
from .ktx_texture_create_flag_bits import KtxTextureCreateFlagBits
|
|
from .ktx_texture_create_info import KtxTextureCreateInfo
|
|
from .ktx_texture_create_storage import KtxTextureCreateStorage
|
|
from .ktx_transcode_fmt import KtxTranscodeFmt
|
|
from pyktx.native import ffi, lib
|
|
from typing import Union
|
|
from .vk_format import VkFormat
|
|
|
|
|
|
class KtxTexture2(KtxTexture):
|
|
"""Class representing a KTX version 2 format texture."""
|
|
|
|
@staticmethod
|
|
def create(create_info: KtxTextureCreateInfo, storage_allocation: KtxTextureCreateStorage) -> 'KtxTexture2':
|
|
"""Create a new empty KtxTexture2."""
|
|
|
|
result = lib.PY_ktxTexture2_Create(0,
|
|
create_info.vk_format.value,
|
|
ffi.NULL,
|
|
create_info.base_width,
|
|
create_info.base_height,
|
|
create_info.base_depth,
|
|
create_info.num_dimensions,
|
|
create_info.num_levels,
|
|
create_info.num_layers,
|
|
create_info.num_faces,
|
|
create_info.is_array,
|
|
create_info.generate_mipmaps,
|
|
storage_allocation.value)
|
|
|
|
if int(result.error) != KtxErrorCode.SUCCESS:
|
|
raise KtxError('ktxTexture2_Create', KtxErrorCode(result.error))
|
|
|
|
return KtxTexture2(result.texture)
|
|
|
|
@staticmethod
|
|
def create_from_named_file(filename: str,
|
|
create_flags: int = KtxTextureCreateFlagBits.LOAD_IMAGE_DATA_BIT) -> 'KtxTexture2':
|
|
"""Create a KtxTexture2 from a named KTX file."""
|
|
|
|
result = lib.PY_ktxTexture_CreateFromNamedFile(filename.encode("ascii"), int(create_flags))
|
|
|
|
if int(result.error) != KtxErrorCode.SUCCESS:
|
|
raise KtxError('ktxTexture2_CreateFromNamedFile', KtxErrorCode(result.error))
|
|
|
|
texture = KtxTexture2(result.texture)
|
|
|
|
if texture.class_id != 2:
|
|
raise KtxVersionMismatchError('The provided file ' + filename + ' is not a KTX2 file')
|
|
|
|
return texture
|
|
|
|
@property
|
|
def vk_format(self) -> VkFormat:
|
|
"""VkFormat for texture."""
|
|
|
|
return VkFormat(lib.PY_ktxTexture2_get_vkFormat(self._ptr))
|
|
|
|
@property
|
|
def supercompression_scheme(self) -> KtxSupercmpScheme:
|
|
"""The supercompression scheme used to compress the texture data."""
|
|
|
|
return KtxSupercmpScheme(lib.PY_ktxTexture2_get_supercompressionScheme(self._ptr))
|
|
|
|
@property
|
|
def oetf(self) -> int:
|
|
"""The opto-electrical transfer function of the images."""
|
|
|
|
return lib.ktxTexture2_GetOETF(self._ptr)
|
|
|
|
@property
|
|
def premultipled_alpha(self) -> bool:
|
|
"""Whether the RGB components have been premultiplied by the alpha component."""
|
|
|
|
return lib.ktxTexture2_GetPremultipliedAlpha(self._ptr)
|
|
|
|
@property
|
|
def needs_transcoding(self) -> bool:
|
|
"""If the images are in a transcodable format."""
|
|
|
|
return lib.ktxTexture2_NeedsTranscoding(self._ptr)
|
|
|
|
def compress_astc(self, params: Union[int, KtxAstcParams]) -> None:
|
|
"""
|
|
Encode and compress a ktx texture with uncompressed images to ASTC.
|
|
|
|
The images are either encoded to ASTC block-compressed format. The
|
|
encoded images replace the original images and the texture's fields
|
|
including the dfd are modified to reflect the new state.
|
|
|
|
Such textures can be directly uploaded to a GPU via a graphics API.
|
|
"""
|
|
|
|
if isinstance(params, int):
|
|
quality = params
|
|
params = KtxAstcParams()
|
|
params.quality_level = quality
|
|
|
|
error = lib.PY_ktxTexture2_CompressAstcEx(self._ptr,
|
|
params.verbose,
|
|
params.thread_count,
|
|
int(params.block_dimension),
|
|
int(params.mode),
|
|
params.quality_level,
|
|
params.normal_map,
|
|
params.perceptual,
|
|
params.input_swizzle)
|
|
|
|
if int(error) != KtxErrorCode.SUCCESS:
|
|
raise KtxError('ktxTexture2_compressAstcEx', KtxErrorCode(error))
|
|
|
|
def compress_basis(self, params: Union[int, KtxBasisParams]) -> None:
|
|
"""
|
|
Supercompress a KTX2 texture with uncompressed images.
|
|
|
|
The images are either encoded to ETC1S block-compressed format and supercompressed
|
|
with Basis LZ or they are encoded to UASTC block-compressed format. UASTC format is
|
|
selected by setting the uastc field of params to true. The encoded images replace
|
|
the original images and the texture's fields including the DFD are modified to reflect
|
|
the new state. Such textures must be transcoded to a desired target block compressed
|
|
format before they can be uploaded to a GPU via a graphics API.
|
|
"""
|
|
|
|
if isinstance(params, int):
|
|
quality = params
|
|
params = KtxBasisParams()
|
|
params.quality_level = quality
|
|
|
|
error = lib.PY_ktxTexture2_CompressBasisEx(self._ptr,
|
|
params.uastc,
|
|
params.verbose,
|
|
params.no_sse,
|
|
params.thread_count,
|
|
params.compression_level,
|
|
params.quality_level,
|
|
params.max_endpoints,
|
|
params.endpoint_rdo_threshold,
|
|
params.max_selectors,
|
|
params.selector_rdo_threshold,
|
|
params.input_swizzle,
|
|
params.normal_map,
|
|
params.pre_swizzle,
|
|
params.separate_rg_to_rgb_a,
|
|
params.no_endpoint_rdo,
|
|
params.no_selector_rdo,
|
|
params.uastc_flags,
|
|
params.uastc_rdo,
|
|
params.uastc_rdo_quality_scalar,
|
|
params.uastc_rdo_dict_size,
|
|
params.uastc_rdo_max_smooth_block_error_scale,
|
|
params.uastc_rdo_max_smooth_block_std_dev,
|
|
params.uastc_rdo_dont_favor_simpler_modes,
|
|
params.uastc_rdo_no_multithreading)
|
|
|
|
if int(error) != KtxErrorCode.SUCCESS:
|
|
raise KtxError('ktxTexture2_CompressBasisEx', KtxErrorCode(error))
|
|
|
|
def deflate_zstd(self, compression_level: int) -> None:
|
|
"""
|
|
Deflate the data in a ktxTexture2 object using Zstandard.
|
|
|
|
The texture's level_index, data_size, dfd and supercompression_scheme will all
|
|
be updated after successful deflation to reflect the deflated data.
|
|
"""
|
|
|
|
if not 1 <= compression_level <= 22:
|
|
raise ValueError("compression_level must be between 1 and 22")
|
|
|
|
error = lib.ktxTexture2_DeflateZstd(self._ptr, compression_level)
|
|
|
|
if int(error) != KtxErrorCode.SUCCESS:
|
|
raise KtxError('ktx2_DeflateZstd', KtxErrorCode(error))
|
|
|
|
def transcode_basis(self, output_format: KtxTranscodeFmt, transcode_flags: int = 0) -> None:
|
|
"""
|
|
Transcode a KTX2 texture with BasisLZ/ETC1S or UASTC images.
|
|
|
|
If the texture contains BasisLZ supercompressed images, inflates them from back to
|
|
ETC1S then transcodes them to the specified block-compressed format. If the texture
|
|
contains UASTC images, inflates them, if they have been supercompressed with zstd, then
|
|
transcodes then to the specified format, The transcoded images replace the original images
|
|
and the texture's fields including the dfd are modified to reflect the new format.
|
|
|
|
These types of textures must be transcoded to a desired target block-compressed format
|
|
before they can be uploaded to a GPU via a graphics API.
|
|
|
|
The following block compressed transcode targets (KtxTranscodeFmt) are available: ETC1_RGB,
|
|
ETC2_RGBA, BC1_RGB, BC3_RGBA, BC4_R, BC5_RG, BC7_RGBA, PVRTC1_4_RGB, PVRTC1_4_RGBA,
|
|
PVRTC2_4_RGB, PVRTC2_4_RGBA, ASTC_4x4_RGBA, ETC2_EAC_R11, ETC2_EAC_RG11, ETC and BC1_OR_3.
|
|
|
|
ETC automatically selects between ETC1_RGB and ETC2_RGBA according to whether an alpha
|
|
channel is available. BC1_OR_3 does likewise between BC1_RGB and BC3_RGBA. Note that if
|
|
PVRTC1_4_RGBA or PVRTC2_4_RGBA is specified and there is no alpha channel PVRTC1_4_RGB
|
|
or PVRTC2_4_RGB respectively will be selected.
|
|
|
|
Transcoding to ATC & FXT1 formats is not supported by libktx as there are no equivalent Vulkan formats.
|
|
|
|
The following uncompressed transcode targets are also available: RGBA32, RGB565, BGR565 and RGBA4444.
|
|
"""
|
|
|
|
error = lib.ktxTexture2_TranscodeBasis(self._ptr, output_format, transcode_flags)
|
|
|
|
if int(error) != KtxErrorCode.SUCCESS:
|
|
raise KtxError('ktx2_TranscodeBasis', KtxErrorCode(error))
|