Add ktx
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
# 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))
|
||||
Reference in New Issue
Block a user