mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-06-08 00:23:52 +00:00
adding new files
This commit is contained in:
5667
encoder/basisu_astc_ldr_common.cpp
Normal file
5667
encoder/basisu_astc_ldr_common.cpp
Normal file
File diff suppressed because it is too large
Load Diff
445
encoder/basisu_astc_ldr_common.h
Normal file
445
encoder/basisu_astc_ldr_common.h
Normal file
@@ -0,0 +1,445 @@
|
||||
// File: basisu_astc_ldr_common.h
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_gpu_texture.h"
|
||||
#include <array>
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
|
||||
namespace astc_ldr
|
||||
{
|
||||
const uint32_t ASTC_LDR_MAX_BLOCK_WIDTH = astc_helpers::MAX_BLOCK_DIM; // 12
|
||||
const uint32_t ASTC_LDR_MAX_BLOCK_HEIGHT = astc_helpers::MAX_BLOCK_DIM; // 12
|
||||
const uint32_t ASTC_LDR_MAX_BLOCK_PIXELS = astc_helpers::MAX_BLOCK_PIXELS; // 144
|
||||
const uint32_t ASTC_LDR_MAX_RAW_WEIGHTS = astc_helpers::MAX_WEIGHT_INTERPOLANT_VALUE + 1; // 65
|
||||
|
||||
const uint32_t WEIGHT_REFINER_MAX_PASSES = 17;
|
||||
|
||||
inline basist::color_rgba convert_to_basist_color_rgba(const color_rgba& c)
|
||||
{
|
||||
return basist::color_rgba(c.r, c.g, c.b, c.a);
|
||||
}
|
||||
|
||||
struct cem_encode_params
|
||||
{
|
||||
uint32_t m_comp_weights[4];
|
||||
bool m_decode_mode_srgb; // todo: store astc_helpers::cDecodeModeSRGB8 : astc_helpers::cDecodeModeLDR8 instead, also the alpha mode for srgb because the decoders are broken
|
||||
|
||||
const uint8_t* m_pForced_weight_vals0;
|
||||
const uint8_t* m_pForced_weight_vals1;
|
||||
|
||||
uint32_t m_max_ls_passes, m_total_weight_refine_passes;
|
||||
bool m_worst_weight_nudging_flag;
|
||||
bool m_endpoint_refinement_flag;
|
||||
|
||||
cem_encode_params()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_comp_weights[0] = 1;
|
||||
m_comp_weights[1] = 1;
|
||||
m_comp_weights[2] = 1;
|
||||
m_comp_weights[3] = 1;
|
||||
|
||||
m_decode_mode_srgb = true;
|
||||
|
||||
m_pForced_weight_vals0 = nullptr;
|
||||
m_pForced_weight_vals1 = nullptr;
|
||||
|
||||
m_max_ls_passes = 3;
|
||||
m_total_weight_refine_passes = 0;
|
||||
m_worst_weight_nudging_flag = false;
|
||||
m_endpoint_refinement_flag = false;
|
||||
}
|
||||
|
||||
float get_total_comp_weights() const
|
||||
{
|
||||
return (float)(m_comp_weights[0] + m_comp_weights[1] + m_comp_weights[2] + m_comp_weights[3]);
|
||||
}
|
||||
};
|
||||
|
||||
struct pixel_stats_t
|
||||
{
|
||||
uint32_t m_num_pixels;
|
||||
|
||||
color_rgba m_pixels[ASTC_LDR_MAX_BLOCK_PIXELS];
|
||||
vec4F m_pixels_f[ASTC_LDR_MAX_BLOCK_PIXELS];
|
||||
|
||||
color_rgba m_min, m_max;
|
||||
|
||||
vec4F m_min_f, m_max_f;
|
||||
vec4F m_mean_f;
|
||||
|
||||
// Always 3D, ignoring alpha
|
||||
vec3F m_mean_rel_axis3;
|
||||
vec3F m_zero_rel_axis3;
|
||||
|
||||
// Always 4D
|
||||
vec4F m_mean_rel_axis4;
|
||||
|
||||
bool m_has_alpha;
|
||||
|
||||
stats<float> m_rgba_stats[4];
|
||||
|
||||
void clear()
|
||||
{
|
||||
clear_obj(*this);
|
||||
}
|
||||
|
||||
void init(uint32_t num_pixels, const color_rgba* pPixels);
|
||||
|
||||
}; // struct struct pixel_stats
|
||||
|
||||
void global_init();
|
||||
|
||||
void bit_transfer_signed_enc(int& a, int& b);
|
||||
void bit_transfer_signed_dec(int& a, int& b); // transfers MSB from a to b, a is then [-32,31]
|
||||
color_rgba blue_contract_enc(color_rgba orig, bool& did_clamp, int encoded_b);
|
||||
int quant_preserve2(uint32_t ise_range, uint32_t v);
|
||||
|
||||
uint32_t get_colors(const color_rgba& l, const color_rgba& h, uint32_t weight_ise_index, color_rgba* pColors, bool decode_mode_srgb);
|
||||
uint32_t get_colors_raw_weights(const color_rgba& l, const color_rgba& h, color_rgba* pColors, bool decode_mode_srgb);
|
||||
void decode_endpoints_ise20(uint32_t cem_index, const uint8_t* pEndpoint_vals, color_rgba& l, color_rgba& h); // assume BISE 20
|
||||
void decode_endpoints(uint32_t cem_index, const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index, color_rgba& l, color_rgba& h, float* pScale = nullptr);
|
||||
uint32_t get_colors(uint32_t cem_index, const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index, uint32_t weight_ise_index, color_rgba* pColors, bool decode_mode_srgb);
|
||||
uint32_t get_colors_raw_weights(uint32_t cem_index, const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index, color_rgba* pColors, bool decode_mode_srgb);
|
||||
|
||||
//int apply_delta_to_bise_endpoint_val(uint32_t endpoint_ise_range, int ise_val, int delta);
|
||||
int apply_delta_to_bise_weight_val(uint32_t weight_ise_range, int ise_val, int delta);
|
||||
|
||||
uint64_t eval_solution(
|
||||
const pixel_stats_t& pixel_stats,
|
||||
uint32_t total_weights, const color_rgba* pWeight_colors,
|
||||
uint8_t* pWeight_vals, uint32_t weight_ise_index,
|
||||
const cem_encode_params& params);
|
||||
|
||||
uint64_t eval_solution(
|
||||
const pixel_stats_t& pixel_stats,
|
||||
uint32_t cem_index,
|
||||
const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index,
|
||||
uint8_t* pWeight_vals, uint32_t weight_ise_index,
|
||||
const cem_encode_params& params);
|
||||
|
||||
uint64_t eval_solution_dp(
|
||||
uint32_t ccs_index,
|
||||
const pixel_stats_t& pixel_stats,
|
||||
uint32_t total_weights, const color_rgba* pWeight_colors,
|
||||
uint8_t* pWeight_vals0, uint8_t* pWeight_vals1, uint32_t weight_ise_index,
|
||||
const cem_encode_params& params);
|
||||
|
||||
uint64_t eval_solution_dp(
|
||||
const pixel_stats_t& pixel_stats,
|
||||
uint32_t cem_index, uint32_t ccs_index,
|
||||
const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index,
|
||||
uint8_t* pWeight_vals0, uint8_t* pWeight_vals1, uint32_t weight_ise_index,
|
||||
const cem_encode_params& params);
|
||||
|
||||
//bool cem8_or_12_used_blue_contraction(uint32_t cem_index, const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index);
|
||||
//bool cem9_or_13_used_blue_contraction(uint32_t cem_index, const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index);
|
||||
//bool used_blue_contraction(uint32_t cem_index, const uint8_t* pEndpoint_vals, uint32_t endpoint_ise_index);
|
||||
|
||||
uint64_t cem_encode_pixels(
|
||||
uint32_t cem_index, int ccs_index,
|
||||
const pixel_stats_t& pixel_stats, const cem_encode_params& enc_params,
|
||||
uint32_t endpoint_ise_range, uint32_t weight_ise_range,
|
||||
uint8_t* pEndpoint_vals, uint8_t* pWeight_vals0, uint8_t* pWeight_vals1, uint64_t cur_blk_error,
|
||||
bool use_blue_contraction, bool* pBase_ofs_clamped_flag);
|
||||
|
||||
// TODO: Rename, confusing vs. std::vector or basisu::vector or vec4F etc.
|
||||
struct partition_pattern_vec
|
||||
{
|
||||
uint32_t m_width, m_height;
|
||||
uint8_t m_parts[ASTC_LDR_MAX_BLOCK_PIXELS];
|
||||
|
||||
partition_pattern_vec();
|
||||
|
||||
partition_pattern_vec(const partition_pattern_vec& other);
|
||||
|
||||
partition_pattern_vec(uint32_t width, uint32_t height, const uint8_t* pParts = nullptr);
|
||||
|
||||
void init(uint32_t width, uint32_t height, const uint8_t* pParts = nullptr);
|
||||
|
||||
void init_part_hist();
|
||||
|
||||
void clear();
|
||||
|
||||
partition_pattern_vec& operator= (const partition_pattern_vec& rhs);
|
||||
|
||||
uint32_t get_width() const { return m_width; }
|
||||
uint32_t get_height() const { return m_height; }
|
||||
uint32_t get_total() const { return m_width * m_height; }
|
||||
|
||||
uint8_t operator[] (uint32_t i) const { assert(i < get_total()); return m_parts[i]; }
|
||||
uint8_t& operator[] (uint32_t i) { assert(i < get_total()); return m_parts[i]; }
|
||||
|
||||
uint8_t operator() (uint32_t x, uint32_t y) const { assert((x < m_width) && (y < m_height)); return m_parts[x + y * m_width]; }
|
||||
uint8_t& operator() (uint32_t x, uint32_t y) { assert((x < m_width) && (y < m_height)); return m_parts[x + y * m_width]; }
|
||||
|
||||
int get_squared_distance(const partition_pattern_vec& other) const;
|
||||
|
||||
float get_distance(const partition_pattern_vec& other) const
|
||||
{
|
||||
return sqrtf((float)get_squared_distance(other));
|
||||
}
|
||||
|
||||
enum { cMaxPermute2Index = 1 };
|
||||
partition_pattern_vec get_permuted2(uint32_t permute_index) const;
|
||||
|
||||
enum { cMaxPermute3Index = 5 };
|
||||
partition_pattern_vec get_permuted3(uint32_t permute_index) const;
|
||||
|
||||
partition_pattern_vec get_canonicalized() const;
|
||||
|
||||
bool operator== (const partition_pattern_vec& rhs) const
|
||||
{
|
||||
if ((m_width != rhs.m_width) || (m_height != rhs.m_height))
|
||||
return false;
|
||||
|
||||
return memcmp(m_parts, rhs.m_parts, get_total()) == 0;
|
||||
}
|
||||
|
||||
operator size_t() const
|
||||
{
|
||||
return basist::hash_hsieh(m_parts, get_total());
|
||||
}
|
||||
};
|
||||
|
||||
struct vp_tree_node
|
||||
{
|
||||
partition_pattern_vec m_vantage_point;
|
||||
uint32_t m_point_index;
|
||||
float m_dist;
|
||||
|
||||
int m_inner_node, m_outer_node;
|
||||
};
|
||||
|
||||
const uint32_t NUM_PART3_MAPPINGS = 6;
|
||||
extern uint8_t g_part3_mapping[NUM_PART3_MAPPINGS][3];
|
||||
|
||||
class vp_tree
|
||||
{
|
||||
public:
|
||||
vp_tree()
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
// This requires no redundant patterns, i.e. all must be unique.
|
||||
bool init(uint32_t n, const partition_pattern_vec* pUnique_pats);
|
||||
|
||||
struct result
|
||||
{
|
||||
uint32_t m_pat_index;
|
||||
uint32_t m_mapping_index;
|
||||
float m_dist;
|
||||
|
||||
bool operator< (const result& rhs) const { return m_dist < rhs.m_dist; }
|
||||
bool operator> (const result& rhs) const { return m_dist > rhs.m_dist; }
|
||||
};
|
||||
|
||||
class result_queue
|
||||
{
|
||||
enum { MaxSupportedSize = 512 + 1 };
|
||||
|
||||
public:
|
||||
result_queue() :
|
||||
m_cur_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
size_t get_size() const
|
||||
{
|
||||
return m_cur_size;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return !m_cur_size;
|
||||
}
|
||||
|
||||
typedef std::array<result, MaxSupportedSize + 1> result_array_type;
|
||||
|
||||
const result_array_type& get_elements() const { return m_elements; }
|
||||
result_array_type& get_elements() { return m_elements; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_cur_size = 0;
|
||||
}
|
||||
|
||||
void reserve(uint32_t n)
|
||||
{
|
||||
BASISU_NOTE_UNUSED(n);
|
||||
}
|
||||
|
||||
const result& top() const
|
||||
{
|
||||
assert(m_cur_size);
|
||||
return m_elements[1];
|
||||
}
|
||||
|
||||
bool insert(const result& val, uint32_t max_size)
|
||||
{
|
||||
assert(max_size < MaxSupportedSize);
|
||||
|
||||
if (m_cur_size >= MaxSupportedSize)
|
||||
return false;
|
||||
|
||||
m_elements[++m_cur_size] = val;
|
||||
up_heap(m_cur_size);
|
||||
|
||||
if (m_cur_size > max_size)
|
||||
pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pop()
|
||||
{
|
||||
if (m_cur_size == 0)
|
||||
return false;
|
||||
|
||||
m_elements[1] = m_elements[m_cur_size--];
|
||||
down_heap(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
float get_highest_dist() const
|
||||
{
|
||||
if (!m_cur_size)
|
||||
return 0.0f;
|
||||
|
||||
return top().m_dist;
|
||||
}
|
||||
|
||||
private:
|
||||
result_array_type m_elements;
|
||||
size_t m_cur_size;
|
||||
|
||||
void up_heap(size_t index)
|
||||
{
|
||||
while ((index > 1) && (m_elements[index] > m_elements[index >> 1]))
|
||||
{
|
||||
std::swap(m_elements[index], m_elements[index >> 1]);
|
||||
index >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void down_heap(size_t index)
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
size_t largest = index, left_child = 2 * index, right_child = 2 * index + 1;
|
||||
|
||||
if ((left_child <= m_cur_size) && (m_elements[left_child] > m_elements[largest]))
|
||||
largest = left_child;
|
||||
|
||||
if ((right_child <= m_cur_size) && (m_elements[right_child] > m_elements[largest]))
|
||||
largest = right_child;
|
||||
|
||||
if (largest == index)
|
||||
break;
|
||||
|
||||
std::swap(m_elements[index], m_elements[largest]);
|
||||
index = largest;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void find_nearest(uint32_t num_subsets, const partition_pattern_vec& desired_pat, result_queue& results, uint32_t max_results) const;
|
||||
|
||||
private:
|
||||
basisu::vector<vp_tree_node> m_nodes;
|
||||
|
||||
void find_nearest_at_node(int node_index, uint32_t num_desired_pats, const partition_pattern_vec* pDesired_pats, result_queue& results, uint32_t max_results) const;
|
||||
|
||||
void find_nearest_at_node_non_recursive(int init_node_index, uint32_t num_desired_pats, const partition_pattern_vec* pDesired_pats, result_queue& results, uint32_t max_results) const;
|
||||
|
||||
// returns the index of the new node, or -1 on error
|
||||
int create_node(uint32_t n, const partition_pattern_vec* pUnique_pats, const uint_vec& pat_indices);
|
||||
|
||||
// returns the pattern index of the vantage point (-1 on error), and the optimal split distance
|
||||
std::pair<int, float> find_best_vantage_point(uint32_t num_unique_pats, const partition_pattern_vec* pUnique_pats, const uint_vec& pat_indices);
|
||||
};
|
||||
|
||||
typedef basisu::hash_map<partition_pattern_vec, std::pair<uint32_t, uint32_t > > partition_hash_map;
|
||||
|
||||
struct partition_pattern_hist
|
||||
{
|
||||
uint8_t m_hist[4];
|
||||
|
||||
partition_pattern_hist() { clear(); }
|
||||
|
||||
void clear() { clear_obj(m_hist); }
|
||||
};
|
||||
|
||||
struct partitions_data
|
||||
{
|
||||
uint32_t m_width, m_height, m_num_partitions;
|
||||
partition_pattern_vec m_partition_pats[astc_helpers::NUM_PARTITION_PATTERNS]; // indexed by unique index, NOT the 10-bit ASTC seed/pattern index
|
||||
|
||||
partition_pattern_hist m_partition_pat_histograms[astc_helpers::NUM_PARTITION_PATTERNS]; // indexed by unique index, histograms of each pattern
|
||||
|
||||
// ASTC seed to unique index and vice versa
|
||||
int16_t m_part_seed_to_unique_index[astc_helpers::NUM_PARTITION_PATTERNS];
|
||||
int16_t m_unique_index_to_part_seed[astc_helpers::NUM_PARTITION_PATTERNS];
|
||||
|
||||
// Total number of unique patterns
|
||||
uint32_t m_total_unique_patterns;
|
||||
|
||||
// VP tree used to rapidly find nearby/similar patterns.
|
||||
vp_tree m_part_vp_tree;
|
||||
|
||||
void init(uint32_t num_partitions, uint32_t block_width, uint32_t block_height, bool init_vp_tree = true);
|
||||
};
|
||||
|
||||
float surrogate_quant_endpoint_val(float e, uint32_t num_endpoint_levels, uint32_t flags);
|
||||
vec4F surrogate_quant_endpoint(const vec4F& e, uint32_t num_endpoint_levels, uint32_t flags);
|
||||
|
||||
float surrogate_evaluate_rgba_sp(const pixel_stats_t& ps, const vec4F& l, const vec4F& h, float* pWeights0, uint32_t num_weight_levels, const cem_encode_params& enc_params, uint32_t flags);
|
||||
float surrogate_evaluate_rgba_dp(uint32_t ccs_index, const pixel_stats_t& ps, const vec4F& l, const vec4F& h, float* pWeights0, float* pWeights1, uint32_t num_weight_levels, const cem_encode_params& enc_params, uint32_t flags);
|
||||
|
||||
enum
|
||||
{
|
||||
cFlagDisableQuant = 1,
|
||||
cFlagNoError = 2
|
||||
}
|
||||
;
|
||||
float cem_surrogate_encode_pixels(
|
||||
uint32_t cem_index, int ccs_index,
|
||||
const pixel_stats_t& pixel_stats, const cem_encode_params& enc_params,
|
||||
uint32_t endpoint_ise_range, uint32_t weight_ise_range,
|
||||
vec4F& low_endpoint, vec4F& high_endpoint, float& s, float* pWeights0, float* pWeights1, uint32_t flags = 0);
|
||||
|
||||
#if 0
|
||||
bool requantize_ise_endpoints(uint32_t cem,
|
||||
uint32_t src_ise_endpoint_range, const uint8_t* pSrc_endpoints,
|
||||
uint32_t dst_ise_endpoint_range, uint8_t* pDst_endpoints);
|
||||
|
||||
uint32_t get_base_cem_without_alpha(uint32_t cem);
|
||||
|
||||
bool pack_base_offset(
|
||||
uint32_t cem_index, uint32_t dst_ise_endpoint_range, uint8_t* pPacked_endpoints,
|
||||
const color_rgba& l, const color_rgba& h,
|
||||
bool use_blue_contraction, bool auto_disable_blue_contraction_if_clamped,
|
||||
bool& blue_contraction_clamped_flag, bool& base_ofs_clamped_flag, bool& endpoints_swapped);
|
||||
|
||||
bool convert_endpoints_across_cems(
|
||||
uint32_t prev_cem, uint32_t prev_endpoint_ise_range, const uint8_t* pPrev_endpoints,
|
||||
uint32_t dst_cem, uint32_t dst_endpoint_ise_range, uint8_t* pDst_endpoints,
|
||||
bool always_repack,
|
||||
bool use_blue_contraction, bool auto_disable_blue_contraction_if_clamped,
|
||||
bool& blue_contraction_clamped_flag, bool& base_ofs_clamped_flag);
|
||||
#endif
|
||||
|
||||
} // namespace astc_ldr
|
||||
|
||||
} // namespace basisu
|
||||
11065
encoder/basisu_astc_ldr_encode.cpp
Normal file
11065
encoder/basisu_astc_ldr_encode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
encoder/basisu_astc_ldr_encode.h
Normal file
125
encoder/basisu_astc_ldr_encode.h
Normal file
@@ -0,0 +1,125 @@
|
||||
// File: basisu_astc_ldr_encode.cpp
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "../transcoder/basisu_astc_helpers.h"
|
||||
|
||||
namespace basisu {
|
||||
namespace astc_ldr {
|
||||
|
||||
void encoder_init();
|
||||
|
||||
const int EFFORT_LEVEL_MIN = 0, EFFORT_LEVEL_MAX = 10, EFFORT_LEVEL_DEF = 3;
|
||||
const int DCT_QUALITY_MIN = 1, DCT_QUALITY_MAX = 100;
|
||||
|
||||
struct astc_ldr_encode_config
|
||||
{
|
||||
astc_ldr_encode_config()
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
*this = astc_ldr_encode_config();
|
||||
}
|
||||
|
||||
// ASTC LDR block dimensions. Must be a valid ASTC block dimension. Any supported from 4x4-12x12, including unequal dimensions.
|
||||
uint32_t m_astc_block_width = 6;
|
||||
uint32_t m_astc_block_height = 6;
|
||||
|
||||
// If true, the encoder assumes all ASTC blocks will be decompressed using sRGB vs. LDR8 mode. This corresponds to astcenc's -cs vs. cl color profiles.
|
||||
// This should match how the texture is later decoded by the GPU for maximum quality. This bit is stored into the output file.
|
||||
bool m_astc_decode_mode_srgb = true;
|
||||
|
||||
// If true, trade off some compression (3-10%) for faster decompression.
|
||||
// If false, favor highest compression, but slower decompression.
|
||||
//bool m_use_faster_format = true;
|
||||
|
||||
basist::astc_ldr_t::xuastc_ldr_syntax m_compressed_syntax = basist::astc_ldr_t::xuastc_ldr_syntax::cFullArith;
|
||||
|
||||
// Encoder CPU effort vs. quality. [0,10], higher=better.
|
||||
// 0=extremely fast but very brittle (no subsets)
|
||||
// 1=first 2 subset effort level
|
||||
// 10=extremely high CPU requirements.
|
||||
uint32_t m_effort_level = 3;
|
||||
|
||||
// Weight grid DCT quality [1,100] - higher=better quality (JPEG-style).
|
||||
float m_dct_quality = 85;
|
||||
|
||||
// true=use weight grid DCT, false=always use DPCM
|
||||
bool m_use_dct = false;
|
||||
|
||||
// true=use lossy supercompression, false=supercompression stage is always lossless.
|
||||
bool m_lossy_supercompression = false;
|
||||
|
||||
// Channel weights used to compute RGBA colorspace L2 errors. Must be >= 1.
|
||||
uint32_t m_comp_weights[4] = { 1, 1, 1, 1 };
|
||||
|
||||
// Lossy supercompression stage parameters for RGB vs. RGBA image inputs.
|
||||
// (Bounded RDO - explictly not Lagrangian.)
|
||||
float m_replacement_min_psnr = 35.0f; // if the block's base PSNR is less than this, it cannot be changed
|
||||
float m_psnr_trial_diff_thresh = 1.5f; // reject candidates if their PSNR is lower than m_replacement_min_psnr-m_psnr_trial_diff_thresh
|
||||
float m_psnr_trial_diff_thresh_edge = 1.0f; // edge variant
|
||||
|
||||
// Lossy supercompression settings - alpha texture variants
|
||||
float m_replacement_min_psnr_alpha = 38.0f;
|
||||
float m_psnr_trial_diff_thresh_alpha = .75f;
|
||||
float m_psnr_trial_diff_thresh_edge_alpha = .5f;
|
||||
|
||||
// If true, try encoding blurred blocks, in addition to unblurred, for superpass 1 and 2.
|
||||
// Higher quality, but massively slower and not yet tuned/refined.
|
||||
bool m_block_blurring_p1 = false, m_block_blurring_p2 = false;
|
||||
|
||||
// If true, no matter what effort level subset usage will be disabled.
|
||||
bool m_force_disable_subsets = false;
|
||||
|
||||
// If true, no matter what effort level RGB dual plane usage will be disabled.
|
||||
bool m_force_disable_rgb_dual_plane = false;
|
||||
|
||||
bool m_debug_images = false;
|
||||
bool m_debug_output = false;
|
||||
|
||||
std::string m_debug_file_prefix;
|
||||
|
||||
void debug_print() const
|
||||
{
|
||||
fmt_debug_printf("ASTC block dimensions: {}x{}\n", m_astc_block_width, m_astc_block_height);
|
||||
fmt_debug_printf("ASTC decode profile mode sRGB: {}\n", m_astc_decode_mode_srgb);
|
||||
fmt_debug_printf("Syntax: {}\n", (uint32_t)m_compressed_syntax);
|
||||
fmt_debug_printf("Effort level: {}\n", m_effort_level);
|
||||
fmt_debug_printf("Use DCT: {}\n", m_use_dct);
|
||||
fmt_debug_printf("DCT quality level (1-100): {}\n", m_dct_quality);
|
||||
fmt_debug_printf("Comp weights: {} {} {} {}\n", m_comp_weights[0], m_comp_weights[1], m_comp_weights[2], m_comp_weights[3]);
|
||||
fmt_debug_printf("Block blurring: {} {}\n", m_block_blurring_p1, m_block_blurring_p2);
|
||||
fmt_debug_printf("Force disable subsets: {}\n", m_force_disable_subsets);
|
||||
fmt_debug_printf("Force disable RGB dual plane: {}\n", m_force_disable_rgb_dual_plane);
|
||||
|
||||
fmt_debug_printf("\nLossy supercompression: {}\n", m_lossy_supercompression);
|
||||
fmt_debug_printf("m_replacement_min_psnr: {}\n", m_replacement_min_psnr);
|
||||
fmt_debug_printf("m_psnr_trial_diff_thresh: {}\n", m_psnr_trial_diff_thresh);
|
||||
fmt_debug_printf("m_psnr_trial_diff_thresh_edge: {}\n", m_psnr_trial_diff_thresh_edge);
|
||||
fmt_debug_printf("m_replacement_min_psnr_alpha: {}\n", m_replacement_min_psnr_alpha);
|
||||
fmt_debug_printf("m_psnr_trial_diff_thresh_alpha: {}\n", m_psnr_trial_diff_thresh_alpha);
|
||||
fmt_debug_printf("m_psnr_trial_diff_thresh_edge_alpha: {}\n", m_psnr_trial_diff_thresh_edge_alpha);
|
||||
|
||||
fmt_debug_printf("m_debug_images: {}\n", m_debug_images);
|
||||
}
|
||||
};
|
||||
|
||||
bool compress_image(
|
||||
const image& orig_img, uint8_vec &comp_data, vector2D<astc_helpers::log_astc_block>& coded_blocks,
|
||||
const astc_ldr_encode_config& global_cfg,
|
||||
job_pool& job_pool);
|
||||
|
||||
bool decompress_image(
|
||||
const uint8_t* pComp_data, size_t comp_data_size,
|
||||
vector2D<astc_helpers::log_astc_block>& coded_blocks, // the actual supercompressed ASTC LDR blocks emitted by the compressor
|
||||
uint32_t& astc_block_width, uint32_t& astc_block_height,
|
||||
uint32_t &actual_width, uint32_t &actual_height, bool &has_alpha, bool& uses_srgb_astc_decode_mode,
|
||||
bool debug_output);
|
||||
|
||||
void deblock_filter(uint32_t filter_block_width, uint32_t filter_block_height, const image& src_img, image& dst_img, bool stronger_filtering = false, int SKIP_THRESH = 24);
|
||||
|
||||
} // namespace astc_ldr
|
||||
} // namespace basisu
|
||||
|
||||
|
||||
319
encoder/basisu_wasm_api.cpp
Normal file
319
encoder/basisu_wasm_api.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
// File: basisu_wasm_api.cpp - Simplified compression API for WASM WASI modules and Python native support.
|
||||
// Also useable by plain C callers.
|
||||
#include "basisu_comp.h"
|
||||
#include "basisu_wasm_api.h"
|
||||
|
||||
using namespace basisu;
|
||||
|
||||
static inline uint64_t wasm_offset(void* p)
|
||||
{
|
||||
return (uint64_t)(uintptr_t)p;
|
||||
}
|
||||
|
||||
static inline uint8_t* wasm_ptr(uint64_t offset)
|
||||
{
|
||||
return (uint8_t*)(uintptr_t)offset;
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_get_version")
|
||||
uint32_t bu_get_version()
|
||||
{
|
||||
printf("Hello from basisu_wasm_api.cpp version %u\n", BASISU_LIB_VERSION);
|
||||
|
||||
return BASISU_LIB_VERSION;
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_enable_debug_printf")
|
||||
void bu_enable_debug_printf(uint32_t flag)
|
||||
{
|
||||
enable_debug_printf(flag != 0);
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_init")
|
||||
void bu_init()
|
||||
{
|
||||
basisu_encoder_init(false, false);
|
||||
}
|
||||
|
||||
// Memory alloc/free — stubs
|
||||
BU_WASM_EXPORT("bu_alloc")
|
||||
uint64_t bu_alloc(uint64_t size)
|
||||
{
|
||||
void* p = malloc((size_t)size);
|
||||
return wasm_offset(p);
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_free")
|
||||
void bu_free(uint64_t ofs)
|
||||
{
|
||||
free(wasm_ptr(ofs));
|
||||
}
|
||||
|
||||
const uint32_t COMP_PARAMS_MAGIC = 0x43504D50; // "CPMP"
|
||||
|
||||
struct comp_params
|
||||
{
|
||||
uint32_t m_magic = COMP_PARAMS_MAGIC;
|
||||
|
||||
comp_params()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
assert(m_magic == COMP_PARAMS_MAGIC);
|
||||
|
||||
m_comp_data.clear();
|
||||
m_images.clear();
|
||||
m_imagesf.clear();
|
||||
|
||||
m_stats.clear();
|
||||
}
|
||||
|
||||
uint8_vec m_comp_data;
|
||||
|
||||
basisu::vector<image> m_images;
|
||||
basisu::vector<imagef> m_imagesf;
|
||||
|
||||
image_stats m_stats;
|
||||
};
|
||||
|
||||
BU_WASM_EXPORT("bu_new_comp_params")
|
||||
uint64_t bu_new_comp_params()
|
||||
{
|
||||
comp_params* p = new comp_params;
|
||||
return wasm_offset(p);
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_delete_comp_params")
|
||||
wasm_bool_t bu_delete_comp_params(uint64_t params_ofs)
|
||||
{
|
||||
comp_params* p = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
assert(p->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (p->m_magic != COMP_PARAMS_MAGIC)
|
||||
return false;
|
||||
|
||||
delete p;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_get_comp_data_size")
|
||||
uint64_t bu_comp_params_get_comp_data_size(uint64_t params_ofs)
|
||||
{
|
||||
comp_params* pParams = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!pParams)
|
||||
return 0;
|
||||
|
||||
assert(pParams->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (pParams->m_magic != COMP_PARAMS_MAGIC)
|
||||
return 0;
|
||||
|
||||
return pParams->m_comp_data.size();
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_get_comp_data_ofs")
|
||||
uint64_t bu_comp_params_get_comp_data_ofs(uint64_t params_ofs)
|
||||
{
|
||||
comp_params* pParams = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!pParams)
|
||||
return 0;
|
||||
|
||||
assert(pParams->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (pParams->m_magic != COMP_PARAMS_MAGIC)
|
||||
return 0;
|
||||
|
||||
return wasm_offset(pParams->m_comp_data.get_ptr());
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_clear")
|
||||
wasm_bool_t bu_comp_params_clear(uint64_t params_ofs)
|
||||
{
|
||||
comp_params* pParams = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!pParams)
|
||||
return false;
|
||||
|
||||
assert(pParams->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (pParams->m_magic != COMP_PARAMS_MAGIC)
|
||||
return false;
|
||||
|
||||
pParams->clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Caller wants to give us a LDR/SDR 32bpp RGBA mipmap level (4 bytes per pixel)
|
||||
BU_WASM_EXPORT("bu_comp_params_set_image_rgba32")
|
||||
wasm_bool_t bu_comp_params_set_image_rgba32(
|
||||
uint64_t params_ofs,
|
||||
uint32_t image_index,
|
||||
uint64_t img_data_ofs,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t pitch_in_bytes)
|
||||
{
|
||||
if ((!width) || (!height) || (!pitch_in_bytes))
|
||||
return false;
|
||||
|
||||
comp_params* pParams = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!pParams)
|
||||
return false;
|
||||
|
||||
assert(pParams->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (pParams->m_magic != COMP_PARAMS_MAGIC)
|
||||
return false;
|
||||
|
||||
const uint8_t* pImage = wasm_ptr(img_data_ofs);
|
||||
if (!pImage)
|
||||
return false;
|
||||
|
||||
const uint32_t bytes_per_pixel = sizeof(color_rgba);
|
||||
|
||||
if (pitch_in_bytes < width * bytes_per_pixel)
|
||||
return false;
|
||||
|
||||
if (image_index >= pParams->m_images.size())
|
||||
{
|
||||
if (!pParams->m_images.try_resize(image_index + 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
basisu::image& dst_img = pParams->m_images[image_index];
|
||||
|
||||
dst_img.resize(width, height);
|
||||
|
||||
if (pitch_in_bytes == width * bytes_per_pixel)
|
||||
{
|
||||
memcpy(dst_img.get_ptr(), pImage, pitch_in_bytes * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
{
|
||||
const uint8_t* pSrc_row = pImage + y * pitch_in_bytes;
|
||||
|
||||
uint8_t* pDst_row = (uint8_t *)&dst_img(0, y);
|
||||
|
||||
memcpy(pDst_row, pSrc_row, width * bytes_per_pixel);
|
||||
} // y
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Caller wants to give us a float RGBA mipmap level (4*4=16 bytes per pixel)
|
||||
BU_WASM_EXPORT("bu_comp_params_set_image_float_rgba")
|
||||
wasm_bool_t bu_comp_params_set_image_float_rgba(
|
||||
uint64_t params_ofs,
|
||||
uint32_t image_index,
|
||||
uint64_t img_data_ofs,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t pitch_in_bytes)
|
||||
{
|
||||
if ((!width) || (!height) || (!pitch_in_bytes))
|
||||
return false;
|
||||
|
||||
comp_params* pParams = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!pParams)
|
||||
return false;
|
||||
|
||||
assert(pParams->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (pParams->m_magic != COMP_PARAMS_MAGIC)
|
||||
return false;
|
||||
|
||||
const uint8_t* pImage = wasm_ptr(img_data_ofs);
|
||||
if (!pImage)
|
||||
return false;
|
||||
|
||||
const uint32_t bytes_per_pixel = sizeof(float) * 4;
|
||||
|
||||
if (pitch_in_bytes < width * bytes_per_pixel)
|
||||
return false;
|
||||
|
||||
if (image_index >= pParams->m_images.size())
|
||||
{
|
||||
if (!pParams->m_imagesf.try_resize(image_index + 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
basisu::imagef& dst_img = pParams->m_imagesf[image_index];
|
||||
|
||||
dst_img.resize(width, height);
|
||||
|
||||
if (pitch_in_bytes == width * bytes_per_pixel)
|
||||
{
|
||||
memcpy((void *)dst_img.get_ptr(), (const void *)pImage, pitch_in_bytes * height);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
{
|
||||
const uint8_t* pSrc_row = pImage + y * pitch_in_bytes;
|
||||
|
||||
uint8_t* pDst_row = (uint8_t*)&dst_img(0, y);
|
||||
|
||||
memcpy(pDst_row, pSrc_row, width * bytes_per_pixel);
|
||||
} // y
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BU_WASM_EXPORT("bu_compress_texture")
|
||||
wasm_bool_t bu_compress_texture(
|
||||
uint64_t params_ofs,
|
||||
uint32_t desired_basis_tex_format, // basis_tex_format
|
||||
int quality_level, int effort_level,
|
||||
uint64_t flags_and_quality, float low_level_uastc_rdo_or_dct_quality)
|
||||
{
|
||||
//enable_debug_printf((flags_and_quality & cFlagDebug) != 0);
|
||||
|
||||
comp_params* pParams = (comp_params*)wasm_ptr(params_ofs);
|
||||
if (!pParams)
|
||||
return false;
|
||||
|
||||
assert(pParams->m_magic == COMP_PARAMS_MAGIC);
|
||||
if (pParams->m_magic != COMP_PARAMS_MAGIC)
|
||||
return false;
|
||||
|
||||
pParams->m_comp_data.clear();
|
||||
|
||||
if (desired_basis_tex_format >= (uint32_t)basist::basis_tex_format::cTotalFormats)
|
||||
return false;
|
||||
|
||||
if (!pParams->m_images.size() && !pParams->m_imagesf.size())
|
||||
return false;
|
||||
if (pParams->m_images.size() && pParams->m_imagesf.size())
|
||||
return false;
|
||||
|
||||
size_t comp_size = 0;
|
||||
|
||||
void* pComp_data = basis_compress_internal(
|
||||
(basist::basis_tex_format)desired_basis_tex_format,
|
||||
pParams->m_images.size() ? &pParams->m_images : nullptr,
|
||||
pParams->m_imagesf.size() ? &pParams->m_imagesf : nullptr,
|
||||
(uint32_t)flags_and_quality,
|
||||
low_level_uastc_rdo_or_dct_quality,
|
||||
&comp_size,
|
||||
&pParams->m_stats,
|
||||
quality_level,
|
||||
effort_level);
|
||||
|
||||
if (!pComp_data)
|
||||
return false;
|
||||
|
||||
if (!pParams->m_comp_data.try_resize(comp_size))
|
||||
{
|
||||
basis_free_data(pComp_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(pParams->m_comp_data.get_ptr(), pComp_data, comp_size);
|
||||
|
||||
basis_free_data(pComp_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
58
encoder/basisu_wasm_api.h
Normal file
58
encoder/basisu_wasm_api.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// File: basisu_wasm_api.h
|
||||
#pragma once
|
||||
#include "basisu_wasm_api_common.h"
|
||||
|
||||
BU_WASM_EXPORT("bu_get_version")
|
||||
uint32_t bu_get_version();
|
||||
|
||||
BU_WASM_EXPORT("bu_enable_debug_printf")
|
||||
void bu_enable_debug_printf(uint32_t flag);
|
||||
|
||||
BU_WASM_EXPORT("bu_init")
|
||||
void bu_init();
|
||||
|
||||
BU_WASM_EXPORT("bu_alloc")
|
||||
uint64_t bu_alloc(uint64_t size);
|
||||
|
||||
BU_WASM_EXPORT("bu_free")
|
||||
void bu_free(uint64_t ofs);
|
||||
|
||||
BU_WASM_EXPORT("bu_new_comp_params")
|
||||
uint64_t bu_new_comp_params();
|
||||
|
||||
BU_WASM_EXPORT("bu_delete_comp_params")
|
||||
wasm_bool_t bu_delete_comp_params(uint64_t params_ofs);
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_get_comp_data_size")
|
||||
uint64_t bu_comp_params_get_comp_data_size(uint64_t params_ofs);
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_get_comp_data_ofs")
|
||||
uint64_t bu_comp_params_get_comp_data_ofs(uint64_t params_ofs);
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_clear")
|
||||
wasm_bool_t bu_comp_params_clear(uint64_t params_ofs);
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_set_image_rgba32")
|
||||
wasm_bool_t bu_comp_params_set_image_rgba32(
|
||||
uint64_t params_ofs,
|
||||
uint32_t image_index,
|
||||
uint64_t img_data_ofs,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t pitch_in_bytes);
|
||||
|
||||
BU_WASM_EXPORT("bu_comp_params_set_image_float_rgba")
|
||||
wasm_bool_t bu_comp_params_set_image_float_rgba(
|
||||
uint64_t params_ofs,
|
||||
uint32_t image_index,
|
||||
uint64_t img_data_ofs,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t pitch_in_bytes);
|
||||
|
||||
BU_WASM_EXPORT("bu_compress_texture")
|
||||
wasm_bool_t bu_compress_texture(
|
||||
uint64_t params_ofs,
|
||||
uint32_t desired_basis_tex_format,
|
||||
int quality_level, int effort_level,
|
||||
uint64_t flags_and_quality,
|
||||
float low_level_uastc_rdo_or_dct_quality);
|
||||
|
||||
156
encoder/basisu_wasm_api_common.h
Normal file
156
encoder/basisu_wasm_api_common.h
Normal file
@@ -0,0 +1,156 @@
|
||||
// File: basisu_wasm_api_common.h
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
|
||||
#if defined(__wasm__)
|
||||
#if defined(__cplusplus)
|
||||
#define BU_WASM_EXPORT(name) __attribute__((export_name(name))) extern "C"
|
||||
#else
|
||||
#define BU_WASM_EXPORT(name) __attribute__((export_name(name)))
|
||||
#endif
|
||||
#elif defined(__cplusplus)
|
||||
#define BU_WASM_EXPORT(name) extern "C"
|
||||
#else
|
||||
#define BU_WASM_EXPORT(name)
|
||||
#endif
|
||||
|
||||
// wasm_bool_t is an alias for uint32_t
|
||||
typedef uint32_t wasm_bool_t;
|
||||
|
||||
// Compression constants
|
||||
|
||||
#define BU_QUALITY_MIN 0
|
||||
#define BU_QUALITY_MAX 100
|
||||
|
||||
#define BU_EFFORT_MIN 0
|
||||
#define BU_EFFORT_MAX 10
|
||||
#define BU_EFFORT_SUPER_FAST = 0
|
||||
#define BU_EFFORT_FAST = 2
|
||||
#define BU_EFFORT_NORMAL = 5
|
||||
#define BU_EFFORT_DEFAULT = 2
|
||||
#define BU_EFFORT_SLOW = 8
|
||||
#define BU_EFFORT_VERY_SLOW = 10
|
||||
|
||||
#define BU_COMP_FLAGS_NONE (0)
|
||||
#define BU_COMP_FLAGS_USE_OPENCL (1 << 8 )
|
||||
#define BU_COMP_FLAGS_THREADED (1 << 9 )
|
||||
#define BU_COMP_FLAGS_DEBUG_OUTPUT (1 << 10)
|
||||
#define BU_COMP_FLAGS_KTX2_OUTPUT (1 << 11)
|
||||
#define BU_COMP_FLAGS_KTX2_UASTC_ZSTD (1 << 12)
|
||||
#define BU_COMP_FLAGS_SRGB (1 << 13)
|
||||
#define BU_COMP_FLAGS_GEN_MIPS_CLAMP (1 << 14)
|
||||
#define BU_COMP_FLAGS_GEN_MIPS_WRAP (1 << 15)
|
||||
#define BU_COMP_FLAGS_Y_FLIP (1 << 16)
|
||||
#define BU_COMP_FLAGS_PRINT_STATS (1 << 18)
|
||||
#define BU_COMP_FLAGS_PRINT_STATUS (1 << 19)
|
||||
#define BU_COMP_FLAGS_DEBUG_IMAGES (1 << 20)
|
||||
#define BU_COMP_FLAGS_REC2020 (1 << 21)
|
||||
#define BU_COMP_FLAGS_VALIDATE_OUTPUT (1 << 22)
|
||||
|
||||
#define BU_COMP_FLAGS_XUASTC_LDR_FULL_ARITH (0)
|
||||
#define BU_COMP_FLAGS_XUASTC_LDR_HYBRID (1 << 23)
|
||||
#define BU_COMP_FLAGS_XUASTC_LDR_FULL_ZSTD (2 << 23)
|
||||
#define BU_COMP_FLAGS_XUASTC_LDR_SYNTAX_SHIFT (23)
|
||||
#define BU_COMP_FLAGS_XUASTC_LDR_SYNTAX_MASK (3)
|
||||
|
||||
#define BU_COMP_FLAGS_TEXTURE_TYPE_2D (0 << 25)
|
||||
#define BU_COMP_FLAGS_TEXTURE_TYPE_2D_ARRAY (1 << 25)
|
||||
#define BU_COMP_FLAGS_TEXTURE_TYPE_CUBEMAP_ARRAY (2 << 25)
|
||||
#define BU_COMP_FLAGS_TEXTURE_TYPE_VIDEO_FRAMES (3 << 25)
|
||||
#define BU_COMP_FLAGS_TEXTURE_TYPE_SHIFT (25)
|
||||
#define BU_COMP_FLAGS_TEXTURE_TYPE_MASK (3)
|
||||
|
||||
#define BU_COMP_FLAGS_VERBOSE (BU_COMP_FLAGS_DEBUG_OUTPUT | BU_COMP_FLAGS_PRINT_STATS | BU_COMP_FLAGS_PRINT_STATUS)
|
||||
|
||||
// basist::basis_tex_format: the supported .ktx2 (and .basis) file format types
|
||||
#define BTF_ETC1S 0
|
||||
#define BTF_UASTC_LDR_4X4 1
|
||||
#define BTF_UASTC_HDR_4X4 2
|
||||
#define BTF_ASTC_HDR_6X6 3
|
||||
#define BTF_UASTC_HDR_6X6 4
|
||||
#define BTF_XUASTC_LDR_4X4 5
|
||||
#define BTF_XUASTC_LDR_5X4 6
|
||||
#define BTF_XUASTC_LDR_5X5 7
|
||||
#define BTF_XUASTC_LDR_6X5 8
|
||||
#define BTF_XUASTC_LDR_6X6 9
|
||||
#define BTF_XUASTC_LDR_8X5 10
|
||||
#define BTF_XUASTC_LDR_8X6 11
|
||||
#define BTF_XUASTC_LDR_10X5 12
|
||||
#define BTF_XUASTC_LDR_10X6 13
|
||||
#define BTF_XUASTC_LDR_8X8 14
|
||||
#define BTF_XUASTC_LDR_10X8 15
|
||||
#define BTF_XUASTC_LDR_10X10 16
|
||||
#define BTF_XUASTC_LDR_12X10 17
|
||||
#define BTF_XUASTC_LDR_12X12 18
|
||||
#define BTF_ASTC_LDR_4X4 19
|
||||
#define BTF_ASTC_LDR_5X4 20
|
||||
#define BTF_ASTC_LDR_5X5 21
|
||||
#define BTF_ASTC_LDR_6X5 22
|
||||
#define BTF_ASTC_LDR_6X6 23
|
||||
#define BTF_ASTC_LDR_8X5 24
|
||||
#define BTF_ASTC_LDR_8X6 25
|
||||
#define BTF_ASTC_LDR_10X5 26
|
||||
#define BTF_ASTC_LDR_10X6 27
|
||||
#define BTF_ASTC_LDR_8X8 28
|
||||
#define BTF_ASTC_LDR_10X8 29
|
||||
#define BTF_ASTC_LDR_10X10 30
|
||||
#define BTF_ASTC_LDR_12X10 31
|
||||
#define BTF_ASTC_LDR_12X12 32
|
||||
#define BTF_TOTAL_FORMATS 33
|
||||
|
||||
// Transcoding constants
|
||||
|
||||
// basist::transcoder_texture_format: the supported transcode GPU texture formats
|
||||
#define TF_ETC1_RGB 0
|
||||
#define TF_ETC2_RGBA 1
|
||||
#define TF_BC1_RGB 2
|
||||
#define TF_BC3_RGBA 3
|
||||
#define TF_BC4_R 4
|
||||
#define TF_BC5_RG 5
|
||||
#define TF_BC7_RGBA 6
|
||||
#define TF_PVRTC1_4_RGB 8
|
||||
#define TF_PVRTC1_4_RGBA 9
|
||||
#define TF_ASTC_LDR_4X4_RGBA 10
|
||||
#define TF_ATC_RGB 11
|
||||
#define TF_ATC_RGBA 12
|
||||
#define TF_FXT1_RGB 17
|
||||
#define TF_PVRTC2_4_RGB 18
|
||||
#define TF_PVRTC2_4_RGBA 19
|
||||
#define TF_ETC2_EAC_R11 20
|
||||
#define TF_ETC2_EAC_RG11 21
|
||||
#define TF_BC6H 22
|
||||
#define TF_ASTC_HDR_4X4_RGBA 23
|
||||
#define TF_RGBA32 13
|
||||
#define TF_RGB565 14
|
||||
#define TF_BGR565 15
|
||||
#define TF_RGBA4444 16
|
||||
#define TF_RGB_HALF 24
|
||||
#define TF_RGBA_HALF 25
|
||||
#define TF_RGB_9E5 26
|
||||
#define TF_ASTC_HDR_6X6_RGBA 27
|
||||
#define TF_ASTC_LDR_5X4_RGBA 28
|
||||
#define TF_ASTC_LDR_5X5_RGBA 29
|
||||
#define TF_ASTC_LDR_6X5_RGBA 30
|
||||
#define TF_ASTC_LDR_6X6_RGBA 31
|
||||
#define TF_ASTC_LDR_8X5_RGBA 32
|
||||
#define TF_ASTC_LDR_8X6_RGBA 33
|
||||
#define TF_ASTC_LDR_10X5_RGBA 34
|
||||
#define TF_ASTC_LDR_10X6_RGBA 35
|
||||
#define TF_ASTC_LDR_8X8_RGBA 36
|
||||
#define TF_ASTC_LDR_10X8_RGBA 37
|
||||
#define TF_ASTC_LDR_10X10_RGBA 38
|
||||
#define TF_ASTC_LDR_12X10_RGBA 39
|
||||
#define TF_ASTC_LDR_12X12_RGBA 40
|
||||
#define TF_TOTAL_TEXTURE_FORMATS 41
|
||||
|
||||
// basist::basisu_decode_flags: Transcode decode flags (bt_ktx2_transcode_image_level decode_flags parameter, logically OR'd)
|
||||
#define DECODE_FLAGS_PVRTC_DECODE_TO_NEXT_POW2 2
|
||||
#define DECODE_FLAGS_TRANSCODE_ALPHA_DATA_TO_OPAQUE_FORMATS 4
|
||||
#define DECODE_FLAGS_BC1_FORBID_THREE_COLOR_BLOCKS 8
|
||||
#define DECODE_FLAGS_OUTPUT_HAS_ALPHA_INDICES 16
|
||||
#define DECODE_FLAGS_HIGH_QUALITY 32
|
||||
#define DECODE_FLAGS_NO_ETC1S_CHROMA_FILTERING 64
|
||||
#define DECODE_FLAGS_NO_DEBLOCK_FILTERING 128
|
||||
#define DECODE_FLAGS_STRONGER_DEBLOCK_FILTERING 256
|
||||
#define DECODE_FLAGS_FORCE_DEBLOCK_FILTERING 512
|
||||
#define DECODE_FLAGS_XUASTC_LDR_DISABLE_FAST_BC7_TRANSCODING 1024
|
||||
1071
encoder/basisu_wasm_transcoder_api.cpp
Normal file
1071
encoder/basisu_wasm_transcoder_api.cpp
Normal file
File diff suppressed because it is too large
Load Diff
216
encoder/basisu_wasm_transcoder_api.h
Normal file
216
encoder/basisu_wasm_transcoder_api.h
Normal file
@@ -0,0 +1,216 @@
|
||||
// File: basisu_wasm_transcoder_api.h - Transcoding API support for WASM WASI modules and Python native support.
|
||||
#pragma once
|
||||
#include "basisu_wasm_api_common.h"
|
||||
|
||||
// High-level functions
|
||||
|
||||
BU_WASM_EXPORT("bt_get_version")
|
||||
uint32_t bt_get_version();
|
||||
|
||||
BU_WASM_EXPORT("bt_enable_debug_printf")
|
||||
void bt_enable_debug_printf(uint32_t flag);
|
||||
|
||||
BU_WASM_EXPORT("bt_init")
|
||||
void bt_init();
|
||||
|
||||
BU_WASM_EXPORT("bt_alloc")
|
||||
uint64_t bt_alloc(uint64_t size);
|
||||
|
||||
BU_WASM_EXPORT("bt_free")
|
||||
void bt_free(uint64_t ofs);
|
||||
|
||||
// basis_tex_format helpers
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_tex_format_is_xuastc_ldr")
|
||||
wasm_bool_t bt_basis_tex_format_is_xuastc_ldr(uint32_t basis_tex_fmt_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_tex_format_is_astc_ldr")
|
||||
wasm_bool_t bt_basis_tex_format_is_astc_ldr(uint32_t basis_tex_fmt_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_tex_format_get_block_width")
|
||||
uint32_t bt_basis_tex_format_get_block_width(uint32_t basis_tex_fmt_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_tex_format_get_block_height")
|
||||
uint32_t bt_basis_tex_format_get_block_height(uint32_t basis_tex_fmt_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_tex_format_is_hdr")
|
||||
wasm_bool_t bt_basis_tex_format_is_hdr(uint32_t basis_tex_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_tex_format_is_ldr")
|
||||
wasm_bool_t bt_basis_tex_format_is_ldr(uint32_t basis_tex_format_u32);
|
||||
|
||||
// transcoder_texture_format helpers
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_get_bytes_per_block_or_pixel")
|
||||
uint32_t bt_basis_get_bytes_per_block_or_pixel(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_transcoder_format_has_alpha")
|
||||
wasm_bool_t bt_basis_transcoder_format_has_alpha(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_transcoder_format_is_hdr")
|
||||
wasm_bool_t bt_basis_transcoder_format_is_hdr(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_transcoder_format_is_ldr")
|
||||
wasm_bool_t bt_basis_transcoder_format_is_ldr(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_transcoder_texture_format_is_astc")
|
||||
wasm_bool_t bt_basis_transcoder_texture_format_is_astc(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_transcoder_format_is_uncompressed")
|
||||
wasm_bool_t bt_basis_transcoder_format_is_uncompressed(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_get_uncompressed_bytes_per_pixel")
|
||||
uint32_t bt_basis_get_uncompressed_bytes_per_pixel(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_get_block_width")
|
||||
uint32_t bt_basis_get_block_width(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_get_block_height")
|
||||
uint32_t bt_basis_get_block_height(uint32_t transcoder_texture_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_get_transcoder_texture_format_from_basis_tex_format")
|
||||
uint32_t bt_basis_get_transcoder_texture_format_from_basis_tex_format(uint32_t basis_tex_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_is_format_supported")
|
||||
wasm_bool_t bt_basis_is_format_supported(uint32_t transcoder_texture_format_u32, uint32_t basis_tex_format_u32);
|
||||
|
||||
BU_WASM_EXPORT("bt_basis_compute_transcoded_image_size_in_bytes")
|
||||
uint32_t bt_basis_compute_transcoded_image_size_in_bytes(uint32_t transcoder_texture_format_u32, uint32_t orig_width, uint32_t orig_height);
|
||||
|
||||
// Transcoding
|
||||
BU_WASM_EXPORT("bt_ktx2_open")
|
||||
uint64_t bt_ktx2_open(uint64_t data_mem_ofs, uint32_t data_len);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_close")
|
||||
void bt_ktx2_close(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_width")
|
||||
uint32_t bt_ktx2_get_width(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_height")
|
||||
uint32_t bt_ktx2_get_height(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_levels")
|
||||
uint32_t bt_ktx2_get_levels(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_faces")
|
||||
uint32_t bt_ktx2_get_faces(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_layers")
|
||||
uint32_t bt_ktx2_get_layers(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_basis_tex_format")
|
||||
uint32_t bt_ktx2_get_basis_tex_format(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_etc1s")
|
||||
wasm_bool_t bt_ktx2_is_etc1s(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_uastc_ldr_4x4")
|
||||
wasm_bool_t bt_ktx2_is_uastc_ldr_4x4(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_hdr")
|
||||
wasm_bool_t bt_ktx2_is_hdr(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_hdr_4x4")
|
||||
wasm_bool_t bt_ktx2_is_hdr_4x4(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_hdr_6x6")
|
||||
wasm_bool_t bt_ktx2_is_hdr_6x6(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_ldr")
|
||||
wasm_bool_t bt_ktx2_is_ldr(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_astc_ldr")
|
||||
wasm_bool_t bt_ktx2_is_astc_ldr(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_xuastc_ldr")
|
||||
wasm_bool_t bt_ktx2_is_xuastc_ldr(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_block_width")
|
||||
uint32_t bt_ktx2_get_block_width(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_block_height")
|
||||
uint32_t bt_ktx2_get_block_height(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_has_alpha")
|
||||
wasm_bool_t bt_ktx2_has_alpha(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_color_model")
|
||||
uint32_t bt_ktx2_get_dfd_color_model(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_color_primaries")
|
||||
uint32_t bt_ktx2_get_dfd_color_primaries(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_transfer_func")
|
||||
uint32_t bt_ktx2_get_dfd_transfer_func(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_srgb")
|
||||
wasm_bool_t bt_ktx2_is_srgb(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_flags")
|
||||
uint32_t bt_ktx2_get_dfd_flags(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_total_samples")
|
||||
uint32_t bt_ktx2_get_dfd_total_samples(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_channel_id0")
|
||||
uint32_t bt_ktx2_get_dfd_channel_id0(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_dfd_channel_id1")
|
||||
uint32_t bt_ktx2_get_dfd_channel_id1(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_is_video")
|
||||
wasm_bool_t bt_ktx2_is_video(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_ldr_hdr_upconversion_nit_multiplier")
|
||||
float bt_ktx2_get_ldr_hdr_upconversion_nit_multiplier(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_orig_width")
|
||||
uint32_t bt_ktx2_get_level_orig_width(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_orig_height")
|
||||
uint32_t bt_ktx2_get_level_orig_height(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_actual_width")
|
||||
uint32_t bt_ktx2_get_level_actual_width(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_actual_height")
|
||||
uint32_t bt_ktx2_get_level_actual_height(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_num_blocks_x")
|
||||
uint32_t bt_ktx2_get_level_num_blocks_x(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_num_blocks_y")
|
||||
uint32_t bt_ktx2_get_level_num_blocks_y(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_total_blocks")
|
||||
uint32_t bt_ktx2_get_level_total_blocks(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_alpha_flag")
|
||||
wasm_bool_t bt_ktx2_get_level_alpha_flag(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_get_level_iframe_flag")
|
||||
wasm_bool_t bt_ktx2_get_level_iframe_flag(uint64_t handle, uint32_t level_index, uint32_t layer_index, uint32_t face_index);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_start_transcoding")
|
||||
wasm_bool_t bt_ktx2_start_transcoding(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_create_transcode_state")
|
||||
uint64_t bt_ktx2_create_transcode_state();
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_destroy_transcode_state")
|
||||
void bt_ktx2_destroy_transcode_state(uint64_t handle);
|
||||
|
||||
BU_WASM_EXPORT("bt_ktx2_transcode_image_level")
|
||||
wasm_bool_t bt_ktx2_transcode_image_level(
|
||||
uint64_t ktx2_handle, // handle to KTX2 file, see bt_ktx2_open()
|
||||
uint32_t level_index, uint32_t layer_index, uint32_t face_index, // KTX2 level/layer/face to transcode
|
||||
uint64_t output_block_mem_ofs, // allocate using bt_alloc()
|
||||
uint32_t output_blocks_buf_size_in_blocks_or_pixels,
|
||||
uint32_t transcoder_texture_format_u32, // target format, TF_ETC1_RGB etc.
|
||||
uint32_t decode_flags, // DECODE_FLAGS_
|
||||
uint32_t output_row_pitch_in_blocks_or_pixels, // can be 0
|
||||
uint32_t output_rows_in_pixels, // can be 0
|
||||
int channel0, int channel1, // both default to -1
|
||||
uint64_t state_handle); // thread local state: can be 0, or bt_ktx2_create_transcode_state()
|
||||
|
||||
707
example_capi/example_capi.c
Normal file
707
example_capi/example_capi.c
Normal file
@@ -0,0 +1,707 @@
|
||||
// example_capi.c - Plain C API examples
|
||||
// Compresses a procedurally generated 32bpp 512x512 test image to a XUASTC LDR 8x5 .ktx2 file with mipmaps and writes a .ktx2 file.
|
||||
// The .ktx2 file is then opened by the transcoder module, examined and unpacked to RGBA 32bpp and ASTC textures which are saved to disk as .tga and .astc files.
|
||||
// The .tga image files can be viewed by many common image editors/viewers.
|
||||
// The standard .astc texture files can be unpacked to .PNG using ARM's astcenc tool, using a command line like this: astcenc-avx2.exe -ds transcoded_0_0_0.astc 0.png
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
|
||||
typedef int BOOL;
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
|
||||
// Include compressor and transcoder C API definitions
|
||||
#include "../encoder/basisu_wasm_api.h"
|
||||
#include "../encoder/basisu_wasm_transcoder_api.h"
|
||||
|
||||
// Write a blob of data in memory to a file
|
||||
int write_blob_to_file(const char* pFilename, const void* pData, size_t len)
|
||||
{
|
||||
assert(pFilename != NULL);
|
||||
assert(pData != NULL);
|
||||
|
||||
if (!pFilename || !pData)
|
||||
return FALSE;
|
||||
|
||||
FILE* f = fopen(pFilename, "wb");
|
||||
if (!f)
|
||||
return FALSE;
|
||||
|
||||
/* Write the data */
|
||||
size_t written = fwrite(pData, 1, len, f);
|
||||
if (written != len)
|
||||
{
|
||||
fclose(f);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (fclose(f) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE; /* success */
|
||||
}
|
||||
|
||||
// Writes 24/32bpp .TGA image files
|
||||
int write_tga_image(const char* pFilename, int w, int h, int has_alpha, const uint8_t* pPixelsRGBA)
|
||||
{
|
||||
assert(pFilename != NULL);
|
||||
assert(pPixelsRGBA != NULL);
|
||||
assert(w > 0);
|
||||
assert(h > 0);
|
||||
assert((has_alpha == 0) || (has_alpha == 1));
|
||||
|
||||
/* Runtime argument validation */
|
||||
if ((!pFilename) || (!pPixelsRGBA) || (w <= 0) || (h <= 0))
|
||||
return -1; // invalid argument
|
||||
|
||||
FILE* pFile = fopen(pFilename, "wb");
|
||||
if (!pFile)
|
||||
return -2; // cannot open file
|
||||
|
||||
uint8_t header[18] = { 0 };
|
||||
header[2] = 2; // uncompressed true-color
|
||||
header[12] = (uint8_t)(w & 0xFF);
|
||||
header[13] = (uint8_t)((w >> 8) & 0xFF);
|
||||
header[14] = (uint8_t)(h & 0xFF);
|
||||
header[15] = (uint8_t)((h >> 8) & 0xFF);
|
||||
header[16] = has_alpha ? 32 : 24;
|
||||
|
||||
/* Classic TGA: bottom-left origin */
|
||||
header[17] = has_alpha ? 8 : 0;
|
||||
|
||||
if (fwrite(header, 1, 18, pFile) != 18)
|
||||
{
|
||||
fclose(pFile);
|
||||
return -3; // header write failed
|
||||
}
|
||||
|
||||
uint64_t bytes_per_pixel = has_alpha ? 4ULL : 3ULL;
|
||||
uint64_t pixel_bytes_u64 = (uint64_t)w * (uint64_t)h * bytes_per_pixel;
|
||||
size_t pixel_bytes = (size_t)pixel_bytes_u64;
|
||||
|
||||
if ((uint64_t)pixel_bytes != pixel_bytes_u64)
|
||||
return -6; // overflow bogus dimensions
|
||||
|
||||
/* allocate one scanline for BGRA/BGR output */
|
||||
size_t row_bytes = (size_t)w * bytes_per_pixel;
|
||||
uint8_t* pRow = (uint8_t*)malloc(row_bytes);
|
||||
if (!pRow)
|
||||
{
|
||||
fclose(pFile);
|
||||
return -7; // out of memory
|
||||
}
|
||||
|
||||
/* TGA expects rows in bottom-to-top order */
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
const uint8_t* pSrcRow = pPixelsRGBA + (size_t)(h - 1 - y) * w * bytes_per_pixel;
|
||||
|
||||
/* Convert RGBA->BGRA or RGB->BGR for this row */
|
||||
if (has_alpha)
|
||||
{
|
||||
/* 4 bytes per pixel */
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
const uint8_t* s = &pSrcRow[x * 4];
|
||||
uint8_t* d = &pRow[x * 4];
|
||||
|
||||
d[0] = s[2]; // B
|
||||
d[1] = s[1]; // G
|
||||
d[2] = s[0]; // R
|
||||
d[3] = s[3]; // A
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 3 bytes per pixel */
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
const uint8_t* s = &pSrcRow[x * 3];
|
||||
uint8_t* d = &pRow[x * 3];
|
||||
|
||||
d[0] = s[2]; // B
|
||||
d[1] = s[1]; // G
|
||||
d[2] = s[0]; // R
|
||||
}
|
||||
}
|
||||
|
||||
if (fwrite(pRow, 1, row_bytes, pFile) != row_bytes)
|
||||
{
|
||||
free(pRow);
|
||||
fclose(pFile);
|
||||
return -4; // pixel write failed
|
||||
}
|
||||
}
|
||||
|
||||
free(pRow);
|
||||
|
||||
if (fclose(pFile) != 0)
|
||||
return -5; // close failed
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
// Write standard ARM .ASTC format texture files
|
||||
int write_astc_file(const char* pFilename,
|
||||
const void* pBlocks, // pointer to ASTC blocks
|
||||
uint32_t block_width, // in texels [4,12]
|
||||
uint32_t block_height, // in texels [4,12]
|
||||
uint32_t dim_x, // image actual dimension in texels
|
||||
uint32_t dim_y) // image actual dimension in texels
|
||||
{
|
||||
assert(pFilename != NULL);
|
||||
assert(pBlocks != NULL);
|
||||
assert(dim_x > 0);
|
||||
assert(dim_y > 0);
|
||||
assert((block_width >= 4) && (block_width <= 12));
|
||||
assert((block_height >= 4) && (block_height <= 12));
|
||||
|
||||
FILE* f = fopen(pFilename, "wb");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
/* Helper macro for writing single bytes with error check */
|
||||
#define PUTB(v) do { if (fputc((int)(v), f) == EOF) { fclose(f); return 0; } } while (0)
|
||||
|
||||
/* Magic */
|
||||
PUTB(0x13);
|
||||
PUTB(0xAB);
|
||||
PUTB(0xA1);
|
||||
PUTB(0x5C);
|
||||
|
||||
/* Block dimensions: x, y, z = 1 */
|
||||
PUTB((uint8_t)block_width);
|
||||
PUTB((uint8_t)block_height);
|
||||
PUTB(1); /* block depth */
|
||||
|
||||
/* dim_x (24-bit little endian) */
|
||||
PUTB((uint8_t)(dim_x & 0xFF));
|
||||
PUTB((uint8_t)((dim_x >> 8) & 0xFF));
|
||||
PUTB((uint8_t)((dim_x >> 16) & 0xFF));
|
||||
|
||||
/* dim_y (24-bit little endian) */
|
||||
PUTB((uint8_t)(dim_y & 0xFF));
|
||||
PUTB((uint8_t)((dim_y >> 8) & 0xFF));
|
||||
PUTB((uint8_t)((dim_y >> 16) & 0xFF));
|
||||
|
||||
/* dim_z = 1 (24-bit LE) */
|
||||
PUTB(1);
|
||||
PUTB(0);
|
||||
PUTB(0);
|
||||
|
||||
/* Compute block count and total bytes */
|
||||
uint32_t num_blocks_x = (dim_x + block_width - 1) / block_width;
|
||||
uint32_t num_blocks_y = (dim_y + block_height - 1) / block_height;
|
||||
|
||||
uint64_t total_bytes_u64 =
|
||||
(uint64_t)num_blocks_x * (uint64_t)num_blocks_y * 16ULL;
|
||||
|
||||
size_t total_bytes = (size_t)total_bytes_u64;
|
||||
|
||||
if ((uint64_t)total_bytes != total_bytes_u64)
|
||||
{
|
||||
fclose(f);
|
||||
return 0; /* overflow → fail */
|
||||
}
|
||||
|
||||
/* Write block data directly */
|
||||
size_t written = fwrite(pBlocks, 1, total_bytes, f);
|
||||
if (written != total_bytes)
|
||||
{
|
||||
fclose(f); /* still close even if error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fclose(f) != 0)
|
||||
return 0;
|
||||
|
||||
return 1; /* success */
|
||||
|
||||
#undef PUTB
|
||||
}
|
||||
|
||||
// Procedurally create a simple test image in memory
|
||||
uint8_t* create_pretty_rgba_pattern(int w, int h, float q)
|
||||
{
|
||||
if (w <= 0 || h <= 0)
|
||||
return NULL;
|
||||
|
||||
uint8_t* pImage = (uint8_t*)malloc((size_t)w * h * 4);
|
||||
if (!pImage)
|
||||
return NULL;
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
/* normalized coordinates 0..1 */
|
||||
float fx = (float)x / (float)w;
|
||||
float fy = (float)y / (float)h;
|
||||
|
||||
/* --- Extra coordinate warping when q != 0 --- */
|
||||
if (q != 0.0f) {
|
||||
float warp = sinf((fx + fy) * 10.0f * q);
|
||||
fx += 0.15f * q * warp;
|
||||
fy += 0.15f * q * sinf((fx - fy) * 8.0f * q);
|
||||
}
|
||||
|
||||
/* Original plasma formula */
|
||||
float v = sinf(fx * 12.0f + fy * 4.0f);
|
||||
v += sinf(fy * 9.0f - fx * 6.0f);
|
||||
v += sinf((fx + fy) * 7.0f);
|
||||
|
||||
/* Extra variation term — contributes only when q != 0 */
|
||||
if (q != 0.0f)
|
||||
{
|
||||
v += q * 0.7f * sinf((fx * fx + fy) * 20.0f);
|
||||
v += q * 0.4f * cosf((fx - fy) * 18.0f);
|
||||
}
|
||||
|
||||
/* scale to 0..1 */
|
||||
v = v * 0.25f + 0.5f;
|
||||
|
||||
float L = 1.5f;
|
||||
|
||||
/* Convert to RGB colors */
|
||||
int r = (int)roundf(255.0f * sinf(v * 6.28f) * L);
|
||||
int g = (int)roundf(255.0f * (1.0f - v) * L);
|
||||
int b = (int)roundf(255.0f * v * L);
|
||||
|
||||
/* clamp */
|
||||
if (r < 0) r = 0; else if (r > 255) r = 255;
|
||||
if (g < 0) g = 0; else if (g > 255) g = 255;
|
||||
if (b < 0) b = 0; else if (b > 255) b = 255;
|
||||
|
||||
/* write RGBA */
|
||||
uint8_t* p = &pImage[(y * w + x) * 4];
|
||||
p[0] = (uint8_t)r;
|
||||
p[1] = (uint8_t)g;
|
||||
p[2] = (uint8_t)b;
|
||||
p[3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
return pImage;
|
||||
}
|
||||
|
||||
// Takes a KTX2 file in memory and displays info about it, then transcodes it to RGBA32 and ASTC, writing .tga/.astc files to disk
|
||||
int transcode_ktx2_file(const void* pKTX2_data, size_t ktx2_data_size, const char *pDesc)
|
||||
{
|
||||
printf("------ transcode_ktx2_file(): ktx2 size: %zu, desc: %s\n", ktx2_data_size, pDesc);
|
||||
|
||||
if (!pKTX2_data || !ktx2_data_size)
|
||||
return FALSE;
|
||||
|
||||
if ((uint32_t)ktx2_data_size != ktx2_data_size)
|
||||
return FALSE;
|
||||
|
||||
uint64_t ktx2_data_ofs = bt_alloc(ktx2_data_size);
|
||||
if (!ktx2_data_ofs)
|
||||
return FALSE;
|
||||
|
||||
memcpy((void*)ktx2_data_ofs, pKTX2_data, ktx2_data_size);
|
||||
|
||||
uint64_t ktx2_handle = bt_ktx2_open(ktx2_data_ofs, (uint32_t)ktx2_data_size);
|
||||
if (!ktx2_handle)
|
||||
{
|
||||
bt_free(ktx2_data_ofs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Just testing LDR here for now
|
||||
if (!bt_ktx2_is_ldr(ktx2_handle))
|
||||
{
|
||||
bt_ktx2_close(ktx2_handle);
|
||||
bt_free(ktx2_data_ofs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!bt_ktx2_start_transcoding(ktx2_handle))
|
||||
{
|
||||
bt_ktx2_close(ktx2_handle);
|
||||
bt_free(ktx2_data_ofs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint32_t width = bt_ktx2_get_width(ktx2_handle), height = bt_ktx2_get_height(ktx2_handle);
|
||||
uint32_t levels = bt_ktx2_get_levels(ktx2_handle); // number of mipmap levels, must be >= 1
|
||||
uint32_t faces = bt_ktx2_get_faces(ktx2_handle); // 1 or 6
|
||||
uint32_t layers = bt_ktx2_get_layers(ktx2_handle); // 0 or array size
|
||||
|
||||
uint32_t basis_tex_format = bt_ktx2_get_basis_tex_format(ktx2_handle);
|
||||
uint32_t block_width = bt_ktx2_get_block_width(ktx2_handle);
|
||||
uint32_t block_height = bt_ktx2_get_block_height(ktx2_handle);
|
||||
uint32_t is_srgb = bt_ktx2_is_srgb(ktx2_handle);
|
||||
uint32_t is_video = bt_ktx2_is_video(ktx2_handle); // only reliably set after calling bt_ktx2_start_transcoding()
|
||||
|
||||
printf("KTX2 Dimensions: %ux%u, Levels: %u, Faces: %u, Layers: %u\n", width, height, levels, faces, layers);
|
||||
printf("basis_tex_format: %u\n", basis_tex_format);
|
||||
printf("Block dimensions: %ux%u\n", block_width, block_height);
|
||||
printf("is sRGB: %u\n", is_srgb);
|
||||
printf("is video: %u\n", is_video);
|
||||
|
||||
assert((width >= 1) && (height >= 1));
|
||||
assert(levels >= 1);
|
||||
assert((faces == 6) || (faces == 1));
|
||||
|
||||
// If layers==0 it's not a texture array
|
||||
if (layers < 1)
|
||||
layers = 1;
|
||||
|
||||
// Create our transcoding state handle (which contains thread-local state)
|
||||
// This is actually optional, and only needed for thread-safe transcoding, but we'll test it here.
|
||||
uint64_t transcode_state_handle = bt_ktx2_create_transcode_state();
|
||||
|
||||
for (uint32_t level_index = 0; level_index < levels; level_index++)
|
||||
{
|
||||
for (uint32_t layer_index = 0; layer_index < layers; layer_index++)
|
||||
{
|
||||
for (uint32_t face_index = 0; face_index < faces; face_index++)
|
||||
{
|
||||
printf("- Level: %u, layer: %u, face: %u\n", level_index, layer_index, face_index);
|
||||
|
||||
uint32_t orig_width = bt_ktx2_get_level_orig_width(ktx2_handle, level_index, layer_index, face_index);
|
||||
uint32_t orig_height = bt_ktx2_get_level_orig_height(ktx2_handle, level_index, layer_index, face_index);
|
||||
|
||||
printf(" Orig dimensions: %ux%u, actual: %ux%u\n",
|
||||
orig_width, orig_height,
|
||||
bt_ktx2_get_level_actual_width(ktx2_handle, level_index, layer_index, face_index), bt_ktx2_get_level_actual_height(ktx2_handle, level_index, layer_index, face_index));
|
||||
|
||||
printf(" Block dimensions: %ux%u, total blocks: %u\n",
|
||||
bt_ktx2_get_level_num_blocks_x(ktx2_handle, level_index, layer_index, face_index),
|
||||
bt_ktx2_get_level_num_blocks_y(ktx2_handle, level_index, layer_index, face_index),
|
||||
bt_ktx2_get_level_total_blocks(ktx2_handle, level_index, layer_index, face_index));
|
||||
|
||||
printf(" Alpha flag: %u, iframe flag: %u\n",
|
||||
bt_ktx2_get_level_alpha_flag(ktx2_handle, level_index, layer_index, face_index),
|
||||
bt_ktx2_get_level_iframe_flag(ktx2_handle, level_index, layer_index, face_index));
|
||||
|
||||
// First transcode level to uncompressed RGBA32 and write a .tga file
|
||||
{
|
||||
char tga_filename[256];
|
||||
snprintf(tga_filename, sizeof(tga_filename), "transcoded_%s_L%u_Y%u_F%u.tga", pDesc, level_index, layer_index, face_index);
|
||||
|
||||
uint32_t transcode_buf_size = bt_basis_compute_transcoded_image_size_in_bytes(TF_RGBA32, orig_width, orig_height);
|
||||
assert(transcode_buf_size);
|
||||
|
||||
uint64_t transcode_buf_ofs = bt_alloc(transcode_buf_size);
|
||||
|
||||
uint32_t decode_flags = 0;
|
||||
|
||||
if (!bt_ktx2_transcode_image_level(ktx2_handle, level_index, layer_index, face_index,
|
||||
transcode_buf_ofs, transcode_buf_size,
|
||||
TF_RGBA32,
|
||||
decode_flags,
|
||||
0, 0, -1, -1, transcode_state_handle))
|
||||
{
|
||||
bt_free(transcode_buf_ofs);
|
||||
bt_ktx2_destroy_transcode_state(transcode_state_handle);
|
||||
bt_ktx2_close(ktx2_handle);
|
||||
bt_free(ktx2_data_ofs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
write_tga_image(tga_filename, orig_width, orig_height, TRUE, (uint8_t*)transcode_buf_ofs);
|
||||
printf("Wrote file %s\n", tga_filename);
|
||||
|
||||
bt_free(transcode_buf_ofs);
|
||||
transcode_buf_ofs = 0;
|
||||
}
|
||||
|
||||
// Now transcode to ASTC and write a .astc file
|
||||
{
|
||||
char astc_filename[256];
|
||||
snprintf(astc_filename, sizeof(astc_filename), "transcoded_%s_L%u_Y%u_F%u.astc", pDesc, level_index, layer_index, face_index);
|
||||
|
||||
// Determine the correct ASTC transcode texture format from the ktx2 format
|
||||
uint32_t target_transcode_fmt = bt_basis_get_transcoder_texture_format_from_basis_tex_format(basis_tex_format);
|
||||
|
||||
uint32_t transcode_buf_size = bt_basis_compute_transcoded_image_size_in_bytes(target_transcode_fmt, orig_width, orig_height);
|
||||
assert(transcode_buf_size);
|
||||
|
||||
uint64_t transcode_buf_ofs = bt_alloc(transcode_buf_size);
|
||||
|
||||
uint32_t decode_flags = 0;
|
||||
|
||||
if (!bt_ktx2_transcode_image_level(ktx2_handle, level_index, layer_index, face_index,
|
||||
transcode_buf_ofs, transcode_buf_size,
|
||||
target_transcode_fmt,
|
||||
decode_flags,
|
||||
0, 0, -1, -1, transcode_state_handle))
|
||||
{
|
||||
bt_free(transcode_buf_ofs);
|
||||
bt_ktx2_destroy_transcode_state(transcode_state_handle);
|
||||
bt_ktx2_close(ktx2_handle);
|
||||
bt_free(ktx2_data_ofs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
write_astc_file(astc_filename, (void*)transcode_buf_ofs, block_width, block_height, orig_width, orig_height);
|
||||
printf("Wrote .astc file %s\n", astc_filename);
|
||||
|
||||
bt_free(transcode_buf_ofs);
|
||||
transcode_buf_ofs = 0;
|
||||
}
|
||||
|
||||
} // face_index
|
||||
|
||||
} // layer_index
|
||||
|
||||
} // level_index
|
||||
|
||||
bt_ktx2_destroy_transcode_state(transcode_state_handle);
|
||||
transcode_state_handle = 0;
|
||||
|
||||
bt_ktx2_close(ktx2_handle);
|
||||
ktx2_handle = 0;
|
||||
|
||||
bt_free(ktx2_data_ofs);
|
||||
ktx2_data_ofs = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Simple 2D test
|
||||
int test_2D()
|
||||
{
|
||||
printf("------ test_2D():\n");
|
||||
|
||||
// Generate a test image
|
||||
int W = 512, H = 512;
|
||||
|
||||
uint8_t* pSrc_image = create_pretty_rgba_pattern(W, H, 0.0f);
|
||||
|
||||
// Save the test image to a .tga file
|
||||
write_tga_image("test_image.tga", W, H, TRUE, pSrc_image);
|
||||
printf("Wrote file test_image.tga\n");
|
||||
|
||||
// Compress it to .ktx2
|
||||
uint64_t comp_params = bu_new_comp_params();
|
||||
|
||||
// Allocate memory
|
||||
uint64_t img_ofs = bu_alloc(W * H * 4);
|
||||
if (!img_ofs)
|
||||
{
|
||||
fprintf(stderr, "bu_alloc() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Copy the test image into the allocated memory
|
||||
memcpy((void*)img_ofs, pSrc_image, W * H * 4);
|
||||
|
||||
// Supply the image to the compressor - it'll immediately make a copy of the data
|
||||
if (!bu_comp_params_set_image_rgba32(comp_params, 0, img_ofs, W, H, W * 4))
|
||||
{
|
||||
fprintf(stderr, "bu_comp_params_set_image_rgba32() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bu_free(img_ofs);
|
||||
img_ofs = 0;
|
||||
|
||||
// Now compress it to XUASTC LDR 8x5 with weight grid DCT
|
||||
uint32_t basis_tex_format = BTF_XUASTC_LDR_8X5;
|
||||
//uint32_t basis_tex_format = BTF_ASTC_LDR_8X5;
|
||||
//uint32_t basis_tex_format = BTF_ETC1S;
|
||||
//uint32_t basis_tex_format = BTF_UASTC_LDR_4X4;
|
||||
|
||||
uint32_t quality_level = 85;
|
||||
uint32_t effort_level = 2;
|
||||
|
||||
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_SRGB |
|
||||
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_GEN_MIPS_CLAMP |
|
||||
BU_COMP_FLAGS_PRINT_STATS | BU_COMP_FLAGS_PRINT_STATUS;
|
||||
|
||||
if (!bu_compress_texture(comp_params, basis_tex_format, quality_level, effort_level, flags, 0.0f))
|
||||
{
|
||||
fprintf(stderr, "bu_compress_texture() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Retrieve the compressed .KTX2 file data
|
||||
uint64_t comp_size = bu_comp_params_get_comp_data_size(comp_params);
|
||||
if (!comp_size)
|
||||
{
|
||||
fprintf(stderr, "bu_comp_params_get_comp_data_size() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void* pComp_data = (void*)bu_comp_params_get_comp_data_ofs(comp_params);
|
||||
if (!pComp_data)
|
||||
{
|
||||
fprintf(stderr, "bu_comp_params_get_comp_data_ofs() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Write the data to disk
|
||||
write_blob_to_file("test.ktx2", pComp_data, comp_size);
|
||||
printf("Wrote file test.ktx2\n");
|
||||
|
||||
// Now inspect and transcode the .KTX2 data to png/astc files
|
||||
if (!transcode_ktx2_file(pComp_data, comp_size, "2D"))
|
||||
{
|
||||
fprintf(stderr, "transcode_ktx2_file() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bu_delete_comp_params(comp_params);
|
||||
|
||||
free(pSrc_image);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// 2D array/texture video test
|
||||
int test_2D_array(BOOL tex_video_flag, int L, BOOL mipmap_flag)
|
||||
{
|
||||
printf("------ test_2D_array() %i %i %i:\n", tex_video_flag, L, mipmap_flag);
|
||||
|
||||
// Generate a test image
|
||||
int W = 256, H = 256;
|
||||
|
||||
// Compress it to .ktx2
|
||||
uint64_t comp_params = bu_new_comp_params();
|
||||
|
||||
const char* pDesc = tex_video_flag ? "video" : "array";
|
||||
|
||||
char filename_buf[256];
|
||||
|
||||
for (int layer = 0; layer < L; layer++)
|
||||
{
|
||||
uint8_t* pSrc_image = create_pretty_rgba_pattern(W, H, (float)layer * .05f);
|
||||
|
||||
// Save the test image to a .tga file
|
||||
snprintf(filename_buf, sizeof(filename_buf), "test_%s_layer_%u.tga", pDesc, layer);
|
||||
|
||||
write_tga_image(filename_buf, W, H, TRUE, pSrc_image);
|
||||
printf("Wrote file %s\n", filename_buf);
|
||||
|
||||
// Allocate memory
|
||||
uint64_t img_ofs = bu_alloc(W * H * 4);
|
||||
if (!img_ofs)
|
||||
{
|
||||
fprintf(stderr, "bu_alloc() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Copy the test image into the allocated memory
|
||||
memcpy((void*)img_ofs, pSrc_image, W * H * 4);
|
||||
|
||||
// Supply the image to the compressor - it'll immediately make a copy of the data
|
||||
if (!bu_comp_params_set_image_rgba32(comp_params, layer, img_ofs, W, H, W * 4))
|
||||
{
|
||||
fprintf(stderr, "bu_comp_params_set_image_rgba32() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bu_free(img_ofs);
|
||||
img_ofs = 0;
|
||||
|
||||
free(pSrc_image);
|
||||
|
||||
} // layer
|
||||
|
||||
// ETC1S has special optimizations for texture video (basic p-frames with skip blocks).
|
||||
uint32_t basis_tex_format = tex_video_flag ? BTF_ETC1S : BTF_XUASTC_LDR_4X4;
|
||||
|
||||
uint32_t quality_level = 100;
|
||||
uint32_t effort_level = 4;
|
||||
|
||||
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_SRGB |
|
||||
BU_COMP_FLAGS_THREADED |
|
||||
BU_COMP_FLAGS_PRINT_STATS | BU_COMP_FLAGS_PRINT_STATUS;
|
||||
|
||||
if (tex_video_flag)
|
||||
flags |= BU_COMP_FLAGS_TEXTURE_TYPE_VIDEO_FRAMES;
|
||||
else
|
||||
flags |= BU_COMP_FLAGS_TEXTURE_TYPE_2D_ARRAY;
|
||||
|
||||
if (mipmap_flag)
|
||||
flags |= BU_COMP_FLAGS_GEN_MIPS_CLAMP;
|
||||
|
||||
if (!bu_compress_texture(comp_params, basis_tex_format, quality_level, effort_level, flags, 0.0f))
|
||||
{
|
||||
fprintf(stderr, "bu_compress_texture() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Retrieve the compressed .KTX2 file data
|
||||
uint64_t comp_size = bu_comp_params_get_comp_data_size(comp_params);
|
||||
if (!comp_size)
|
||||
{
|
||||
fprintf(stderr, "bu_comp_params_get_comp_data_size() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void* pComp_data = (void*)bu_comp_params_get_comp_data_ofs(comp_params);
|
||||
if (!pComp_data)
|
||||
{
|
||||
fprintf(stderr, "bu_comp_params_get_comp_data_ofs() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Write the data to disk
|
||||
snprintf(filename_buf, sizeof(filename_buf), "test_%s.ktx2", pDesc);
|
||||
write_blob_to_file(filename_buf, pComp_data, comp_size);
|
||||
printf("Wrote file %s\n", filename_buf);
|
||||
|
||||
// Now inspect and transcode the .KTX2 data to png/astc files
|
||||
if (!transcode_ktx2_file(pComp_data, comp_size, pDesc))
|
||||
{
|
||||
fprintf(stderr, "transcode_ktx2_file() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bu_delete_comp_params(comp_params);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
printf("example_capi.c:\n");
|
||||
|
||||
// Initialize the encoder (which initializers the transcoder for us)
|
||||
printf("bu_init:\n");
|
||||
bu_init();
|
||||
|
||||
// bu_init() already does this for us, but it's harmless to call again.
|
||||
printf("bt_init:\n");
|
||||
bt_init();
|
||||
|
||||
// Control debug output from the compressor
|
||||
bu_enable_debug_printf(FALSE);
|
||||
|
||||
// simple 2D
|
||||
if (test_2D() != EXIT_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "test_2D() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// 2D array
|
||||
if (test_2D_array(FALSE, 8, FALSE) != EXIT_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "test_2D_array() (array mode) failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// texture video
|
||||
if (test_2D_array(TRUE, 8, TRUE) != EXIT_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "test_2D_array() (texture video mode) failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Success\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
238
example_capi/example_capi.vcxproj
Normal file
238
example_capi/example_capi.vcxproj
Normal file
@@ -0,0 +1,238 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64EC">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64EC</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64EC">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64EC</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>18.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{be889347-e4fd-47dd-bbf4-81f98faa8ba9}</ProjectGuid>
|
||||
<RootNamespace>examplecapi</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\OpenCL</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\OpenCL</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\OpenCL</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\OpenCL</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;softintrin.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\OpenCL</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\OpenCL</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>..\OpenCL\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>opencl64.lib;softintrin.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\encoder\basisu_wasm_api.cpp" />
|
||||
<ClCompile Include="..\encoder\basisu_wasm_transcoder_api.cpp" />
|
||||
<ClCompile Include="example_capi.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\encoder\basisu_wasm_api.h" />
|
||||
<ClInclude Include="..\encoder\basisu_wasm_api_common.h" />
|
||||
<ClInclude Include="..\encoder\basisu_wasm_transcoder_api.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\encoder_lib\encoder_lib.vcxproj">
|
||||
<Project>{97c34996-f458-4030-a402-b32c581872f1}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
39
example_capi/example_capi.vcxproj.filters
Normal file
39
example_capi/example_capi.vcxproj.filters
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="example_capi.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\encoder\basisu_wasm_transcoder_api.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\encoder\basisu_wasm_api.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\encoder\basisu_wasm_api_common.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\encoder\basisu_wasm_transcoder_api.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\encoder\basisu_wasm_api.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
286
example_transcoding/dds_defs.h
Normal file
286
example_transcoding/dds_defs.h
Normal file
@@ -0,0 +1,286 @@
|
||||
// File: dds_defs.h
|
||||
// DX9/10 .DDS file header definitions.
|
||||
#pragma once
|
||||
|
||||
#define PIXEL_FMT_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U))
|
||||
|
||||
enum pixel_format
|
||||
{
|
||||
PIXEL_FMT_INVALID = 0,
|
||||
|
||||
PIXEL_FMT_DXT1 = PIXEL_FMT_FOURCC('D', 'X', 'T', '1'),
|
||||
PIXEL_FMT_DXT2 = PIXEL_FMT_FOURCC('D', 'X', 'T', '2'),
|
||||
PIXEL_FMT_DXT3 = PIXEL_FMT_FOURCC('D', 'X', 'T', '3'),
|
||||
PIXEL_FMT_DXT4 = PIXEL_FMT_FOURCC('D', 'X', 'T', '4'),
|
||||
PIXEL_FMT_DXT5 = PIXEL_FMT_FOURCC('D', 'X', 'T', '5'),
|
||||
PIXEL_FMT_3DC = PIXEL_FMT_FOURCC('A', 'T', 'I', '2'), // DXN_YX
|
||||
PIXEL_FMT_DXN = PIXEL_FMT_FOURCC('A', '2', 'X', 'Y'), // DXN_XY
|
||||
PIXEL_FMT_DXT5A = PIXEL_FMT_FOURCC('A', 'T', 'I', '1'), // ATI1N, http://developer.amd.com/media/gpu_assets/Radeon_X1x00_Programming_Guide.pdf
|
||||
|
||||
// Non-standard formats (some of these are supported by ATI's Compressonator)
|
||||
PIXEL_FMT_DXT5_CCxY = PIXEL_FMT_FOURCC('C', 'C', 'x', 'Y'),
|
||||
PIXEL_FMT_DXT5_xGxR = PIXEL_FMT_FOURCC('x', 'G', 'x', 'R'),
|
||||
PIXEL_FMT_DXT5_xGBR = PIXEL_FMT_FOURCC('x', 'G', 'B', 'R'),
|
||||
PIXEL_FMT_DXT5_AGBR = PIXEL_FMT_FOURCC('A', 'G', 'B', 'R'),
|
||||
|
||||
PIXEL_FMT_DXT1A = PIXEL_FMT_FOURCC('D', 'X', '1', 'A'),
|
||||
PIXEL_FMT_ETC1 = PIXEL_FMT_FOURCC('E', 'T', 'C', '1'),
|
||||
|
||||
PIXEL_FMT_R8G8B8 = PIXEL_FMT_FOURCC('R', 'G', 'B', 'x'),
|
||||
PIXEL_FMT_L8 = PIXEL_FMT_FOURCC('L', 'x', 'x', 'x'),
|
||||
PIXEL_FMT_A8 = PIXEL_FMT_FOURCC('x', 'x', 'x', 'A'),
|
||||
PIXEL_FMT_A8L8 = PIXEL_FMT_FOURCC('L', 'x', 'x', 'A'),
|
||||
PIXEL_FMT_A8R8G8B8 = PIXEL_FMT_FOURCC('R', 'G', 'B', 'A')
|
||||
};
|
||||
|
||||
const uint32_t cDDSMaxImageDimensions = 8192U;
|
||||
|
||||
// Total size of header is sizeof(uint32)+cDDSSizeofDDSurfaceDesc2;
|
||||
const uint32_t cDDSSizeofDDSurfaceDesc2 = 124;
|
||||
|
||||
// "DDS "
|
||||
const uint32_t cDDSFileSignature = 0x20534444;
|
||||
|
||||
struct DDCOLORKEY
|
||||
{
|
||||
uint32_t dwUnused0;
|
||||
uint32_t dwUnused1;
|
||||
};
|
||||
|
||||
struct DDPIXELFORMAT
|
||||
{
|
||||
uint32_t dwSize;
|
||||
uint32_t dwFlags;
|
||||
uint32_t dwFourCC;
|
||||
uint32_t dwRGBBitCount; // ATI compressonator will place a FOURCC code here for swizzled/cooked DXTn formats
|
||||
uint32_t dwRBitMask;
|
||||
uint32_t dwGBitMask;
|
||||
uint32_t dwBBitMask;
|
||||
uint32_t dwRGBAlphaBitMask;
|
||||
};
|
||||
|
||||
struct DDSCAPS2
|
||||
{
|
||||
uint32_t dwCaps;
|
||||
uint32_t dwCaps2;
|
||||
uint32_t dwCaps3;
|
||||
uint32_t dwCaps4;
|
||||
};
|
||||
|
||||
struct DDSURFACEDESC2
|
||||
{
|
||||
uint32_t dwSize;
|
||||
uint32_t dwFlags;
|
||||
uint32_t dwHeight;
|
||||
uint32_t dwWidth;
|
||||
union
|
||||
{
|
||||
int32_t lPitch;
|
||||
uint32_t dwLinearSize;
|
||||
};
|
||||
uint32_t dwBackBufferCount;
|
||||
uint32_t dwMipMapCount;
|
||||
uint32_t dwAlphaBitDepth;
|
||||
uint32_t dwUnused0;
|
||||
uint32_t lpSurface;
|
||||
DDCOLORKEY unused0;
|
||||
DDCOLORKEY unused1;
|
||||
DDCOLORKEY unused2;
|
||||
DDCOLORKEY unused3;
|
||||
DDPIXELFORMAT ddpfPixelFormat;
|
||||
DDSCAPS2 ddsCaps;
|
||||
uint32_t dwUnused1;
|
||||
};
|
||||
|
||||
const uint32_t DDSD_CAPS = 0x00000001;
|
||||
const uint32_t DDSD_HEIGHT = 0x00000002;
|
||||
const uint32_t DDSD_WIDTH = 0x00000004;
|
||||
const uint32_t DDSD_PITCH = 0x00000008;
|
||||
|
||||
const uint32_t DDSD_BACKBUFFERCOUNT = 0x00000020;
|
||||
const uint32_t DDSD_ZBUFFERBITDEPTH = 0x00000040;
|
||||
const uint32_t DDSD_ALPHABITDEPTH = 0x00000080;
|
||||
|
||||
const uint32_t DDSD_LPSURFACE = 0x00000800;
|
||||
|
||||
const uint32_t DDSD_PIXELFORMAT = 0x00001000;
|
||||
const uint32_t DDSD_CKDESTOVERLAY = 0x00002000;
|
||||
const uint32_t DDSD_CKDESTBLT = 0x00004000;
|
||||
const uint32_t DDSD_CKSRCOVERLAY = 0x00008000;
|
||||
|
||||
const uint32_t DDSD_CKSRCBLT = 0x00010000;
|
||||
const uint32_t DDSD_MIPMAPCOUNT = 0x00020000;
|
||||
const uint32_t DDSD_REFRESHRATE = 0x00040000;
|
||||
const uint32_t DDSD_LINEARSIZE = 0x00080000;
|
||||
|
||||
const uint32_t DDSD_TEXTURESTAGE = 0x00100000;
|
||||
const uint32_t DDSD_FVF = 0x00200000;
|
||||
const uint32_t DDSD_SRCVBHANDLE = 0x00400000;
|
||||
const uint32_t DDSD_DEPTH = 0x00800000;
|
||||
|
||||
const uint32_t DDSD_ALL = 0x00fff9ee;
|
||||
|
||||
const uint32_t DDPF_ALPHAPIXELS = 0x00000001;
|
||||
const uint32_t DDPF_ALPHA = 0x00000002;
|
||||
const uint32_t DDPF_FOURCC = 0x00000004;
|
||||
const uint32_t DDPF_PALETTEINDEXED8 = 0x00000020;
|
||||
const uint32_t DDPF_RGB = 0x00000040;
|
||||
const uint32_t DDPF_LUMINANCE = 0x00020000;
|
||||
|
||||
const uint32_t DDSCAPS_COMPLEX = 0x00000008;
|
||||
const uint32_t DDSCAPS_TEXTURE = 0x00001000;
|
||||
const uint32_t DDSCAPS_MIPMAP = 0x00400000;
|
||||
|
||||
const uint32_t DDSCAPS2_CUBEMAP = 0x00000200;
|
||||
const uint32_t DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400;
|
||||
const uint32_t DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800;
|
||||
|
||||
const uint32_t DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000;
|
||||
const uint32_t DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000;
|
||||
const uint32_t DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000;
|
||||
const uint32_t DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000;
|
||||
|
||||
const uint32_t DDSCAPS2_VOLUME = 0x00200000;
|
||||
|
||||
typedef enum DXGI_FORMAT
|
||||
{
|
||||
DXGI_FORMAT_UNKNOWN = 0,
|
||||
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
|
||||
DXGI_FORMAT_R32G32B32A32_UINT = 3,
|
||||
DXGI_FORMAT_R32G32B32A32_SINT = 4,
|
||||
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
|
||||
DXGI_FORMAT_R32G32B32_FLOAT = 6,
|
||||
DXGI_FORMAT_R32G32B32_UINT = 7,
|
||||
DXGI_FORMAT_R32G32B32_SINT = 8,
|
||||
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
|
||||
DXGI_FORMAT_R16G16B16A16_UINT = 12,
|
||||
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
|
||||
DXGI_FORMAT_R16G16B16A16_SINT = 14,
|
||||
DXGI_FORMAT_R32G32_TYPELESS = 15,
|
||||
DXGI_FORMAT_R32G32_FLOAT = 16,
|
||||
DXGI_FORMAT_R32G32_UINT = 17,
|
||||
DXGI_FORMAT_R32G32_SINT = 18,
|
||||
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
|
||||
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
|
||||
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
|
||||
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
|
||||
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
|
||||
DXGI_FORMAT_R10G10B10A2_UINT = 25,
|
||||
DXGI_FORMAT_R11G11B10_FLOAT = 26,
|
||||
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
|
||||
DXGI_FORMAT_R8G8B8A8_UINT = 30,
|
||||
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
|
||||
DXGI_FORMAT_R8G8B8A8_SINT = 32,
|
||||
DXGI_FORMAT_R16G16_TYPELESS = 33,
|
||||
DXGI_FORMAT_R16G16_FLOAT = 34,
|
||||
DXGI_FORMAT_R16G16_UNORM = 35,
|
||||
DXGI_FORMAT_R16G16_UINT = 36,
|
||||
DXGI_FORMAT_R16G16_SNORM = 37,
|
||||
DXGI_FORMAT_R16G16_SINT = 38,
|
||||
DXGI_FORMAT_R32_TYPELESS = 39,
|
||||
DXGI_FORMAT_D32_FLOAT = 40,
|
||||
DXGI_FORMAT_R32_FLOAT = 41,
|
||||
DXGI_FORMAT_R32_UINT = 42,
|
||||
DXGI_FORMAT_R32_SINT = 43,
|
||||
DXGI_FORMAT_R24G8_TYPELESS = 44,
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
|
||||
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
|
||||
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
|
||||
DXGI_FORMAT_R8G8_TYPELESS = 48,
|
||||
DXGI_FORMAT_R8G8_UNORM = 49,
|
||||
DXGI_FORMAT_R8G8_UINT = 50,
|
||||
DXGI_FORMAT_R8G8_SNORM = 51,
|
||||
DXGI_FORMAT_R8G8_SINT = 52,
|
||||
DXGI_FORMAT_R16_TYPELESS = 53,
|
||||
DXGI_FORMAT_R16_FLOAT = 54,
|
||||
DXGI_FORMAT_D16_UNORM = 55,
|
||||
DXGI_FORMAT_R16_UNORM = 56,
|
||||
DXGI_FORMAT_R16_UINT = 57,
|
||||
DXGI_FORMAT_R16_SNORM = 58,
|
||||
DXGI_FORMAT_R16_SINT = 59,
|
||||
DXGI_FORMAT_R8_TYPELESS = 60,
|
||||
DXGI_FORMAT_R8_UNORM = 61,
|
||||
DXGI_FORMAT_R8_UINT = 62,
|
||||
DXGI_FORMAT_R8_SNORM = 63,
|
||||
DXGI_FORMAT_R8_SINT = 64,
|
||||
DXGI_FORMAT_A8_UNORM = 65,
|
||||
DXGI_FORMAT_R1_UNORM = 66,
|
||||
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
|
||||
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
|
||||
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
|
||||
DXGI_FORMAT_BC1_TYPELESS = 70,
|
||||
DXGI_FORMAT_BC1_UNORM = 71,
|
||||
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
|
||||
DXGI_FORMAT_BC2_TYPELESS = 73,
|
||||
DXGI_FORMAT_BC2_UNORM = 74,
|
||||
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
|
||||
DXGI_FORMAT_BC3_TYPELESS = 76,
|
||||
DXGI_FORMAT_BC3_UNORM = 77,
|
||||
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
|
||||
DXGI_FORMAT_BC4_TYPELESS = 79,
|
||||
DXGI_FORMAT_BC4_UNORM = 80,
|
||||
DXGI_FORMAT_BC4_SNORM = 81,
|
||||
DXGI_FORMAT_BC5_TYPELESS = 82,
|
||||
DXGI_FORMAT_BC5_UNORM = 83,
|
||||
DXGI_FORMAT_BC5_SNORM = 84,
|
||||
DXGI_FORMAT_B5G6R5_UNORM = 85,
|
||||
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
|
||||
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
|
||||
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
|
||||
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
|
||||
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
|
||||
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
|
||||
DXGI_FORMAT_BC6H_TYPELESS = 94,
|
||||
DXGI_FORMAT_BC6H_UF16 = 95,
|
||||
DXGI_FORMAT_BC6H_SF16 = 96,
|
||||
DXGI_FORMAT_BC7_TYPELESS = 97,
|
||||
DXGI_FORMAT_BC7_UNORM = 98,
|
||||
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
|
||||
DXGI_FORMAT_AYUV = 100,
|
||||
DXGI_FORMAT_Y410 = 101,
|
||||
DXGI_FORMAT_Y416 = 102,
|
||||
DXGI_FORMAT_NV12 = 103,
|
||||
DXGI_FORMAT_P010 = 104,
|
||||
DXGI_FORMAT_P016 = 105,
|
||||
DXGI_FORMAT_420_OPAQUE = 106,
|
||||
DXGI_FORMAT_YUY2 = 107,
|
||||
DXGI_FORMAT_Y210 = 108,
|
||||
DXGI_FORMAT_Y216 = 109,
|
||||
DXGI_FORMAT_NV11 = 110,
|
||||
DXGI_FORMAT_AI44 = 111,
|
||||
DXGI_FORMAT_IA44 = 112,
|
||||
DXGI_FORMAT_P8 = 113,
|
||||
DXGI_FORMAT_A8P8 = 114,
|
||||
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
|
||||
DXGI_FORMAT_P208 = 130,
|
||||
DXGI_FORMAT_V208 = 131,
|
||||
DXGI_FORMAT_V408 = 132,
|
||||
DXGI_FORMAT_FORCE_UINT = 0xffffffff
|
||||
} DXGI_FORMAT;
|
||||
|
||||
enum D3D10_RESOURCE_DIMENSION
|
||||
{
|
||||
D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
|
||||
D3D10_RESOURCE_DIMENSION_BUFFER = 1,
|
||||
D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
|
||||
D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
|
||||
D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4
|
||||
};
|
||||
|
||||
struct DDS_HEADER_DXT10
|
||||
{
|
||||
DXGI_FORMAT dxgiFormat;
|
||||
D3D10_RESOURCE_DIMENSION resourceDimension;
|
||||
uint32_t miscFlag;
|
||||
uint32_t arraySize;
|
||||
uint32_t miscFlags2;
|
||||
};
|
||||
|
||||
100
example_transcoding/example_transcoding.cpp
Normal file
100
example_transcoding/example_transcoding.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// example_transcoding.cpp: Very simple transcoding-only example. Does not depend on the basisu encoder library at all, just basisu_transcoder.cpp.
|
||||
// You can use AMD Compressonator or Microsoft's DirectXTex tools on github to view the written DX10 .DDS file.
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// for testing
|
||||
//#define BASISD_SUPPORT_XUASTC (0)
|
||||
//#define BASISD_SUPPORT_KTX2_ZSTD (0)
|
||||
|
||||
#include "../transcoder/basisu_transcoder.h"
|
||||
#include "utils.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
basist::basisu_transcoder_init();
|
||||
|
||||
// Read the .KTX2 file's data into memory.
|
||||
utils::uint8_vec ktx2_file_data;
|
||||
if (!utils::read_file("../test_files/base_xuastc_arith.ktx2", ktx2_file_data))
|
||||
{
|
||||
if (!utils::read_file("base_xuastc_arith.ktx2", ktx2_file_data))
|
||||
{
|
||||
fprintf(stderr, "Can't read file ../test_files/base_xuastc_arith.ktx2 or base_xuastc_arith.ktx2\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Read file base_xuastc_arith.ktx2\n");
|
||||
|
||||
if (ktx2_file_data.size() > UINT32_MAX)
|
||||
{
|
||||
fprintf(stderr, "KTX2 file too large\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
basist::ktx2_transcoder transcoder;
|
||||
|
||||
// Initialize the transcoder.
|
||||
if (!transcoder.init(ktx2_file_data.data(), (uint32_t)ktx2_file_data.size()))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
const uint32_t width = transcoder.get_width();
|
||||
const uint32_t height = transcoder.get_height();
|
||||
const uint32_t num_levels = transcoder.get_levels();
|
||||
const bool is_srgb = transcoder.is_srgb();
|
||||
|
||||
printf("KTX2 dimensions: %ux%u, num mip levels: %u, sRGB: %u\n", width, height, num_levels, is_srgb);
|
||||
|
||||
// Can't transcode HDR to LDR formats.
|
||||
if (transcoder.is_hdr())
|
||||
{
|
||||
fprintf(stderr, "Expected LDR KTX2 file\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Ensure BC7 support was enabled at compilation time (it will be enabled by default).
|
||||
const basist::transcoder_texture_format tex_fmt = basist::transcoder_texture_format::cTFBC7_RGBA;
|
||||
if (!basist::basis_is_format_supported(tex_fmt, transcoder.get_basis_tex_format()))
|
||||
{
|
||||
printf("BC7 was disabled in the transcoder at compilation\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Begin transcoding (this will be a no-op with UASTC HDR textures, but you still need to do it. For ETC1S it'll unpack the global codebooks).
|
||||
transcoder.start_transcoding();
|
||||
|
||||
// Transcode to BC7 and write a BC7 .DDS file.
|
||||
|
||||
// Bytes per block (8 or 16 for BC1-7)
|
||||
const uint32_t bytes_per_block = basist::basis_get_bytes_per_block_or_pixel(tex_fmt);
|
||||
// Compute total bytes needed to transcode the slice
|
||||
const uint32_t total_bytes = basist::basis_compute_transcoded_image_size_in_bytes(tex_fmt, width, height);
|
||||
// Derive the total number of blocks the output buffer can hold. The transcoder will use this to verify the buffer is large enough.
|
||||
const uint32_t total_blocks = total_bytes / bytes_per_block;
|
||||
|
||||
// Allocate the buffer to hold the blocks
|
||||
utils::uint8_vec tex_buffer(total_bytes);
|
||||
|
||||
// Transcode the level
|
||||
bool status = transcoder.transcode_image_level(0, 0, 0,
|
||||
tex_buffer.data(), total_blocks,
|
||||
tex_fmt, 0);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
fprintf(stderr, "transcoder.transcode_image_level() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Write an sRGB DX10-style .DDS file.
|
||||
if (!utils::save_dds("out.dds", width, height, tex_buffer.data(), 8, DXGI_FORMAT_BC7_UNORM_SRGB, true, true))
|
||||
{
|
||||
fprintf(stderr, "save_dds() failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Wrote out.dds\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
10
example_transcoding/example_transcoding.manifest
Normal file
10
example_transcoding/example_transcoding.manifest
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity type="win32" name="..." version="6.0.0.0"/>
|
||||
<application>
|
||||
<windowsSettings>
|
||||
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
|
||||
202
example_transcoding/example_transcoding.vcxproj
Normal file
202
example_transcoding/example_transcoding.vcxproj
Normal file
@@ -0,0 +1,202 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64EC">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64EC</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64EC">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64EC</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{13333092-fcfe-4d74-8e76-f10c6037593c}</ProjectGuid>
|
||||
<RootNamespace>exampletranscoding</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'">
|
||||
<ClCompile>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\transcoder\basisu_transcoder.cpp" />
|
||||
<ClCompile Include="..\zstd\zstddeclib.c" />
|
||||
<ClCompile Include="example_transcoding.cpp" />
|
||||
<ClCompile Include="utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="example_transcoding.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="dds_defs.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
47
example_transcoding/example_transcoding.vcxproj.filters
Normal file
47
example_transcoding/example_transcoding.vcxproj.filters
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\utils">
|
||||
<UniqueIdentifier>{db43163f-6d1b-46cf-90ad-24650d502e6a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="example_transcoding.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\transcoder\basisu_transcoder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils.cpp">
|
||||
<Filter>Source Files\utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\zstd\zstddeclib.c">
|
||||
<Filter>Source Files\utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="example_transcoding.manifest">
|
||||
<Filter>Source Files</Filter>
|
||||
</Manifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="utils.h">
|
||||
<Filter>Source Files\utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dds_defs.h">
|
||||
<Filter>Source Files\utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
948
example_transcoding/utils.cpp
Normal file
948
example_transcoding/utils.cpp
Normal file
@@ -0,0 +1,948 @@
|
||||
// File: utils.cpp
|
||||
#include "utils.h"
|
||||
//#include "lodepng.h"
|
||||
//#include "miniz.h"
|
||||
|
||||
namespace utils
|
||||
{
|
||||
|
||||
#define FLOOD_PUSH(y, xl, xr, dy) if (((y + (dy)) >= 0) && ((y + (dy)) < (int)m_height)) { stack.push_back(fill_segment(y, xl, xr, dy)); }
|
||||
|
||||
// See http://www.realtimerendering.com/resources/GraphicsGems/gems/SeedFill.c
|
||||
uint32_t image_u8::flood_fill(int x, int y, const color_quad_u8& c, const color_quad_u8& b, std::vector<pixel_coord>* pSet_pixels)
|
||||
{
|
||||
uint32_t total_set = 0;
|
||||
|
||||
if (!flood_fill_is_inside(x, y, b))
|
||||
return 0;
|
||||
|
||||
std::vector<fill_segment> stack;
|
||||
stack.reserve(64);
|
||||
|
||||
FLOOD_PUSH(y, x, x, 1);
|
||||
FLOOD_PUSH(y + 1, x, x, -1);
|
||||
|
||||
while (stack.size())
|
||||
{
|
||||
fill_segment s = stack.back();
|
||||
stack.pop_back();
|
||||
|
||||
int x1 = s.m_xl, x2 = s.m_xr, dy = s.m_dy;
|
||||
y = s.m_y + s.m_dy;
|
||||
|
||||
for (x = x1; (x >= 0) && flood_fill_is_inside(x, y, b); x--)
|
||||
{
|
||||
(*this)(x, y) = c;
|
||||
total_set++;
|
||||
if (pSet_pixels)
|
||||
pSet_pixels->push_back(pixel_coord(x, y));
|
||||
}
|
||||
|
||||
int l;
|
||||
|
||||
if (x >= x1)
|
||||
goto skip;
|
||||
|
||||
l = x + 1;
|
||||
if (l < x1)
|
||||
FLOOD_PUSH(y, l, x1 - 1, -dy);
|
||||
|
||||
x = x1 + 1;
|
||||
|
||||
do
|
||||
{
|
||||
for (; x <= ((int)m_width - 1) && flood_fill_is_inside(x, y, b); x++)
|
||||
{
|
||||
(*this)(x, y) = c;
|
||||
total_set++;
|
||||
if (pSet_pixels)
|
||||
pSet_pixels->push_back(pixel_coord(x, y));
|
||||
}
|
||||
FLOOD_PUSH(y, l, x - 1, dy);
|
||||
|
||||
if (x > (x2 + 1))
|
||||
FLOOD_PUSH(y, x2 + 1, x - 1, -dy);
|
||||
|
||||
skip:
|
||||
for (x++; x <= x2 && !flood_fill_is_inside(x, y, b); x++)
|
||||
;
|
||||
|
||||
l = x;
|
||||
} while (x <= x2);
|
||||
}
|
||||
|
||||
return total_set;
|
||||
}
|
||||
|
||||
void image_u8::draw_line(int xs, int ys, int xe, int ye, const color_quad_u8& color)
|
||||
{
|
||||
if (xs > xe)
|
||||
{
|
||||
std::swap(xs, xe);
|
||||
std::swap(ys, ye);
|
||||
}
|
||||
|
||||
int dx = xe - xs, dy = ye - ys;
|
||||
if (!dx)
|
||||
{
|
||||
if (ys > ye)
|
||||
std::swap(ys, ye);
|
||||
for (int i = ys; i <= ye; i++)
|
||||
set_pixel_clipped(xs, i, color);
|
||||
}
|
||||
else if (!dy)
|
||||
{
|
||||
for (int i = xs; i < xe; i++)
|
||||
set_pixel_clipped(i, ys, color);
|
||||
}
|
||||
else if (dy > 0)
|
||||
{
|
||||
if (dy <= dx)
|
||||
{
|
||||
int e = 2 * dy - dx, e_no_inc = 2 * dy, e_inc = 2 * (dy - dx);
|
||||
rasterize_line(xs, ys, xe, ye, 0, 1, e, e_inc, e_no_inc, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
int e = 2 * dx - dy, e_no_inc = 2 * dx, e_inc = 2 * (dx - dy);
|
||||
rasterize_line(xs, ys, xe, ye, 1, 1, e, e_inc, e_no_inc, color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dy = -dy;
|
||||
if (dy <= dx)
|
||||
{
|
||||
int e = 2 * dy - dx, e_no_inc = 2 * dy, e_inc = 2 * (dy - dx);
|
||||
rasterize_line(xs, ys, xe, ye, 0, -1, e, e_inc, e_no_inc, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
int e = 2 * dx - dy, e_no_inc = (2 * dx), e_inc = 2 * (dx - dy);
|
||||
rasterize_line(xe, ye, xs, ys, 1, -1, e, e_inc, e_no_inc, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void image_u8::rasterize_line(int xs, int ys, int xe, int ye, int pred, int inc_dec, int e, int e_inc, int e_no_inc, const color_quad_u8& color)
|
||||
{
|
||||
int start, end, var;
|
||||
|
||||
if (pred)
|
||||
{
|
||||
start = ys;
|
||||
end = ye;
|
||||
var = xs;
|
||||
for (int i = start; i <= end; i++)
|
||||
{
|
||||
set_pixel_clipped(var, i, color);
|
||||
if (e < 0)
|
||||
e += e_no_inc;
|
||||
else
|
||||
{
|
||||
var += inc_dec;
|
||||
e += e_inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
start = xs;
|
||||
end = xe;
|
||||
var = ys;
|
||||
for (int i = start; i <= end; i++)
|
||||
{
|
||||
set_pixel_clipped(i, var, color);
|
||||
if (e < 0)
|
||||
e += e_no_inc;
|
||||
else
|
||||
{
|
||||
var += inc_dec;
|
||||
e += e_inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool load_png(const char* pFilename, image_u8& img)
|
||||
{
|
||||
img.clear();
|
||||
|
||||
std::vector<unsigned char> pixels;
|
||||
unsigned int w = 0, h = 0;
|
||||
unsigned int e = lodepng::decode(pixels, w, h, pFilename);
|
||||
if (e != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed loading PNG file %s\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
img.init(w, h);
|
||||
memcpy(&img.get_pixels()[0], &pixels[0], w * h * sizeof(uint32_t));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool save_png(const char* pFilename, const image_u8& img, bool save_alpha)
|
||||
{
|
||||
const uint32_t w = img.width();
|
||||
const uint32_t h = img.height();
|
||||
|
||||
std::vector<unsigned char> pixels;
|
||||
if (save_alpha)
|
||||
{
|
||||
pixels.resize(w * h * sizeof(color_quad_u8));
|
||||
memcpy(&pixels[0], &img.get_pixels()[0], w * h * sizeof(color_quad_u8));
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels.resize(w * h * 3);
|
||||
unsigned char* pDst = &pixels[0];
|
||||
for (uint32_t y = 0; y < h; y++)
|
||||
for (uint32_t x = 0; x < w; x++, pDst += 3)
|
||||
pDst[0] = img(x, y)[0], pDst[1] = img(x, y)[1], pDst[2] = img(x, y)[2];
|
||||
}
|
||||
|
||||
return lodepng::encode(pFilename, pixels, w, h, save_alpha ? LCT_RGBA : LCT_RGB) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static float gauss(int x, int y, float sigma_sqr)
|
||||
{
|
||||
float pow = expf(-((x * x + y * y) / (2.0f * sigma_sqr)));
|
||||
float g = (1.0f / (sqrtf((float)(2.0f * M_PI * sigma_sqr)))) * pow;
|
||||
return g;
|
||||
}
|
||||
|
||||
// size_x/y should be odd
|
||||
void compute_gaussian_kernel(float* pDst, int size_x, int size_y, float sigma_sqr, uint32_t flags)
|
||||
{
|
||||
assert(size_x & size_y & 1);
|
||||
|
||||
if (!(size_x | size_y))
|
||||
return;
|
||||
|
||||
int mid_x = size_x / 2;
|
||||
int mid_y = size_y / 2;
|
||||
|
||||
double sum = 0;
|
||||
for (int x = 0; x < size_x; x++)
|
||||
{
|
||||
for (int y = 0; y < size_y; y++)
|
||||
{
|
||||
float g;
|
||||
if ((x > mid_x) && (y < mid_y))
|
||||
g = pDst[(size_x - x - 1) + y * size_x];
|
||||
else if ((x < mid_x) && (y > mid_y))
|
||||
g = pDst[x + (size_y - y - 1) * size_x];
|
||||
else if ((x > mid_x) && (y > mid_y))
|
||||
g = pDst[(size_x - x - 1) + (size_y - y - 1) * size_x];
|
||||
else
|
||||
g = gauss(x - mid_x, y - mid_y, sigma_sqr);
|
||||
|
||||
pDst[x + y * size_x] = g;
|
||||
sum += g;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & cComputeGaussianFlagNormalizeCenterToOne)
|
||||
{
|
||||
sum = pDst[mid_x + mid_y * size_x];
|
||||
}
|
||||
|
||||
if (flags & (cComputeGaussianFlagNormalizeCenterToOne | cComputeGaussianFlagNormalize))
|
||||
{
|
||||
double one_over_sum = 1.0f / sum;
|
||||
for (int i = 0; i < size_x * size_y; i++)
|
||||
pDst[i] = static_cast<float>(pDst[i] * one_over_sum);
|
||||
|
||||
if (flags & cComputeGaussianFlagNormalizeCenterToOne)
|
||||
pDst[mid_x + mid_y * size_x] = 1.0f;
|
||||
}
|
||||
|
||||
if (flags & cComputeGaussianFlagPrint)
|
||||
{
|
||||
printf("{\n");
|
||||
for (int y = 0; y < size_y; y++)
|
||||
{
|
||||
printf(" ");
|
||||
for (int x = 0; x < size_x; x++)
|
||||
{
|
||||
printf("%f, ", pDst[x + y * size_x]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("}");
|
||||
}
|
||||
}
|
||||
|
||||
void gaussian_filter(imagef& dst, const imagef& orig_img, uint32_t odd_filter_width, float sigma_sqr, bool wrapping, uint32_t width_divisor, uint32_t height_divisor)
|
||||
{
|
||||
assert(odd_filter_width && (odd_filter_width & 1));
|
||||
odd_filter_width |= 1;
|
||||
|
||||
std::vector<float> kernel(odd_filter_width * odd_filter_width);
|
||||
compute_gaussian_kernel(&kernel[0], odd_filter_width, odd_filter_width, sigma_sqr, cComputeGaussianFlagNormalize);
|
||||
|
||||
const int dst_width = orig_img.get_width() / width_divisor;
|
||||
const int dst_height = orig_img.get_height() / height_divisor;
|
||||
|
||||
const int H = odd_filter_width / 2;
|
||||
const int L = -H;
|
||||
|
||||
dst.crop(dst_width, dst_height);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int oy = 0; oy < dst_height; oy++)
|
||||
{
|
||||
for (int ox = 0; ox < dst_width; ox++)
|
||||
{
|
||||
vec4F c(0.0f);
|
||||
|
||||
for (int yd = L; yd <= H; yd++)
|
||||
{
|
||||
int y = oy * height_divisor + (height_divisor >> 1) + yd;
|
||||
|
||||
for (int xd = L; xd <= H; xd++)
|
||||
{
|
||||
int x = ox * width_divisor + (width_divisor >> 1) + xd;
|
||||
|
||||
const vec4F& p = orig_img.get_clamped_or_wrapped(x, y, wrapping, wrapping);
|
||||
|
||||
float w = kernel[(xd + H) + (yd + H) * odd_filter_width];
|
||||
c[0] += p[0] * w;
|
||||
c[1] += p[1] * w;
|
||||
c[2] += p[2] * w;
|
||||
c[3] += p[3] * w;
|
||||
}
|
||||
}
|
||||
|
||||
dst(ox, oy).set(c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pow_image(const imagef& src, imagef& dst, const vec4F& power)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& p = src(x, y);
|
||||
|
||||
if ((power[0] == 2.0f) && (power[1] == 2.0f) && (power[2] == 2.0f) && (power[3] == 2.0f))
|
||||
dst(x, y).set(p[0] * p[0], p[1] * p[1], p[2] * p[2], p[3] * p[3]);
|
||||
else
|
||||
dst(x, y).set(powf(p[0], power[0]), powf(p[1], power[1]), powf(p[2], power[2]), powf(p[3], power[3]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void mul_image(const imagef& src, imagef& dst, const vec4F& mul)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& p = src(x, y);
|
||||
dst(x, y).set(p[0] * mul[0], p[1] * mul[1], p[2] * mul[2], p[3] * mul[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void scale_image(const imagef& src, imagef& dst, const vec4F& scale, const vec4F& shift)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& p = src(x, y);
|
||||
|
||||
vec4F d;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
d[c] = scale[c] * p[c] + shift[c];
|
||||
|
||||
dst(x, y).set(d[0], d[1], d[2], d[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void add_weighted_image(const imagef& src1, const vec4F& alpha, const imagef& src2, const vec4F& beta, const vec4F& gamma, imagef& dst)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& s1 = src1(x, y);
|
||||
const vec4F& s2 = src2(x, y);
|
||||
|
||||
dst(x, y).set(
|
||||
s1[0] * alpha[0] + s2[0] * beta[0] + gamma[0],
|
||||
s1[1] * alpha[1] + s2[1] * beta[1] + gamma[1],
|
||||
s1[2] * alpha[2] + s2[2] * beta[2] + gamma[2],
|
||||
s1[3] * alpha[3] + s2[3] * beta[3] + gamma[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void add_image(const imagef& src1, const imagef& src2, imagef& dst)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& s1 = src1(x, y);
|
||||
const vec4F& s2 = src2(x, y);
|
||||
|
||||
dst(x, y).set(s1[0] + s2[0], s1[1] + s2[1], s1[2] + s2[2], s1[3] + s2[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void adds_image(const imagef& src, const vec4F& value, imagef& dst)
|
||||
{
|
||||
dst.resize(src);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& p = src(x, y);
|
||||
|
||||
dst(x, y).set(p[0] + value[0], p[1] + value[1], p[2] + value[2], p[3] + value[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mul_image(const imagef& src1, const imagef& src2, imagef& dst, const vec4F& scale)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& s1 = src1(x, y);
|
||||
const vec4F& s2 = src2(x, y);
|
||||
|
||||
vec4F d;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
float v1 = s1[c];
|
||||
float v2 = s2[c];
|
||||
d[c] = v1 * v2 * scale[c];
|
||||
}
|
||||
|
||||
dst(x, y) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void div_image(const imagef& src1, const imagef& src2, imagef& dst, const vec4F& scale)
|
||||
{
|
||||
dst.resize(src1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
for (int y = 0; y < (int)dst.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < dst.get_width(); x++)
|
||||
{
|
||||
const vec4F& s1 = src1(x, y);
|
||||
const vec4F& s2 = src2(x, y);
|
||||
|
||||
vec4F d;
|
||||
|
||||
for (uint32_t c = 0; c < 4; c++)
|
||||
{
|
||||
float v = s2[c];
|
||||
if (v == 0.0f)
|
||||
d[c] = 0.0f;
|
||||
else
|
||||
d[c] = (s1[c] * scale[c]) / v;
|
||||
}
|
||||
|
||||
dst(x, y) = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vec4F avg_image(const imagef& src)
|
||||
{
|
||||
vec4F avg(0.0f);
|
||||
|
||||
for (uint32_t y = 0; y < src.get_height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < src.get_width(); x++)
|
||||
{
|
||||
const vec4F& s = src(x, y);
|
||||
|
||||
avg += vec4F(s[0], s[1], s[2], s[3]);
|
||||
}
|
||||
}
|
||||
|
||||
avg /= static_cast<float>(src.get_total_pixels());
|
||||
|
||||
return avg;
|
||||
}
|
||||
|
||||
// Reference: https://ece.uwaterloo.ca/~z70wang/research/ssim/index.html
|
||||
vec4F compute_ssim(const imagef& a, const imagef& b)
|
||||
{
|
||||
imagef axb, a_sq, b_sq, mu1, mu2, mu1_sq, mu2_sq, mu1_mu2, s1_sq, s2_sq, s12, smap, t1, t2, t3;
|
||||
|
||||
const float C1 = 6.50250f, C2 = 58.52250f;
|
||||
|
||||
pow_image(a, a_sq, vec4F(2));
|
||||
pow_image(b, b_sq, vec4F(2));
|
||||
mul_image(a, b, axb, vec4F(1.0f));
|
||||
|
||||
gaussian_filter(mu1, a, 11, 1.5f * 1.5f);
|
||||
gaussian_filter(mu2, b, 11, 1.5f * 1.5f);
|
||||
|
||||
pow_image(mu1, mu1_sq, vec4F(2));
|
||||
pow_image(mu2, mu2_sq, vec4F(2));
|
||||
mul_image(mu1, mu2, mu1_mu2, vec4F(1.0f));
|
||||
|
||||
gaussian_filter(s1_sq, a_sq, 11, 1.5f * 1.5f);
|
||||
add_weighted_image(s1_sq, vec4F(1), mu1_sq, vec4F(-1), vec4F(0), s1_sq);
|
||||
|
||||
gaussian_filter(s2_sq, b_sq, 11, 1.5f * 1.5f);
|
||||
add_weighted_image(s2_sq, vec4F(1), mu2_sq, vec4F(-1), vec4F(0), s2_sq);
|
||||
|
||||
gaussian_filter(s12, axb, 11, 1.5f * 1.5f);
|
||||
add_weighted_image(s12, vec4F(1), mu1_mu2, vec4F(-1), vec4F(0), s12);
|
||||
|
||||
scale_image(mu1_mu2, t1, vec4F(2), vec4F(0));
|
||||
adds_image(t1, vec4F(C1), t1);
|
||||
|
||||
scale_image(s12, t2, vec4F(2), vec4F(0));
|
||||
adds_image(t2, vec4F(C2), t2);
|
||||
|
||||
mul_image(t1, t2, t3, vec4F(1));
|
||||
|
||||
add_image(mu1_sq, mu2_sq, t1);
|
||||
adds_image(t1, vec4F(C1), t1);
|
||||
|
||||
add_image(s1_sq, s2_sq, t2);
|
||||
adds_image(t2, vec4F(C2), t2);
|
||||
|
||||
mul_image(t1, t2, t1, vec4F(1));
|
||||
|
||||
div_image(t3, t1, smap, vec4F(1));
|
||||
|
||||
return avg_image(smap);
|
||||
}
|
||||
|
||||
vec4F compute_ssim(const image_u8& a, const image_u8& b, bool luma)
|
||||
{
|
||||
image_u8 ta(a), tb(b);
|
||||
|
||||
if ((ta.width() != tb.width()) || (ta.height() != tb.height()))
|
||||
{
|
||||
fprintf(stderr, "compute_ssim: Cropping input images to equal dimensions\n");
|
||||
|
||||
const uint32_t w = std::min(a.width(), b.width());
|
||||
const uint32_t h = std::min(a.height(), b.height());
|
||||
ta.crop(w, h);
|
||||
tb.crop(w, h);
|
||||
}
|
||||
|
||||
if (!ta.width() || !ta.height())
|
||||
{
|
||||
assert(0);
|
||||
return vec4F(0);
|
||||
}
|
||||
|
||||
if (luma)
|
||||
{
|
||||
for (uint32_t y = 0; y < ta.height(); y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < ta.width(); x++)
|
||||
{
|
||||
ta(x, y).set((uint8_t)ta(x, y).get_luma(), ta(x, y).a);
|
||||
tb(x, y).set((uint8_t)tb(x, y).get_luma(), tb(x, y).a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imagef fta, ftb;
|
||||
|
||||
fta.set(ta);
|
||||
ftb.set(tb);
|
||||
|
||||
return compute_ssim(fta, ftb);
|
||||
}
|
||||
|
||||
bool save_dds(const char* pFilename, uint32_t width, uint32_t height, const void* pBlocks, uint32_t pixel_format_bpp, DXGI_FORMAT dxgi_format, bool srgb, bool force_dx10_header)
|
||||
{
|
||||
(void)srgb;
|
||||
|
||||
FILE* pFile = NULL;
|
||||
#ifdef _MSC_VER
|
||||
fopen_s(&pFile, pFilename, "wb");
|
||||
#else
|
||||
pFile = fopen(pFilename, "wb");
|
||||
#endif
|
||||
if (!pFile)
|
||||
{
|
||||
fprintf(stderr, "Failed creating file %s!\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
fwrite("DDS ", 4, 1, pFile);
|
||||
|
||||
DDSURFACEDESC2 desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||
|
||||
desc.dwWidth = width;
|
||||
desc.dwHeight = height;
|
||||
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
||||
desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
|
||||
|
||||
desc.ddpfPixelFormat.dwFlags |= DDPF_FOURCC;
|
||||
|
||||
desc.lPitch = (((desc.dwWidth + 3) & ~3) * ((desc.dwHeight + 3) & ~3) * pixel_format_bpp) >> 3;
|
||||
desc.dwFlags |= DDSD_LINEARSIZE;
|
||||
|
||||
desc.ddpfPixelFormat.dwRGBBitCount = 0;
|
||||
|
||||
if ((!force_dx10_header) &&
|
||||
((dxgi_format == DXGI_FORMAT_BC1_UNORM) ||
|
||||
(dxgi_format == DXGI_FORMAT_BC3_UNORM) ||
|
||||
(dxgi_format == DXGI_FORMAT_BC4_UNORM) ||
|
||||
(dxgi_format == DXGI_FORMAT_BC5_UNORM)))
|
||||
{
|
||||
if (dxgi_format == DXGI_FORMAT_BC1_UNORM)
|
||||
desc.ddpfPixelFormat.dwFourCC = (uint32_t)PIXEL_FMT_FOURCC('D', 'X', 'T', '1');
|
||||
else if (dxgi_format == DXGI_FORMAT_BC3_UNORM)
|
||||
desc.ddpfPixelFormat.dwFourCC = (uint32_t)PIXEL_FMT_FOURCC('D', 'X', 'T', '5');
|
||||
else if (dxgi_format == DXGI_FORMAT_BC4_UNORM)
|
||||
desc.ddpfPixelFormat.dwFourCC = (uint32_t)PIXEL_FMT_FOURCC('A', 'T', 'I', '1');
|
||||
else if (dxgi_format == DXGI_FORMAT_BC5_UNORM)
|
||||
desc.ddpfPixelFormat.dwFourCC = (uint32_t)PIXEL_FMT_FOURCC('A', 'T', 'I', '2');
|
||||
|
||||
fwrite(&desc, sizeof(desc), 1, pFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ddpfPixelFormat.dwFourCC = (uint32_t)PIXEL_FMT_FOURCC('D', 'X', '1', '0');
|
||||
|
||||
fwrite(&desc, sizeof(desc), 1, pFile);
|
||||
|
||||
DDS_HEADER_DXT10 hdr10;
|
||||
memset(&hdr10, 0, sizeof(hdr10));
|
||||
|
||||
// Not all tools support DXGI_FORMAT_BC7_UNORM_SRGB (like NVTT), but ddsview in DirectXTex pays attention to it. So not sure what to do here.
|
||||
// For best compatibility just write DXGI_FORMAT_BC7_UNORM.
|
||||
//hdr10.dxgiFormat = srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
|
||||
hdr10.dxgiFormat = dxgi_format; // DXGI_FORMAT_BC7_UNORM;
|
||||
hdr10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
hdr10.arraySize = 1;
|
||||
|
||||
fwrite(&hdr10, sizeof(hdr10), 1, pFile);
|
||||
}
|
||||
|
||||
fwrite(pBlocks, desc.lPitch, 1, pFile);
|
||||
|
||||
if (fclose(pFile) == EOF)
|
||||
{
|
||||
fprintf(stderr, "Failed writing to DDS file %s!\n", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void strip_extension(std::string& s)
|
||||
{
|
||||
for (int32_t i = (int32_t)s.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (s[i] == '.')
|
||||
{
|
||||
s.resize(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void strip_path(std::string& s)
|
||||
{
|
||||
for (int32_t i = (int32_t)s.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if ((s[i] == '/') || (s[i] == ':') || (s[i] == '\\'))
|
||||
{
|
||||
s.erase(0, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t hash_hsieh(const uint8_t* pBuf, size_t len)
|
||||
{
|
||||
if (!pBuf || !len)
|
||||
return 0;
|
||||
|
||||
uint32_t h = static_cast<uint32_t>(len);
|
||||
|
||||
const uint32_t bytes_left = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
const uint16_t* pWords = reinterpret_cast<const uint16_t*>(pBuf);
|
||||
|
||||
h += pWords[0];
|
||||
|
||||
const uint32_t t = (pWords[1] << 11) ^ h;
|
||||
h = (h << 16) ^ t;
|
||||
|
||||
pBuf += sizeof(uint32_t);
|
||||
|
||||
h += h >> 11;
|
||||
}
|
||||
|
||||
switch (bytes_left)
|
||||
{
|
||||
case 1:
|
||||
h += *reinterpret_cast<const signed char*>(pBuf);
|
||||
h ^= h << 10;
|
||||
h += h >> 1;
|
||||
break;
|
||||
case 2:
|
||||
h += *reinterpret_cast<const uint16_t*>(pBuf);
|
||||
h ^= h << 11;
|
||||
h += h >> 17;
|
||||
break;
|
||||
case 3:
|
||||
h += *reinterpret_cast<const uint16_t*>(pBuf);
|
||||
h ^= h << 16;
|
||||
h ^= (static_cast<signed char>(pBuf[sizeof(uint16_t)])) << 18;
|
||||
h += h >> 11;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
h ^= h << 3;
|
||||
h += h >> 5;
|
||||
h ^= h << 4;
|
||||
h += h >> 17;
|
||||
h ^= h << 25;
|
||||
h += h >> 6;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
float compute_block_max_std_dev(const color_quad_u8* pPixels, uint32_t block_width, uint32_t block_height, uint32_t num_comps)
|
||||
{
|
||||
tracked_stat comp_stats[4];
|
||||
|
||||
for (uint32_t y = 0; y < block_height; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < block_width; x++)
|
||||
{
|
||||
const color_quad_u8* pPixel = pPixels + x + y * block_width;
|
||||
|
||||
for (uint32_t c = 0; c < num_comps; c++)
|
||||
comp_stats[c].update(pPixel->m_c[c]);
|
||||
}
|
||||
}
|
||||
|
||||
float max_std_dev = 0.0f;
|
||||
for (uint32_t i = 0; i < num_comps; i++)
|
||||
max_std_dev = std::max(max_std_dev, comp_stats[i].get_std_dev());
|
||||
return max_std_dev;
|
||||
}
|
||||
|
||||
const uint32_t ASTC_SIG = 0x5CA1AB13;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct astc_header
|
||||
{
|
||||
uint32_t m_sig;
|
||||
uint8_t m_block_x;
|
||||
uint8_t m_block_y;
|
||||
uint8_t m_block_z;
|
||||
uint8_t m_width[3];
|
||||
uint8_t m_height[3];
|
||||
uint8_t m_depth[3];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool save_astc_file(const char* pFilename, block16_vec& blocks, uint32_t width, uint32_t height, uint32_t block_width, uint32_t block_height)
|
||||
{
|
||||
FILE* pFile = nullptr;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
fopen_s(&pFile, pFilename, "wb");
|
||||
#else
|
||||
pFile = fopen(pFilename, "wb");
|
||||
#endif
|
||||
|
||||
if (!pFile)
|
||||
return false;
|
||||
|
||||
astc_header hdr;
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
hdr.m_sig = ASTC_SIG;
|
||||
hdr.m_block_x = (uint8_t)block_width;
|
||||
hdr.m_block_y = (uint8_t)block_height;
|
||||
hdr.m_block_z = 1;
|
||||
hdr.m_width[0] = (uint8_t)(width);
|
||||
hdr.m_width[1] = (uint8_t)(width >> 8);
|
||||
hdr.m_width[2] = (uint8_t)(width >> 16);
|
||||
hdr.m_height[0] = (uint8_t)(height);
|
||||
hdr.m_height[1] = (uint8_t)(height >> 8);
|
||||
hdr.m_height[2] = (uint8_t)(height >> 16);
|
||||
hdr.m_depth[0] = 1;
|
||||
fwrite(&hdr, sizeof(hdr), 1, pFile);
|
||||
|
||||
fwrite(blocks.data(), 16, blocks.size(), pFile);
|
||||
if (fclose(pFile) == EOF)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_astc_file(const char* pFilename, block16_vec& blocks, uint32_t& width, uint32_t& height, uint32_t& block_width, uint32_t& block_height)
|
||||
{
|
||||
FILE* pFile = nullptr;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
fopen_s(&pFile, pFilename, "rb");
|
||||
#else
|
||||
pFile = fopen(pFilename, "rb");
|
||||
#endif
|
||||
|
||||
if (!pFile)
|
||||
return false;
|
||||
|
||||
astc_header hdr;
|
||||
if (fread(&hdr, sizeof(hdr), 1, pFile) != 1)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hdr.m_sig != ASTC_SIG)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
width = hdr.m_width[0] + (hdr.m_width[1] << 8) + (hdr.m_width[2] << 16);
|
||||
height = hdr.m_height[0] + (hdr.m_height[1] << 8) + (hdr.m_height[2] << 16);
|
||||
uint32_t depth = hdr.m_depth[0] + (hdr.m_depth[1] << 8) + (hdr.m_depth[2] << 16);
|
||||
|
||||
if ((width < 1) || (width > 32768) || (height < 1) || (height > 32768))
|
||||
return false;
|
||||
if ((hdr.m_block_z != 1) || (depth != 1))
|
||||
return false;
|
||||
|
||||
block_width = hdr.m_block_x;
|
||||
block_height = hdr.m_block_y;
|
||||
|
||||
if ((block_width < 4) || (block_width > 12) || (block_height < 4) || (block_height > 12))
|
||||
return false;
|
||||
|
||||
uint32_t blocks_x = (width + block_width - 1) / block_width;
|
||||
uint32_t blocks_y = (height + block_height - 1) / block_height;
|
||||
uint32_t total_blocks = blocks_x * blocks_y;
|
||||
|
||||
blocks.resize(total_blocks);
|
||||
|
||||
if (fread(blocks.data(), 16, total_blocks, pFile) != total_blocks)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint32_t get_deflate_size(const void* pData, size_t data_size)
|
||||
{
|
||||
size_t comp_size = 0;
|
||||
void* pPre_RDO_Comp_data = tdefl_compress_mem_to_heap(pData, data_size, &comp_size, TDEFL_MAX_PROBES_MASK);// TDEFL_DEFAULT_MAX_PROBES);
|
||||
mz_free(pPre_RDO_Comp_data);
|
||||
|
||||
if (comp_size > UINT32_MAX)
|
||||
return UINT32_MAX;
|
||||
|
||||
return (uint32_t)comp_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool read_file(const char* pFilename, uint8_vec& buf)
|
||||
{
|
||||
buf.resize(0);
|
||||
|
||||
FILE* pFile = nullptr;
|
||||
#if _MSC_VER
|
||||
fopen_s(&pFile, pFilename, "rb");
|
||||
#else
|
||||
pFile = fopen(pFilename, "rb");
|
||||
#endif
|
||||
if (!pFile)
|
||||
return false;
|
||||
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
|
||||
long file_end_ofs = ftell(pFile);
|
||||
if (file_end_ofs <= 0)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t sz = static_cast<size_t>(file_end_ofs);
|
||||
if (sz != (unsigned long)file_end_ofs)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
|
||||
buf.resize(sz);
|
||||
|
||||
if (fread(buf.data(), sizeof(uint8_t), sz, pFile) != sz)
|
||||
{
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
2621
example_transcoding/utils.h
Normal file
2621
example_transcoding/utils.h
Normal file
File diff suppressed because it is too large
Load Diff
59
python/README.md
Normal file
59
python/README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
Python support is still new and coming online, but is entirely functional.
|
||||
The library's pure C (WASM friendly) API's are completely exposed to Python.
|
||||
|
||||
The Python integration first tries to use native .so's in the basisu_py
|
||||
directory. If they don't exist, it tries the slower and single threaded WASM
|
||||
fallbacks under basisu_py/wasm, which requires wasmtime for Python to be
|
||||
installed. Some tests require an input.ktx2 or test.ktx2 to be in the current
|
||||
directory.
|
||||
|
||||
Building:
|
||||
|
||||
Under the repo's root directory - build the native SO's:
|
||||
|
||||
```
|
||||
mkdir build_python
|
||||
cd build_python
|
||||
cmake -DBASISU_BUILD_PYTHON=ON ..
|
||||
make
|
||||
```
|
||||
|
||||
Build the WASM modules (see README_WASI.md file for instructions on how to
|
||||
install the WASI SDK, which is required):
|
||||
|
||||
```
|
||||
mkdir build_wasm_st
|
||||
cd build_wasm_st
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake -DCMAKE_BUILD_TYPE=Release -DBASISU_WASM_THREADING=OFF
|
||||
make
|
||||
```
|
||||
|
||||
Running tests:
|
||||
|
||||
The tests assume the current directory is "python". Run them like this:
|
||||
|
||||
Higher-level tests:
|
||||
|
||||
python3 -m tests.test_backend_loading
|
||||
python3 -m tests.test_basic_wasm_selection
|
||||
python3 -m tests.test_basic_backend_selection
|
||||
python3 -m tests.test_basic_decode
|
||||
python3 -m tests.test_basic_transcode
|
||||
python3 -m tests.test_compress_swirl
|
||||
python3 -m tests.test_compress_swirl_hdr
|
||||
python3 -m tests.test_transcoder_astc
|
||||
python3 -m tests.test_transcoder_backend_loading
|
||||
python3 -m tests.test_transcoder_end_to_end
|
||||
python3 -m tests.test_transcoder_end_to_end_hdr
|
||||
python3 -m tests.test_transcoder_helpers
|
||||
|
||||
Low-level tests (used while bringing up the codec):
|
||||
|
||||
python3 -m lowlevel_test_native.basic_test
|
||||
python3 -m lowlevel_test_native.test_transcoder_basic
|
||||
python3 -m lowlevel_test_native.example_capi_python
|
||||
|
||||
python3 -m lowlevel_test_wasm.basic_test
|
||||
python3 -m lowlevel_test_wasm.compress_test
|
||||
python3 -m lowlevel_test_wasm.compress_test_float
|
||||
|
||||
85
python/README_win.md
Normal file
85
python/README_win.md
Normal file
@@ -0,0 +1,85 @@
|
||||
Windows Native Python Build Instructions
|
||||
========================================
|
||||
|
||||
This project uses pybind11 to build Python .pyd extension modules on Windows.
|
||||
Because Windows installs multiple Python versions, and pybind11 currently only
|
||||
supports up to Python 3.12, you must follow these steps exactly.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
- Visual Studio Developer Command Prompt (VS C++ Build Tools installed)
|
||||
- Python 3.12 (pybind11 does NOT support 3.13+ at the time of writing)
|
||||
- pybind11 installed into Python 3.12
|
||||
|
||||
Check installed Python versions:
|
||||
py -0
|
||||
|
||||
If Python 3.12 is missing:
|
||||
winget install Python.Python.3.12
|
||||
|
||||
Install pybind11 for Python 3.12:
|
||||
py -3.12 -m pip install pybind11
|
||||
|
||||
IMPORTANT:
|
||||
You must build AND run with the same Python interpreter version (3.12).
|
||||
|
||||
Building the .pyd Modules
|
||||
-------------------------
|
||||
Open the "Developer Command Prompt for Visual Studio".
|
||||
|
||||
From the project root:
|
||||
|
||||
mkdir build_python_win
|
||||
cd build_python_win
|
||||
|
||||
Run CMake using the exact path to python.exe for Python 3.12:
|
||||
|
||||
cmake -G "Visual Studio 17 2022" -A x64 -DBASISU_BUILD_PYTHON=ON -DBASISU_BUILD_WASM=OFF -DPYTHON_EXECUTABLE="C:\Users\<YOU>\AppData\Local\Programs\Python\Python312\python.exe" ..
|
||||
|
||||
Build:
|
||||
|
||||
cmake --build . --config Release
|
||||
|
||||
Output files will be created in:
|
||||
|
||||
python/basisu_py/basisu_python.pyd
|
||||
python/basisu_py/basisu_transcoder_python.pyd
|
||||
|
||||
Running the Modules
|
||||
-------------------
|
||||
Always run using Python 3.12:
|
||||
|
||||
py -3.12
|
||||
|
||||
Inside Python:
|
||||
|
||||
import basisu_py
|
||||
print("Modules loaded OK.")
|
||||
|
||||
While in the "python" directory:
|
||||
|
||||
py -m tests.test_backend_loading
|
||||
|
||||
WASM Backend (Optional)
|
||||
-----------------------
|
||||
Install wasmtime:
|
||||
|
||||
py -3.12 -m pip install wasmtime
|
||||
|
||||
Ensure these files exist:
|
||||
|
||||
python/basisu_py/wasm/*.wasm
|
||||
|
||||
Common Problems
|
||||
---------------
|
||||
1. "pybind11 not found"
|
||||
-> Installed into wrong Python version. Use:
|
||||
py -3.12 -m pip install pybind11
|
||||
|
||||
2. "Python config failure"
|
||||
-> You are using Python 3.13 or 3.14. Must use Python 3.12.
|
||||
|
||||
3. Modules not loading
|
||||
-> You must run them with the same interpreter used to build them:
|
||||
py -3.12
|
||||
|
||||
83
python/astc_writer.py
Normal file
83
python/astc_writer.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# astc_writer.py
|
||||
#
|
||||
# Minimal ASTC writer that mirrors the C/C++ write_astc_file() logic from example_capi.c.
|
||||
# Writes a valid single-slice 2D ASTC texture file (no array slices, no 3D, no mips).
|
||||
#
|
||||
# Usage:
|
||||
# from astc_writer import write_astc_file
|
||||
# write_astc_file("output.astc", blocks, block_width, block_height, width, height)
|
||||
#
|
||||
# "blocks" must be a bytes-like object containing the full ASTC block data
|
||||
# using 16 bytes per block (standard ASTC block size).
|
||||
|
||||
|
||||
def write_astc_file(
|
||||
filename: str,
|
||||
blocks: bytes,
|
||||
block_width: int,
|
||||
block_height: int,
|
||||
width: int,
|
||||
height: int
|
||||
) -> None:
|
||||
"""
|
||||
Write an ASTC file to disk.
|
||||
|
||||
Parameters:
|
||||
filename : Output filename ("something.astc")
|
||||
blocks : Bytes-like object containing ASTC blocks (16 bytes per block)
|
||||
block_width : ASTC block width (e.g. 4-12)
|
||||
block_height : ASTC block height (e.g. 4-12)
|
||||
width : Original image width in pixels
|
||||
height : Original image height in pixels
|
||||
|
||||
Notes:
|
||||
- ASTC files use 2D blocks; depth is always 1.
|
||||
- Block layout goes row-major: (num_blocks_y num_blocks_x) blocks.
|
||||
- No mipmaps are stored in this format.
|
||||
"""
|
||||
|
||||
# Validate block dimensions
|
||||
if block_width < 4 or block_width > 12:
|
||||
raise ValueError(f"ASTC block_width {block_width} out of range (412)")
|
||||
if block_height < 4 or block_height > 12:
|
||||
raise ValueError(f"ASTC block_height {block_height} out of range (412)")
|
||||
|
||||
# Compute block grid
|
||||
num_blocks_x = (width + block_width - 1) // block_width
|
||||
num_blocks_y = (height + block_height - 1) // block_height
|
||||
total_blocks = num_blocks_x * num_blocks_y
|
||||
expected_size = total_blocks * 16 # 16 bytes per ASTC block (always)
|
||||
|
||||
if len(blocks) != expected_size:
|
||||
raise ValueError(
|
||||
f"ASTC block buffer incorrect size: expected {expected_size}, got {len(blocks)}"
|
||||
)
|
||||
|
||||
# Write file
|
||||
with open(filename, "wb") as f:
|
||||
# ASTC magic number (0x13AB A15C)
|
||||
f.write(bytes([0x13, 0xAB, 0xA1, 0x5C]))
|
||||
|
||||
# Block dims: x, y, z (z=1)
|
||||
f.write(bytes([
|
||||
block_width & 0xFF,
|
||||
block_height & 0xFF,
|
||||
1
|
||||
]))
|
||||
|
||||
# ASTC stores width/height/depth as 24-bit LE
|
||||
def write_24bit_le(v: int):
|
||||
f.write(bytes([
|
||||
v & 0xFF,
|
||||
(v >> 8) & 0xFF,
|
||||
(v >> 16) & 0xFF
|
||||
]))
|
||||
|
||||
write_24bit_le(width)
|
||||
write_24bit_le(height)
|
||||
write_24bit_le(1) # depth
|
||||
|
||||
# Write actual block payload
|
||||
f.write(blocks)
|
||||
|
||||
print(f"[ASTC Writer] Wrote: {filename} ({width}x{height}, {block_width}x{block_height} blocks)")
|
||||
109
python/basisu_encoder_pybind11.cpp
Normal file
109
python/basisu_encoder_pybind11.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
// File: basisu_encoder_pybind11.cpp
|
||||
// pybind11 native bindings for the compressor's pure C API basisu_wasm_api.h
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// include the basisu compression plain C API
|
||||
#include "../encoder/basisu_wasm_api.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
// Convert wasm_bool_t (uint32_t) ? Python bool
|
||||
static inline bool to_bool(uint32_t v) { return v != 0; }
|
||||
|
||||
PYBIND11_MODULE(basisu_python, m) {
|
||||
m.doc() = "Native Basis Universal encoder (pybind11 binding over basisu_wasm_api)";
|
||||
|
||||
//
|
||||
// Initialization / Version
|
||||
//
|
||||
m.def("init", &bu_init, "Initialize the BasisU codec library");
|
||||
m.def("get_version", &bu_get_version, "Return BASISU_LIB_VERSION");
|
||||
|
||||
//
|
||||
// Memory allocation helpers
|
||||
//
|
||||
m.def("alloc", &bu_alloc,
|
||||
"Allocate memory inside native heap and return pointer as uint64");
|
||||
m.def("free", &bu_free,
|
||||
"Free previously allocated pointer");
|
||||
|
||||
//
|
||||
// Compression params handles
|
||||
//
|
||||
m.def("new_params", &bu_new_comp_params,
|
||||
"Create a new comp_params struct inside native heap");
|
||||
m.def("delete_params",
|
||||
[](uint64_t h) { return to_bool(bu_delete_comp_params(h)); },
|
||||
"Destroy a comp_params struct");
|
||||
|
||||
m.def("params_clear",
|
||||
[](uint64_t h) { return to_bool(bu_comp_params_clear(h)); },
|
||||
"Clear comp_params struct");
|
||||
|
||||
//
|
||||
// Image upload API
|
||||
//
|
||||
m.def("set_image_rgba32",
|
||||
[](uint64_t params, uint32_t index,
|
||||
uint64_t img_ptr, uint32_t w, uint32_t h, uint32_t pitch) {
|
||||
return to_bool(bu_comp_params_set_image_rgba32(
|
||||
params, index, img_ptr, w, h, pitch));
|
||||
},
|
||||
"Set 8-bit RGBA32 image into parameters");
|
||||
|
||||
m.def("set_image_float_rgba",
|
||||
[](uint64_t params, uint32_t index,
|
||||
uint64_t img_ptr, uint32_t w, uint32_t h, uint32_t pitch) {
|
||||
return to_bool(bu_comp_params_set_image_float_rgba(
|
||||
params, index, img_ptr, w, h, pitch));
|
||||
},
|
||||
"Set float32 RGBA image into parameters");
|
||||
|
||||
//
|
||||
// Compression
|
||||
//
|
||||
m.def("compress",
|
||||
[](uint64_t params,
|
||||
int tex_format,
|
||||
int quality,
|
||||
int effort,
|
||||
uint64_t flags,
|
||||
float rdo_quality)
|
||||
{
|
||||
return to_bool(bu_compress_texture(
|
||||
params, tex_format, quality, effort, flags, rdo_quality));
|
||||
},
|
||||
py::arg("params"),
|
||||
py::arg("tex_format"),
|
||||
py::arg("quality"),
|
||||
py::arg("effort"),
|
||||
py::arg("flags"),
|
||||
py::arg("rdo_quality") = 0.0f
|
||||
);
|
||||
|
||||
//
|
||||
// Output blob access
|
||||
//
|
||||
m.def("get_comp_data_size",
|
||||
&bu_comp_params_get_comp_data_size,
|
||||
"Return size (bytes) of compressed output");
|
||||
m.def("get_comp_data_ofs",
|
||||
&bu_comp_params_get_comp_data_ofs,
|
||||
"Return pointer (uint64) to compressed output buffer");
|
||||
|
||||
// Memory read/write
|
||||
m.def("read_memory",
|
||||
[](uint64_t ptr, uint32_t size) {
|
||||
return py::bytes((const char*)ptr, size);
|
||||
},
|
||||
"Read `size` bytes starting at native memory address `ptr`");
|
||||
|
||||
m.def("write_memory",
|
||||
[](uint64_t dest_ptr, py::buffer src) {
|
||||
py::buffer_info info = src.request();
|
||||
memcpy((void*)dest_ptr, info.ptr, info.size * info.itemsize);
|
||||
},
|
||||
"Write bytes/buffer-like object into native memory at address `ptr`");
|
||||
}
|
||||
2
python/basisu_py/MANIFEST.in
Normal file
2
python/basisu_py/MANIFEST.in
Normal file
@@ -0,0 +1,2 @@
|
||||
recursive-include basisu_py *.py *.so *.wasm
|
||||
include README.md
|
||||
5
python/basisu_py/READMD.md
Normal file
5
python/basisu_py/READMD.md
Normal file
@@ -0,0 +1,5 @@
|
||||
This is the Python support directory for the Basis Universal KTX2 compressor
|
||||
and transcoder modules.
|
||||
|
||||
License: Apache 2.0
|
||||
|
||||
35
python/basisu_py/__init__.py
Normal file
35
python/basisu_py/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
basisu_py
|
||||
=========
|
||||
Python bindings for the Basis Universal encoder and transcoder, with
|
||||
automatic fallback between native C++ extensions and WASM modules.
|
||||
|
||||
Main entry points:
|
||||
- Transcoder : basisu_py.transcoder.Transcoder
|
||||
- Encoder : basisu_py.codec.Encoder
|
||||
- constants : basisu_py.constants
|
||||
"""
|
||||
|
||||
from .codec import Encoder
|
||||
from .transcoder import Transcoder, KTX2Handle
|
||||
from .constants import (
|
||||
BasisTexFormat,
|
||||
BasisQuality,
|
||||
BasisEffort,
|
||||
BasisFlags,
|
||||
TranscoderTextureFormat,
|
||||
TranscodeDecodeFlags,
|
||||
)
|
||||
|
||||
# What the package publicly exposes
|
||||
__all__ = [
|
||||
"Encoder",
|
||||
"Transcoder",
|
||||
"KTX2Handle",
|
||||
"BasisTexFormat",
|
||||
"BasisQuality",
|
||||
"BasisEffort",
|
||||
"BasisFlags",
|
||||
"TranscoderTextureFormat",
|
||||
"TranscodeDecodeFlags",
|
||||
]
|
||||
BIN
python/basisu_py/basisu_python.cpython-312-x86_64-linux-gnu.so
Normal file
BIN
python/basisu_py/basisu_python.cpython-312-x86_64-linux-gnu.so
Normal file
Binary file not shown.
BIN
python/basisu_py/basisu_python.pyd
Normal file
BIN
python/basisu_py/basisu_python.pyd
Normal file
Binary file not shown.
Binary file not shown.
BIN
python/basisu_py/basisu_transcoder_python.pyd
Normal file
BIN
python/basisu_py/basisu_transcoder_python.pyd
Normal file
Binary file not shown.
222
python/basisu_py/codec.py
Normal file
222
python/basisu_py/codec.py
Normal file
@@ -0,0 +1,222 @@
|
||||
# basisu_py/codec.py
|
||||
|
||||
import importlib
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
import ctypes
|
||||
|
||||
from .constants import BasisTexFormat, BasisQuality, BasisEffort, BasisFlags
|
||||
from pathlib import Path
|
||||
|
||||
class EncoderBackend:
|
||||
NATIVE = "native"
|
||||
WASM = "wasm"
|
||||
AUTO = "auto"
|
||||
|
||||
class Encoder:
|
||||
|
||||
def __init__(self, backend=EncoderBackend.AUTO):
|
||||
self.backend = backend
|
||||
self._native = None
|
||||
self._wasm = None
|
||||
self.backend_name = None
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Try native first (AUTO or NATIVE modes)
|
||||
# ------------------------------------------------------------------
|
||||
if backend in (EncoderBackend.AUTO, EncoderBackend.NATIVE):
|
||||
try:
|
||||
import basisu_py.basisu_python as native_encoder
|
||||
native_encoder.init()
|
||||
|
||||
self._native = native_encoder
|
||||
self._wasm = None
|
||||
self.backend_name = "NATIVE"
|
||||
|
||||
print("[Encoder] Using native backend")
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
if backend == EncoderBackend.NATIVE:
|
||||
raise RuntimeError(
|
||||
f"[Encoder] Native backend requested but unavailable: {e}"
|
||||
)
|
||||
print("[Encoder] Native unavailable; falling back to WASM:", e)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Fallback to WASM (AUTO or explicitly WASM)
|
||||
# ------------------------------------------------------------------
|
||||
try:
|
||||
from basisu_py.wasm.wasm_encoder import BasisuWasmEncoder
|
||||
except Exception as e:
|
||||
raise RuntimeError(
|
||||
f"[Encoder] WASM backend cannot be imported: {e}\n"
|
||||
"Make sure wasmtime is installed and basisu_py/wasm/*.wasm exist."
|
||||
)
|
||||
|
||||
wasm_path = Path(__file__).parent / "wasm" / "basisu_module_st.wasm"
|
||||
self._wasm = BasisuWasmEncoder(str(wasm_path))
|
||||
self._wasm.load()
|
||||
self._native = None
|
||||
self.backend_name = "WASM"
|
||||
|
||||
print("[Encoder] Using WASM backend")
|
||||
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Public API
|
||||
# ------------------------------------------------------
|
||||
def compress(self,
|
||||
image,
|
||||
format=-1,
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT | BasisFlags.SRGB | BasisFlags.THREADED | BasisFlags.XUASTC_LDR_FULL_ZSTD):
|
||||
|
||||
rgba_bytes, w, h, is_hdr = self._convert_input_to_rgba_bytes(image)
|
||||
|
||||
# Auto-select format if user passed -1
|
||||
if format == -1:
|
||||
if is_hdr:
|
||||
format = BasisTexFormat.cUASTC_HDR_6x6
|
||||
else:
|
||||
format = BasisTexFormat.cXUASTC_LDR_6x6
|
||||
|
||||
if self._native:
|
||||
return self._compress_native(rgba_bytes, w, h, format, quality, effort, flags, is_hdr)
|
||||
else:
|
||||
return self._compress_wasm(rgba_bytes, w, h, format, quality, effort, flags, is_hdr)
|
||||
|
||||
def compress_float32(self, arr, **kwargs):
|
||||
if not isinstance(arr, np.ndarray) or arr.dtype != np.float32:
|
||||
raise ValueError("compress_float32 requires float32 NumPy HxWx4 array")
|
||||
|
||||
return self.compress(arr, **kwargs)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Native backend
|
||||
# ------------------------------------------------------
|
||||
def _compress_native(self, bytes_data, w, h, fmt, quality, effort, flags, is_hdr=False):
|
||||
enc = self._native
|
||||
|
||||
params = enc.new_params()
|
||||
|
||||
try:
|
||||
buf_ptr = enc.alloc(len(bytes_data))
|
||||
|
||||
# Write raw bytes (uint8 or float32)
|
||||
ctypes.memmove(buf_ptr, bytes_data, len(bytes_data))
|
||||
|
||||
if is_hdr:
|
||||
ok = enc.set_image_float_rgba(params, 0, buf_ptr, w, h, w * 16) # 4 floats = 16 bytes per pixel
|
||||
else:
|
||||
ok = enc.set_image_rgba32(params, 0, buf_ptr, w, h, w * 4)
|
||||
|
||||
if not ok:
|
||||
raise RuntimeError("Native encoder: set_image failed (HDR or LDR)")
|
||||
|
||||
ok = enc.compress(params, fmt, quality, effort, flags, 0.0)
|
||||
if not ok:
|
||||
raise RuntimeError("Native encoder: compress() failed")
|
||||
|
||||
size = enc.get_comp_data_size(params)
|
||||
ofs = enc.get_comp_data_ofs(params)
|
||||
blob = enc.read_memory(ofs, size)
|
||||
return blob
|
||||
|
||||
finally:
|
||||
enc.delete_params(params)
|
||||
if buf_ptr:
|
||||
enc.free(buf_ptr)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# WASM backend
|
||||
# ------------------------------------------------------
|
||||
def _compress_wasm(self, bytes_data, w, h, fmt, quality, effort, flags, is_hdr=False):
|
||||
enc = self._wasm
|
||||
|
||||
params = enc.new_params()
|
||||
|
||||
try:
|
||||
buf_ptr = enc.alloc(len(bytes_data))
|
||||
enc.write_bytes(buf_ptr, bytes_data)
|
||||
|
||||
if is_hdr:
|
||||
ok = enc.set_image_float_rgba(params, 0, buf_ptr, w, h, w * 16)
|
||||
else:
|
||||
ok = enc.set_image_rgba32(params, 0, buf_ptr, w, h, w * 4)
|
||||
|
||||
if not ok:
|
||||
raise RuntimeError("WASM encoder: set_image failed (HDR or LDR)")
|
||||
|
||||
ok = enc.compress(params, fmt, quality, effort, flags, 0.0)
|
||||
if not ok:
|
||||
raise RuntimeError("WASM encoder: compress() failed")
|
||||
|
||||
size = enc.get_comp_data_size(params)
|
||||
ofs = enc.get_comp_data_ofs(params)
|
||||
blob = enc.read_bytes(ofs, size)
|
||||
return blob
|
||||
|
||||
finally:
|
||||
enc.delete_params(params)
|
||||
if buf_ptr:
|
||||
enc.free(buf_ptr)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Image conversion
|
||||
# ------------------------------------------------------
|
||||
def _convert_input_to_rgba_bytes(self, image):
|
||||
"""
|
||||
Accept:
|
||||
- Pillow Image (LDR) -> returns uint8 bytes
|
||||
- NumPy uint8 LDR -> returns uint8 bytes
|
||||
- NumPy float32 HDR -> returns float32 bytes
|
||||
Returns (bytes, width, height, is_hdr)
|
||||
"""
|
||||
|
||||
# Pillow image -> LDR
|
||||
if isinstance(image, Image.Image):
|
||||
image = image.convert("RGBA")
|
||||
arr = np.array(image, dtype=np.uint8)
|
||||
h, w = arr.shape[:2]
|
||||
return arr.tobytes(), w, h, False
|
||||
|
||||
# NumPy array
|
||||
elif isinstance(image, np.ndarray):
|
||||
|
||||
# HDR float32 image
|
||||
if image.dtype == np.float32:
|
||||
if image.ndim != 3 or image.shape[2] not in (3,4):
|
||||
raise ValueError("HDR NumPy image must be HxWx3 or HxWx4 float32")
|
||||
|
||||
h, w, c = image.shape
|
||||
|
||||
# Expand RGB -> RGBA if needed
|
||||
if c == 3:
|
||||
alpha = np.ones((h, w, 1), dtype=np.float32)
|
||||
arr = np.concatenate([image, alpha], axis=2)
|
||||
else:
|
||||
arr = image
|
||||
|
||||
return arr.tobytes(), w, h, True
|
||||
|
||||
# LDR uint8 image
|
||||
if image.dtype == np.uint8:
|
||||
if image.ndim != 3 or image.shape[2] not in (3,4):
|
||||
raise ValueError("LDR NumPy image must be HxWx3 or HxWx4 uint8")
|
||||
|
||||
h, w, c = image.shape
|
||||
|
||||
if c == 3:
|
||||
alpha = np.full((h, w, 1), 255, dtype=np.uint8)
|
||||
arr = np.concatenate([image, alpha], axis=2)
|
||||
else:
|
||||
arr = image
|
||||
|
||||
return arr.tobytes(), w, h, False
|
||||
|
||||
raise ValueError("NumPy image must be uint8 (LDR) or float32 (HDR)")
|
||||
|
||||
else:
|
||||
raise TypeError("compress() expects Pillow Image or NumPy array")
|
||||
183
python/basisu_py/constants.py
Normal file
183
python/basisu_py/constants.py
Normal file
@@ -0,0 +1,183 @@
|
||||
# basisu_constants.py
|
||||
|
||||
# ============================================================
|
||||
# .KTX2/.basis file types
|
||||
# basist::basis_tex_format
|
||||
# ============================================================
|
||||
class BasisTexFormat:
|
||||
# Original LDR formats
|
||||
cETC1S = 0
|
||||
cUASTC_LDR_4x4 = 1
|
||||
|
||||
# HDR
|
||||
cUASTC_HDR_4x4 = 2
|
||||
cASTC_HDR_6x6 = 3
|
||||
cUASTC_HDR_6x6 = 4
|
||||
|
||||
# XUASTC supercompressed LDR formats
|
||||
cXUASTC_LDR_4x4 = 5
|
||||
cXUASTC_LDR_5x4 = 6
|
||||
cXUASTC_LDR_5x5 = 7
|
||||
cXUASTC_LDR_6x5 = 8
|
||||
cXUASTC_LDR_6x6 = 9
|
||||
cXUASTC_LDR_8x5 = 10
|
||||
cXUASTC_LDR_8x6 = 11
|
||||
cXUASTC_LDR_10x5 = 12
|
||||
cXUASTC_LDR_10x6 = 13
|
||||
cXUASTC_LDR_8x8 = 14
|
||||
cXUASTC_LDR_10x8 = 15
|
||||
cXUASTC_LDR_10x10= 16
|
||||
cXUASTC_LDR_12x10= 17
|
||||
cXUASTC_LDR_12x12= 18
|
||||
|
||||
# Standard ASTC LDR
|
||||
cASTC_LDR_4x4 = 19
|
||||
cASTC_LDR_5x4 = 20
|
||||
cASTC_LDR_5x5 = 21
|
||||
cASTC_LDR_6x5 = 22
|
||||
cASTC_LDR_6x6 = 23
|
||||
cASTC_LDR_8x5 = 24
|
||||
cASTC_LDR_8x6 = 25
|
||||
cASTC_LDR_10x5 = 26
|
||||
cASTC_LDR_10x6 = 27
|
||||
cASTC_LDR_8x8 = 28
|
||||
cASTC_LDR_10x8 = 29
|
||||
cASTC_LDR_10x10= 30
|
||||
cASTC_LDR_12x10= 31
|
||||
cASTC_LDR_12x12= 32
|
||||
|
||||
# ============================================================
|
||||
# Unified quality level: 1-100 (higher=better quality, 100 disables some codec options)
|
||||
# ============================================================
|
||||
class BasisQuality:
|
||||
MIN = 1
|
||||
MAX = 100
|
||||
|
||||
# ============================================================
|
||||
# Unified effort level: 0-10 (0=fastest, 10=very slow, higher=slower but higher potential quality/more features utilized)
|
||||
# ============================================================
|
||||
class BasisEffort:
|
||||
MIN = 0
|
||||
MAX = 10
|
||||
|
||||
SUPER_FAST = 0
|
||||
FAST = 2
|
||||
NORMAL = 5
|
||||
DEFAULT = 2
|
||||
SLOW = 8
|
||||
VERY_SLOW = 10
|
||||
|
||||
# ============================================================
|
||||
# C-style API flags
|
||||
# ============================================================
|
||||
class BasisFlags:
|
||||
NONE = 0
|
||||
USE_OPENCL = 1 << 8
|
||||
THREADED = 1 << 9
|
||||
DEBUG_OUTPUT = 1 << 10
|
||||
|
||||
KTX2_OUTPUT = 1 << 11
|
||||
KTX2_UASTC_ZSTD = 1 << 12
|
||||
|
||||
SRGB = 1 << 13
|
||||
GEN_MIPS_CLAMP = 1 << 14
|
||||
GEN_MIPS_WRAP = 1 << 15
|
||||
|
||||
Y_FLIP = 1 << 16
|
||||
|
||||
PRINT_STATS = 1 << 18
|
||||
PRINT_STATUS = 1 << 19
|
||||
|
||||
DEBUG_IMAGES = 1 << 20
|
||||
|
||||
REC2020 = 1 << 21
|
||||
VALIDATE_OUTPUT = 1 << 22
|
||||
|
||||
XUASTC_LDR_FULL_ARITH = 0
|
||||
XUASTC_LDR_HYBRID = 1 << 23
|
||||
XUASTC_LDR_FULL_ZSTD = 2 << 23
|
||||
XUASTC_LDR_SYNTAX_SHIFT = 23
|
||||
XUASTC_LDR_SYNTAX_MASK = 3
|
||||
|
||||
TEXTURE_TYPE_2D = 0 << 25
|
||||
TEXTURE_TYPE_2D_ARRAY = 1 << 25
|
||||
TEXTURE_TYPE_CUBEMAP_ARRAY = 2 << 25
|
||||
TEXTURE_TYPE_VIDEO_FRAMES = 3 << 25
|
||||
TEXTURE_TYPE_SHIFT = 25
|
||||
TEXTURE_TYPE_MASK = 3
|
||||
|
||||
VERBOSE = PRINT_STATS | PRINT_STATUS
|
||||
MIPMAP_CLAMP = GEN_MIPS_CLAMP
|
||||
MIPMAP_WRAP = GEN_MIPS_WRAP
|
||||
|
||||
# ============================================================
|
||||
# Transcoder Texture Formats (GPU block formats)
|
||||
# basist::transcoder_texture_format
|
||||
# ============================================================
|
||||
class TranscoderTextureFormat:
|
||||
TF_ETC1_RGB = 0
|
||||
TF_ETC2_RGBA = 1
|
||||
TF_BC1_RGB = 2
|
||||
TF_BC3_RGBA = 3
|
||||
TF_BC4_R = 4
|
||||
TF_BC5_RG = 5
|
||||
TF_BC7_RGBA = 6
|
||||
|
||||
TF_PVRTC1_4_RGB = 8
|
||||
TF_PVRTC1_4_RGBA = 9
|
||||
|
||||
TF_ASTC_LDR_4X4_RGBA = 10
|
||||
TF_ATC_RGB = 11
|
||||
TF_ATC_RGBA = 12
|
||||
|
||||
# Uncompressed
|
||||
TF_RGBA32 = 13
|
||||
TF_RGB565 = 14
|
||||
TF_BGR565 = 15
|
||||
TF_RGBA4444 = 16
|
||||
|
||||
TF_FXT1_RGB = 17
|
||||
TF_PVRTC2_4_RGB = 18
|
||||
TF_PVRTC2_4_RGBA = 19
|
||||
|
||||
TF_ETC2_EAC_R11 = 20
|
||||
TF_ETC2_EAC_RG11 = 21
|
||||
TF_BC6H = 22
|
||||
|
||||
TF_ASTC_HDR_4X4_RGBA = 23
|
||||
|
||||
TF_RGB_HALF = 24
|
||||
TF_RGBA_HALF = 25
|
||||
TF_RGB_9E5 = 26
|
||||
TF_ASTC_HDR_6X6_RGBA = 27
|
||||
|
||||
TF_ASTC_LDR_5X4_RGBA = 28
|
||||
TF_ASTC_LDR_5X5_RGBA = 29
|
||||
TF_ASTC_LDR_6X5_RGBA = 30
|
||||
TF_ASTC_LDR_6X6_RGBA = 31
|
||||
TF_ASTC_LDR_8X5_RGBA = 32
|
||||
TF_ASTC_LDR_8X6_RGBA = 33
|
||||
TF_ASTC_LDR_10X5_RGBA = 34
|
||||
TF_ASTC_LDR_10X6_RGBA = 35
|
||||
TF_ASTC_LDR_8X8_RGBA = 36
|
||||
TF_ASTC_LDR_10X8_RGBA = 37
|
||||
TF_ASTC_LDR_10X10_RGBA= 38
|
||||
TF_ASTC_LDR_12X10_RGBA= 39
|
||||
TF_ASTC_LDR_12X12_RGBA= 40
|
||||
|
||||
TOTAL = 41
|
||||
|
||||
# ============================================================
|
||||
# Transcoder Decode Flags
|
||||
# ============================================================
|
||||
class TranscodeDecodeFlags:
|
||||
PVRTC_DECODE_TO_NEXT_POW2 = 2
|
||||
TRANSCODE_ALPHA_TO_OPAQUE = 4
|
||||
BC1_FORBID_THREE_COLOR_BLOCKS = 8
|
||||
OUTPUT_HAS_ALPHA_INDICES = 16
|
||||
HIGH_QUALITY = 32
|
||||
NO_ETC1S_CHROMA_FILTERING = 64
|
||||
NO_DEBLOCK_FILTERING = 128
|
||||
STRONGER_DEBLOCK_FILTERING = 256
|
||||
FORCE_DEBLOCK_FILTERING = 512
|
||||
XUASTC_LDR_DISABLE_FAST_BC7_TRANSCODING = 1024
|
||||
735
python/basisu_py/transcoder.py
Normal file
735
python/basisu_py/transcoder.py
Normal file
@@ -0,0 +1,735 @@
|
||||
# basisu_py/transcoder.py
|
||||
import numpy as np
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from basisu_py.constants import (
|
||||
TranscoderTextureFormat,
|
||||
)
|
||||
|
||||
import importlib
|
||||
import ctypes
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Enum to select backend
|
||||
# ---------------------------------------------------------------------------
|
||||
class TranscoderBackend:
|
||||
NATIVE = "native"
|
||||
WASM = "wasm"
|
||||
AUTO = "auto"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Wrapper class storing pointer+handle
|
||||
# ---------------------------------------------------------------------------
|
||||
@dataclass
|
||||
class KTX2Handle:
|
||||
ptr: int
|
||||
handle: int
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main Transcoder class
|
||||
# ---------------------------------------------------------------------------
|
||||
class Transcoder:
|
||||
def __init__(self, backend=TranscoderBackend.AUTO):
|
||||
self._native = None
|
||||
self._wasm = None
|
||||
self.backend_name = None
|
||||
self.backend = None
|
||||
|
||||
use_native = False
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Try native backend first if AUTO or NATIVE
|
||||
# ------------------------------------------------------------------
|
||||
if backend in (TranscoderBackend.AUTO, TranscoderBackend.NATIVE):
|
||||
try:
|
||||
native_mod = importlib.import_module("basisu_py.basisu_transcoder_python")
|
||||
native_mod.init()
|
||||
self._native = native_mod
|
||||
self.backend = native_mod
|
||||
self.backend_name = "NATIVE"
|
||||
use_native = True
|
||||
print("[Transcoder] Using native backend")
|
||||
except Exception as e:
|
||||
if backend == TranscoderBackend.NATIVE:
|
||||
# Caller explicitly requested native - fail hard
|
||||
raise RuntimeError(f"Native transcoder backend failed: {e}")
|
||||
print("[Transcoder] Native backend unavailable, reason:", e)
|
||||
self._native = None
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Fallback to WASM if native is not being used
|
||||
# ------------------------------------------------------------------
|
||||
if not use_native:
|
||||
try:
|
||||
from basisu_py.wasm.wasm_transcoder import BasisuWasmTranscoder
|
||||
except Exception as e:
|
||||
raise RuntimeError(
|
||||
f"WASM backend cannot be imported: {e}\n"
|
||||
"Ensure that:\n"
|
||||
" - 'wasmtime' is installed\n"
|
||||
" - basisu_py/wasm/*.wasm files are present in the install\n"
|
||||
)
|
||||
|
||||
wasm_path = Path(__file__).parent / "wasm" / "basisu_transcoder_module_st.wasm"
|
||||
self._wasm = BasisuWasmTranscoder(str(wasm_path))
|
||||
self._wasm.load()
|
||||
self.backend = self._wasm
|
||||
self.backend_name = "WASM"
|
||||
print("[Transcoder] Using WASM backend")
|
||||
|
||||
# Finally, bind the unified API to whichever backend we chose
|
||||
self._bind_backend(self.backend)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Unified backend binding (native or wasm)
|
||||
# -----------------------------------------------------------------------
|
||||
def _bind_backend(self, b):
|
||||
self.backend = b
|
||||
|
||||
# ------------------ memory operations ------------------
|
||||
memory_mapping = [
|
||||
("_alloc", "alloc"),
|
||||
("_free", "free"),
|
||||
("_write", "write_memory"),
|
||||
("_read", "read_memory"),
|
||||
]
|
||||
|
||||
# ------------------ KTX2 core ------------------
|
||||
basis_mapping = [
|
||||
# basis_tex_format helpers
|
||||
("basis_tex_format_is_xuastc_ldr", "basis_tex_format_is_xuastc_ldr"),
|
||||
("basis_tex_format_is_astc_ldr", "basis_tex_format_is_astc_ldr"),
|
||||
("basis_tex_format_get_block_width", "basis_tex_format_get_block_width"),
|
||||
("basis_tex_format_get_block_height", "basis_tex_format_get_block_height"),
|
||||
("basis_tex_format_is_hdr", "basis_tex_format_is_hdr"),
|
||||
("basis_tex_format_is_ldr", "basis_tex_format_is_ldr"),
|
||||
|
||||
# transcoder_texture_format helpers
|
||||
("basis_get_bytes_per_block_or_pixel", "basis_get_bytes_per_block_or_pixel"),
|
||||
("basis_transcoder_format_has_alpha", "basis_transcoder_format_has_alpha"),
|
||||
("basis_transcoder_format_is_hdr", "basis_transcoder_format_is_hdr"),
|
||||
("basis_transcoder_format_is_ldr", "basis_transcoder_format_is_ldr"),
|
||||
("basis_transcoder_texture_format_is_astc", "basis_transcoder_texture_format_is_astc"),
|
||||
("basis_transcoder_format_is_uncompressed", "basis_transcoder_format_is_uncompressed"),
|
||||
("basis_get_uncompressed_bytes_per_pixel", "basis_get_uncompressed_bytes_per_pixel"),
|
||||
("basis_get_block_width", "basis_get_block_width"),
|
||||
("basis_get_block_height", "basis_get_block_height"),
|
||||
("basis_get_transcoder_texture_format_from_basis_tex_format","basis_get_transcoder_texture_format_from_basis_tex_format"),
|
||||
("basis_is_format_supported", "basis_is_format_supported"),
|
||||
("basis_compute_transcoded_image_size_in_bytes","basis_compute_transcoded_image_size_in_bytes"),
|
||||
]
|
||||
|
||||
ktx2_mapping = [
|
||||
|
||||
("ktx2_open", "ktx2_open"),
|
||||
("ktx2_close", "ktx2_close"),
|
||||
|
||||
("ktx2_get_width", "ktx2_get_width"),
|
||||
("ktx2_get_height", "ktx2_get_height"),
|
||||
("ktx2_get_levels", "ktx2_get_levels"),
|
||||
("ktx2_get_faces", "ktx2_get_faces"),
|
||||
("ktx2_get_layers", "ktx2_get_layers"),
|
||||
|
||||
("ktx2_get_basis_tex_format", "ktx2_get_basis_tex_format"),
|
||||
|
||||
("ktx2_get_block_width", "ktx2_get_block_width"),
|
||||
("ktx2_get_block_height", "ktx2_get_block_height"),
|
||||
|
||||
("ktx2_has_alpha", "ktx2_has_alpha"),
|
||||
|
||||
# flags
|
||||
("ktx2_is_hdr", "ktx2_is_hdr"),
|
||||
("ktx2_is_hdr_4x4", "ktx2_is_hdr_4x4"),
|
||||
("ktx2_is_hdr_6x6", "ktx2_is_hdr_6x6"),
|
||||
("ktx2_is_ldr", "ktx2_is_ldr"),
|
||||
("ktx2_is_srgb", "ktx2_is_srgb"),
|
||||
("ktx2_is_etc1s", "ktx2_is_etc1s"),
|
||||
("ktx2_is_uastc_ldr_4x4", "ktx2_is_uastc_ldr_4x4"),
|
||||
("ktx2_is_xuastc_ldr", "ktx2_is_xuastc_ldr"),
|
||||
("ktx2_is_astc_ldr", "ktx2_is_astc_ldr"),
|
||||
("ktx2_is_video", "ktx2_is_video"),
|
||||
("ktx2_get_ldr_hdr_upconversion_nit_multiplier", "ktx2_get_ldr_hdr_upconversion_nit_multiplier"),
|
||||
|
||||
# DFD access
|
||||
("ktx2_get_dfd_flags", "ktx2_get_dfd_flags"),
|
||||
("ktx2_get_dfd_total_samples", "ktx2_get_dfd_total_samples"),
|
||||
("ktx2_get_dfd_channel_id0", "ktx2_get_dfd_channel_id0"),
|
||||
("ktx2_get_dfd_channel_id1", "ktx2_get_dfd_channel_id1"),
|
||||
("ktx2_get_dfd_color_model", "ktx2_get_dfd_color_model"),
|
||||
("ktx2_get_dfd_color_primaries", "ktx2_get_dfd_color_primaries"),
|
||||
("ktx2_get_dfd_transfer_func", "ktx2_get_dfd_transfer_func"),
|
||||
|
||||
# per-level info
|
||||
("ktx2_get_level_orig_width", "ktx2_get_level_orig_width"),
|
||||
("ktx2_get_level_orig_height", "ktx2_get_level_orig_height"),
|
||||
("ktx2_get_level_actual_width", "ktx2_get_level_actual_width"),
|
||||
("ktx2_get_level_actual_height", "ktx2_get_level_actual_height"),
|
||||
|
||||
("ktx2_get_level_num_blocks_x", "ktx2_get_level_num_blocks_x"),
|
||||
("ktx2_get_level_num_blocks_y", "ktx2_get_level_num_blocks_y"),
|
||||
("ktx2_get_level_total_blocks", "ktx2_get_level_total_blocks"),
|
||||
|
||||
("ktx2_get_level_alpha_flag", "ktx2_get_level_alpha_flag"),
|
||||
("ktx2_get_level_iframe_flag", "ktx2_get_level_iframe_flag"),
|
||||
|
||||
# transcoding
|
||||
("ktx2_start_transcoding", "ktx2_start_transcoding"),
|
||||
("ktx2_transcode_image_level", "ktx2_transcode_image_level"),
|
||||
|
||||
# version
|
||||
("get_version_fn", "get_version"),
|
||||
]
|
||||
|
||||
# Apply all mappings
|
||||
for public_name, backend_name in (memory_mapping + ktx2_mapping + basis_mapping):
|
||||
setattr(self, public_name, getattr(b, backend_name))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Public version query
|
||||
# -----------------------------------------------------------------------
|
||||
def get_version(self):
|
||||
return self.get_version_fn()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Enable library debug printing to stdout (also set BASISU_FORCE_DEVEL_MESSAGES to 1 in transcoder/basisu.h)
|
||||
# -----------------------------------------------------------------------
|
||||
def enable_debug_printf(self, flag: bool = True):
|
||||
return self.backend.enable_debug_printf(flag)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# KTX2 Handle API: open/close + all queries
|
||||
# -----------------------------------------------------------------------
|
||||
def open(self, ktx2_bytes: bytes) -> KTX2Handle:
|
||||
ptr = self._alloc(len(ktx2_bytes))
|
||||
self._write(ptr, ktx2_bytes)
|
||||
handle = self.ktx2_open(ptr, len(ktx2_bytes))
|
||||
return KTX2Handle(ptr, handle)
|
||||
|
||||
def close(self, ktx2_handle: KTX2Handle):
|
||||
self.ktx2_close(ktx2_handle.handle)
|
||||
self._free(ktx2_handle.ptr)
|
||||
|
||||
# ---- Basic queries ----
|
||||
def get_width(self, ktx2_handle: KTX2Handle):
|
||||
return self.ktx2_get_width(ktx2_handle.handle)
|
||||
|
||||
def get_height(self, ktx2_handle: KTX2Handle):
|
||||
return self.ktx2_get_height(ktx2_handle.handle)
|
||||
|
||||
def get_levels(self, ktx2_handle: KTX2Handle):
|
||||
return self.ktx2_get_levels(ktx2_handle.handle)
|
||||
|
||||
def get_faces(self, ktx2_handle: KTX2Handle):
|
||||
return self.ktx2_get_faces(ktx2_handle.handle)
|
||||
|
||||
def get_layers(self, ktx2_handle: KTX2Handle):
|
||||
return self.ktx2_get_layers(ktx2_handle.handle)
|
||||
|
||||
def get_basis_tex_format(self, ktx2_handle: KTX2Handle):
|
||||
return self.ktx2_get_basis_tex_format(ktx2_handle.handle)
|
||||
|
||||
def has_alpha(self, ktx2_handle: KTX2Handle) -> bool:
|
||||
"""
|
||||
Return true if the KTX2 container has alpha.
|
||||
"""
|
||||
return bool(self.ktx2_has_alpha(ktx2_handle.handle))
|
||||
|
||||
# ---- Format flags ----
|
||||
def is_hdr(self, ktx2_handle): return bool(self.ktx2_is_hdr(ktx2_handle.handle))
|
||||
def is_hdr_4x4(self, ktx2_handle): return bool(self.ktx2_is_hdr_4x4(ktx2_handle.handle))
|
||||
def is_hdr_6x6(self, ktx2_handle): return bool(self.ktx2_is_hdr_6x6(ktx2_handle.handle))
|
||||
def is_ldr(self, ktx2_handle): return bool(self.ktx2_is_ldr(ktx2_handle.handle))
|
||||
def is_srgb(self, ktx2_handle): return bool(self.ktx2_is_srgb(ktx2_handle.handle))
|
||||
def is_video(self, ktx2_handle): return bool(self.ktx2_is_video(ktx2_handle.handle))
|
||||
def get_ldr_hdr_upconversion_nit_multiplier(self, ktx2_handle): return self.ktx2_get_ldr_hdr_upconversion_nit_multiplier(ktx2_handle.handle)
|
||||
def is_etc1s(self, ktx2_handle): return bool(self.ktx2_is_etc1s(ktx2_handle.handle))
|
||||
def is_uastc_ldr_4x4(self, ktx2_handle): return bool(self.ktx2_is_uastc_ldr_4x4(ktx2_handle.handle))
|
||||
def is_xuastc_ldr(self, ktx2_handle): return bool(self.ktx2_is_xuastc_ldr(ktx2_handle.handle))
|
||||
def is_astc_ldr(self, ktx2_handle): return bool(self.ktx2_is_astc_ldr(ktx2_handle.handle))
|
||||
|
||||
# ---- DFD access
|
||||
def get_dfd_flags(self, ktx2_handle): return self.ktx2_get_dfd_flags(ktx2_handle.handle)
|
||||
def get_dfd_total_samples(self, ktx2_handle): return self.ktx2_get_dfd_total_samples(ktx2_handle.handle)
|
||||
def get_dfd_color_model(self, ktx2_handle): return self.ktx2_get_dfd_color_model(ktx2_handle.handle)
|
||||
def get_dfd_color_primaries(self, ktx2_handle): return self.ktx2_get_dfd_color_primaries(ktx2_handle.handle)
|
||||
def get_dfd_transfer_func(self, ktx2_handle): return self.ktx2_get_dfd_transfer_func(ktx2_handle.handle)
|
||||
def get_dfd_channel_id0(self, ktx2_handle): return self.ktx2_get_dfd_channel_id0(ktx2_handle.handle)
|
||||
def get_dfd_channel_id1(self, ktx2_handle): return self.ktx2_get_dfd_channel_id1(ktx2_handle.handle)
|
||||
|
||||
# ---- Block dimensions ----
|
||||
def get_block_width(self, ktx2_handle): return self.ktx2_get_block_width(ktx2_handle.handle)
|
||||
def get_block_height(self, ktx2_handle): return self.ktx2_get_block_height(ktx2_handle.handle)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Explicit: start transcoding on an already-open KTX2 file
|
||||
# -----------------------------------------------------------------------
|
||||
def start_transcoding(self, ktx2_handle: KTX2Handle):
|
||||
"""
|
||||
Must be called before per-level iframe flags become valid.
|
||||
"""
|
||||
ok = self.ktx2_start_transcoding(ktx2_handle.handle)
|
||||
if not ok:
|
||||
raise RuntimeError("start_transcoding() failed")
|
||||
return True
|
||||
|
||||
# ---- Level info ----
|
||||
def get_level_orig_width(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_orig_width(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_orig_height(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_orig_height(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_actual_width(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_actual_width(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_actual_height(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_actual_height(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_num_blocks_x(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_num_blocks_x(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_num_blocks_y(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_num_blocks_y(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_total_blocks(self, ktx2_handle, level, layer=0, face=0):
|
||||
return self.ktx2_get_level_total_blocks(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
def get_level_alpha_flag(self, ktx2_handle, level, layer=0, face=0):
|
||||
return bool(self.ktx2_get_level_alpha_flag(ktx2_handle.handle, level, layer, face))
|
||||
|
||||
def get_level_iframe_flag(self, ktx2_handle, level, layer=0, face=0):
|
||||
return bool(self.ktx2_get_level_iframe_flag(ktx2_handle.handle, level, layer, face))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Low-level: Decode RGBA8 from an already-open KTX2 handle
|
||||
# -----------------------------------------------------------------------
|
||||
def decode_rgba_handle(self, ktx2_handle: KTX2Handle, level=0, layer=0, face=0):
|
||||
"""
|
||||
Low-level fast decode. Requires an already-open KTX2Handle.
|
||||
Returns HxWx4 uint8 NumPy array.
|
||||
"""
|
||||
w = self.ktx2_get_level_orig_width(ktx2_handle.handle, level, layer, face)
|
||||
h = self.ktx2_get_level_orig_height(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
out_size = w * h * 4
|
||||
out_ptr = self._alloc(out_size)
|
||||
|
||||
# MUST start transcoding before ANY decode
|
||||
ok = self.ktx2_start_transcoding(ktx2_handle.handle)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("start_transcoding failed")
|
||||
|
||||
ok = self.ktx2_transcode_image_level(
|
||||
ktx2_handle.handle,
|
||||
level, layer, face,
|
||||
out_ptr,
|
||||
out_size,
|
||||
TranscoderTextureFormat.TF_RGBA32,
|
||||
0, 0, 0, -1, -1, 0
|
||||
)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("transcode_image_level failed")
|
||||
|
||||
raw_bytes = self._read(out_ptr, out_size)
|
||||
self._free(out_ptr)
|
||||
|
||||
arr = np.frombuffer(raw_bytes, dtype=np.uint8)
|
||||
return arr.reshape((h, w, 4))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# High-level: Decode RGBA8 directly from KTX2 file data
|
||||
# -----------------------------------------------------------------------
|
||||
def decode_rgba(self, ktx2_bytes: bytes, level=0, layer=0, face=0):
|
||||
"""
|
||||
High-level convenience decode. Opens the KTX2 file bytes for you.
|
||||
"""
|
||||
ktx2_handle = self.open(ktx2_bytes)
|
||||
try:
|
||||
return self.decode_rgba_handle(ktx2_handle, level, layer, face)
|
||||
finally:
|
||||
self.close(ktx2_handle)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Low-level: Decode HDR (RGBA float32) from open KTX2
|
||||
# -----------------------------------------------------------------------
|
||||
def decode_rgba_hdr_handle(self, ktx2_handle: KTX2Handle, level=0, layer=0, face=0):
|
||||
"""
|
||||
Low-level HDR decode. Returns HxWx4 float32 NumPy array.
|
||||
"""
|
||||
w = self.ktx2_get_level_orig_width(ktx2_handle.handle, level, layer, face)
|
||||
h = self.ktx2_get_level_orig_height(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
bytes_per_pixel = 8 # 4 * half-float
|
||||
out_size = w * h * bytes_per_pixel
|
||||
out_ptr = self._alloc(out_size)
|
||||
|
||||
ok = self.ktx2_start_transcoding(ktx2_handle.handle)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("start_transcoding failed")
|
||||
|
||||
ok = self.ktx2_transcode_image_level(
|
||||
ktx2_handle.handle,
|
||||
level, layer, face,
|
||||
out_ptr,
|
||||
out_size,
|
||||
TranscoderTextureFormat.TF_RGBA_HALF,
|
||||
0, 0, 0, -1, -1, 0
|
||||
)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("transcode_image_level failed")
|
||||
|
||||
raw_bytes = self._read(out_ptr, out_size)
|
||||
self._free(out_ptr)
|
||||
|
||||
arr = np.frombuffer(raw_bytes, dtype=np.float16).astype(np.float32)
|
||||
return arr.reshape((h, w, 4))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# High-level: Decode HDR (RGBA float32) from KTX2 file data
|
||||
# -----------------------------------------------------------------------
|
||||
def decode_rgba_hdr(self, ktx2_bytes: bytes, level=0, layer=0, face=0):
|
||||
"""
|
||||
High-level convenience HDR decode. Opens the KTX2 file bytes for you.
|
||||
"""
|
||||
ktx2_handle = self.open(ktx2_bytes)
|
||||
try:
|
||||
return self.decode_rgba_hdr_handle(ktx2_handle, level, layer, face)
|
||||
finally:
|
||||
self.close(ktx2_handle)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Low-level: General-purpose transcode using a chosen TranscoderTextureFormat format
|
||||
# -----------------------------------------------------------------------
|
||||
def transcode_tfmt_handle(self, ktx2_handle: KTX2Handle, tfmt: int,
|
||||
level=0, layer=0, face=0, decode_flags=0,
|
||||
channel0=-1, channel1=-1):
|
||||
"""
|
||||
Low-level direct transcoding from an already-open KTX2 handle.
|
||||
|
||||
Parameters:
|
||||
ktx2_handle: KTX2Handle -> already-open KTX2
|
||||
tfmt: int -> TranscoderTextureFormat to transcode to (for ASTC: block size and LDR/HDR MUST match the KTX2 file, for HDR: must be a HDR texture format)
|
||||
level/layer/face: int -> which image slice to decode
|
||||
decode_flags: int -> basist::decode_flags
|
||||
row_pitch, rows_in_pixels, channel0, channel1 -> advanced options
|
||||
|
||||
Returns: bytes (transcoded GPU texture data or uncompressed image)
|
||||
"""
|
||||
|
||||
# Determine actual output size in bytes
|
||||
ow = self.ktx2_get_level_orig_width(ktx2_handle.handle, level, layer, face)
|
||||
oh = self.ktx2_get_level_orig_height(ktx2_handle.handle, level, layer, face)
|
||||
|
||||
out_size = self.basis_compute_transcoded_image_size_in_bytes(tfmt, ow, oh)
|
||||
if out_size == 0:
|
||||
raise RuntimeError("basis_compute_transcoded_image_size_in_bytes returned 0")
|
||||
|
||||
# print(f"*** ow={ow}, oh={oh}, out_size={out_size}")
|
||||
|
||||
out_ptr = self._alloc(out_size)
|
||||
|
||||
# Call transcoder
|
||||
ok = self.ktx2_start_transcoding(ktx2_handle.handle)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("start_transcoding failed")
|
||||
|
||||
ok = self.ktx2_transcode_image_level(
|
||||
ktx2_handle.handle,
|
||||
level, layer, face,
|
||||
out_ptr,
|
||||
out_size,
|
||||
tfmt,
|
||||
decode_flags,
|
||||
0,
|
||||
0,
|
||||
channel0, channel1,
|
||||
0 # no per-thread state object
|
||||
)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("ktx2_transcode_image_level failed")
|
||||
|
||||
# Extract bytes
|
||||
raw_bytes = self._read(out_ptr, out_size)
|
||||
|
||||
self._free(out_ptr)
|
||||
return raw_bytes
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# High-level: General-purpose transcode (opens the KTX2 for you)
|
||||
# tfmt: the TranscoderTextureFormat to transcode too
|
||||
# -----------------------------------------------------------------------
|
||||
def transcode_tfmt(self, ktx2_bytes: bytes, tfmt: int,
|
||||
level=0, layer=0, face=0, decode_flags=0,
|
||||
channel0=-1, channel1=-1):
|
||||
"""
|
||||
High-level convenience wrapper for transcode_tfmt_handle().
|
||||
Automatically opens/closes the KTX2 file.
|
||||
"""
|
||||
ktx2_handle = self.open(ktx2_bytes)
|
||||
try:
|
||||
return self.transcode_tfmt_handle(
|
||||
ktx2_handle, tfmt,
|
||||
level=level,
|
||||
layer=layer,
|
||||
face=face,
|
||||
decode_flags=decode_flags,
|
||||
channel0=channel0,
|
||||
channel1=channel1
|
||||
)
|
||||
finally:
|
||||
self.close(ktx2_handle)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Low-level: choose a specific transcoder_texture_format from a family string
|
||||
# -----------------------------------------------------------------------
|
||||
def choose_transcoder_format(self, ktx2_handle: KTX2Handle, family: str) -> int:
|
||||
"""
|
||||
Given an already-opened KTX2 and a desired family string, choose a concrete
|
||||
TranscoderTextureFormat enum.
|
||||
|
||||
family: one of:
|
||||
"ASTC", "BC1", "BC3", "BC4", "BC5", "BC6H", "BC7",
|
||||
"PVRTC1", "PVRTC2",
|
||||
"ETC1", "ETC2", "ETC2_EAC_R11", "ETC2_EAC_RG11",
|
||||
"ATC", "FXT1",
|
||||
"RGBA32", "RGB_HALF", "RGBA_HALF", "RGB_FLOAT", "RGBA_FLOAT",
|
||||
"RGB_9E5"
|
||||
|
||||
Returns:
|
||||
int: TranscoderTextureFormat value
|
||||
"""
|
||||
|
||||
s = family.strip().upper().replace(" ", "")
|
||||
hdr_tex = self.is_hdr(ktx2_handle)
|
||||
has_alpha = self.has_alpha(ktx2_handle)
|
||||
basis_fmt = self.get_basis_tex_format(ktx2_handle)
|
||||
|
||||
tfmt = None
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Uncompressed families
|
||||
# -------------------------------------------------------------------
|
||||
if s in ("RGBA32", "RGBA8", "UNCOMPRESSED"):
|
||||
tfmt = TranscoderTextureFormat.TF_RGBA32
|
||||
|
||||
elif s in ("RGBHALF", "RGB16F", "RGB_FLOAT", "RGBFLOAT"):
|
||||
tfmt = TranscoderTextureFormat.TF_RGB_HALF
|
||||
|
||||
elif s in ("RGBAHALF", "RGBA16F", "RGBA_FLOAT", "RGBAFLOAT"):
|
||||
tfmt = TranscoderTextureFormat.TF_RGBA_HALF
|
||||
|
||||
elif s in ("RGB9E5", "RGB_9E5"):
|
||||
tfmt = TranscoderTextureFormat.TF_RGB_9E5
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# BC families
|
||||
# -------------------------------------------------------------------
|
||||
elif s == "BC1":
|
||||
tfmt = TranscoderTextureFormat.TF_BC1_RGB
|
||||
elif s == "BC3":
|
||||
tfmt = TranscoderTextureFormat.TF_BC3_RGBA
|
||||
elif s == "BC4":
|
||||
tfmt = TranscoderTextureFormat.TF_BC4_R
|
||||
elif s == "BC5":
|
||||
tfmt = TranscoderTextureFormat.TF_BC5_RG
|
||||
elif s == "BC6H":
|
||||
tfmt = TranscoderTextureFormat.TF_BC6H
|
||||
elif s == "BC7":
|
||||
tfmt = TranscoderTextureFormat.TF_BC7_RGBA
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# PVRTC families
|
||||
# -------------------------------------------------------------------
|
||||
elif s == "PVRTC1":
|
||||
tfmt = (TranscoderTextureFormat.TF_PVRTC1_4_RGBA
|
||||
if has_alpha else TranscoderTextureFormat.TF_PVRTC1_4_RGB)
|
||||
|
||||
elif s == "PVRTC2":
|
||||
tfmt = (TranscoderTextureFormat.TF_PVRTC2_4_RGBA
|
||||
if has_alpha else TranscoderTextureFormat.TF_PVRTC2_4_RGB)
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# ETC / EAC families
|
||||
# -------------------------------------------------------------------
|
||||
elif s == "ETC1":
|
||||
tfmt = TranscoderTextureFormat.TF_ETC1_RGB
|
||||
|
||||
elif s == "ETC2":
|
||||
tfmt = TranscoderTextureFormat.TF_ETC2_RGBA
|
||||
|
||||
elif s in ("ETC2_EAC_R11", "EAC_R11"):
|
||||
tfmt = TranscoderTextureFormat.TF_ETC2_EAC_R11
|
||||
|
||||
elif s in ("ETC2_EAC_RG11", "EAC_RG11"):
|
||||
tfmt = TranscoderTextureFormat.TF_ETC2_EAC_RG11
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# ATC / FXT
|
||||
# -------------------------------------------------------------------
|
||||
elif s == "ATC":
|
||||
tfmt = (TranscoderTextureFormat.TF_ATC_RGBA
|
||||
if has_alpha else TranscoderTextureFormat.TF_ATC_RGB)
|
||||
|
||||
elif s == "FXT1":
|
||||
tfmt = TranscoderTextureFormat.TF_FXT1_RGB
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# ASTC family
|
||||
# -------------------------------------------------------------------
|
||||
elif s == "ASTC":
|
||||
# Let BasisU decide correct ASTC format (block size + LDR/HDR)
|
||||
tfmt = self.basis_get_transcoder_texture_format_from_basis_tex_format(basis_fmt)
|
||||
|
||||
else:
|
||||
# Unknown family: choose a safe uncompressed default
|
||||
if hdr_tex:
|
||||
tfmt = TranscoderTextureFormat.TF_RGBA_HALF
|
||||
else:
|
||||
tfmt = TranscoderTextureFormat.TF_RGBA32
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Validate HDR/LDR compatibility (optional but recommended)
|
||||
# -------------------------------------------------------------------
|
||||
# Use helpers to ensure we don't do HDR->LDR or LDR->HDR accidentally.
|
||||
is_tfmt_hdr = self.basis_transcoder_format_is_hdr(tfmt)
|
||||
if hdr_tex and not is_tfmt_hdr:
|
||||
raise ValueError(f"Requested {family} (LDR transcoder format) for HDR KTX2.")
|
||||
if not hdr_tex and is_tfmt_hdr:
|
||||
raise ValueError(f"Requested {family} (HDR transcoder format) for LDR KTX2.")
|
||||
|
||||
return tfmt
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Low-level: General-purpose transcode using a family string
|
||||
# from an already opened ktx2 file.
|
||||
# Returns:
|
||||
# (data_bytes, chosen_tfmt, block_width, block_height)
|
||||
# -----------------------------------------------------------------------
|
||||
def transcode_handle(
|
||||
self,
|
||||
ktx2_handle: KTX2Handle,
|
||||
family: str,
|
||||
level=0,
|
||||
layer=0,
|
||||
face=0,
|
||||
decode_flags=0,
|
||||
channel0=-1,
|
||||
channel1=-1
|
||||
):
|
||||
"""
|
||||
Low-level direct transcoding from an already-open KTX2 handle,
|
||||
using a high-level family string such as:
|
||||
"BC7", "BC3", "BC1", "ETC1", "ETC2", "ASTC", "PVRTC1",
|
||||
"RGBA32", "RGB_HALF", "RGBA_HALF", "RGB_9E5", etc.
|
||||
See choose_transcoder_format().
|
||||
Returns:
|
||||
(data_bytes, tfmt, block_width, block_height)
|
||||
"""
|
||||
|
||||
# Decide the exact transcoder format (BC1/BC7/etc.)
|
||||
tfmt = self.choose_transcoder_format(ktx2_handle, family)
|
||||
|
||||
# Get original dims of the requested slice
|
||||
ow = self.get_level_orig_width(ktx2_handle, level, layer, face)
|
||||
oh = self.get_level_orig_height(ktx2_handle, level, layer, face)
|
||||
|
||||
# Compute correct output size for the chosen format
|
||||
out_size = self.basis_compute_transcoded_image_size_in_bytes(tfmt, ow, oh)
|
||||
if out_size == 0:
|
||||
raise RuntimeError(
|
||||
f"Computed output size is 0 for tfmt={tfmt}, dims={ow}x{oh}"
|
||||
)
|
||||
|
||||
# Allocate output buffer
|
||||
out_ptr = self._alloc(out_size)
|
||||
|
||||
# Ensure transcoding tables are ready
|
||||
ok = self.ktx2_start_transcoding(ktx2_handle.handle)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("start_transcoding failed")
|
||||
|
||||
# Perform the transcode
|
||||
ok = self.ktx2_transcode_image_level(
|
||||
ktx2_handle.handle,
|
||||
level, layer, face,
|
||||
out_ptr,
|
||||
out_size,
|
||||
tfmt,
|
||||
decode_flags,
|
||||
0, # row_pitch_in_blocks_or_pixels
|
||||
0, # rows_in_pixels
|
||||
channel0,
|
||||
channel1,
|
||||
0 # no thread-local state
|
||||
)
|
||||
if not ok:
|
||||
self._free(out_ptr)
|
||||
raise RuntimeError("ktx2_transcode_image_level failed")
|
||||
|
||||
# Extract bytes from native/WASM memory
|
||||
data_bytes = self._read(out_ptr, out_size)
|
||||
|
||||
# Free the output buffer
|
||||
self._free(out_ptr)
|
||||
|
||||
# Determine block dims for this texture format
|
||||
if self.basis_transcoder_format_is_uncompressed(tfmt):
|
||||
bw = None
|
||||
bh = None
|
||||
else:
|
||||
bw = self.basis_get_block_width(tfmt)
|
||||
bh = self.basis_get_block_height(tfmt)
|
||||
|
||||
return data_bytes, tfmt, bw, bh
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# High-level: one-shot transcode using a family string
|
||||
# directly from ktx2 file data. (Slower if you're transcoding multiple
|
||||
# levels/faces/layers.)
|
||||
# -----------------------------------------------------------------------
|
||||
def transcode(
|
||||
self,
|
||||
ktx2_bytes: bytes,
|
||||
family: str,
|
||||
level=0,
|
||||
layer=0,
|
||||
face=0,
|
||||
decode_flags=0,
|
||||
channel0=-1,
|
||||
channel1=-1
|
||||
):
|
||||
"""
|
||||
High-level version of transcode_handle().
|
||||
Calls transcode_handle() internally.
|
||||
|
||||
Returns:
|
||||
(data_bytes, tfmt, block_width, block_height)
|
||||
"""
|
||||
ktx2_handle = self.open(ktx2_bytes)
|
||||
try:
|
||||
return self.transcode_handle(
|
||||
ktx2_handle,
|
||||
family,
|
||||
level=level,
|
||||
layer=layer,
|
||||
face=face,
|
||||
decode_flags=decode_flags,
|
||||
channel0=channel0,
|
||||
channel1=channel1
|
||||
)
|
||||
finally:
|
||||
self.close(ktx2_handle)
|
||||
|
||||
def tfmt_name(self, tfmt: int):
|
||||
return TranscoderTextureFormat(tfmt).name
|
||||
1
python/basisu_py/wasm/__init__.py
Normal file
1
python/basisu_py/wasm/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Purposely empty
|
||||
BIN
python/basisu_py/wasm/basisu_module_mt.wasm
Normal file
BIN
python/basisu_py/wasm/basisu_module_mt.wasm
Normal file
Binary file not shown.
BIN
python/basisu_py/wasm/basisu_module_st.wasm
Normal file
BIN
python/basisu_py/wasm/basisu_module_st.wasm
Normal file
Binary file not shown.
BIN
python/basisu_py/wasm/basisu_transcoder_module_mt.wasm
Normal file
BIN
python/basisu_py/wasm/basisu_transcoder_module_mt.wasm
Normal file
Binary file not shown.
BIN
python/basisu_py/wasm/basisu_transcoder_module_st.wasm
Normal file
BIN
python/basisu_py/wasm/basisu_transcoder_module_st.wasm
Normal file
Binary file not shown.
126
python/basisu_py/wasm/wasm_encoder.py
Normal file
126
python/basisu_py/wasm/wasm_encoder.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# basisu_py/wasm/wasm_encoder.py
|
||||
|
||||
import wasmtime
|
||||
import ctypes
|
||||
|
||||
from ..constants import BasisTexFormat, BasisQuality, BasisEffort, BasisFlags
|
||||
|
||||
|
||||
class BasisuWasmEncoder:
|
||||
def __init__(self, wasm_path):
|
||||
self.wasm_path = wasm_path
|
||||
self.engine = None
|
||||
self.store = None
|
||||
self.memory = None
|
||||
self.exports = None
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Initialize WASM + WASI
|
||||
# ------------------------------------------------------
|
||||
def _init_engine(self):
|
||||
self.engine = wasmtime.Engine()
|
||||
self.store = wasmtime.Store(self.engine)
|
||||
|
||||
wasi = wasmtime.WasiConfig()
|
||||
wasi.argv = ["basisu-wasm"]
|
||||
wasi.inherit_stdout()
|
||||
wasi.inherit_stderr()
|
||||
self.store.set_wasi(wasi)
|
||||
|
||||
def load(self):
|
||||
self._init_engine()
|
||||
|
||||
module = wasmtime.Module.from_file(self.engine, self.wasm_path)
|
||||
linker = wasmtime.Linker(self.engine)
|
||||
linker.define_wasi()
|
||||
|
||||
instance = linker.instantiate(self.store, module)
|
||||
self.exports = instance.exports(self.store)
|
||||
self.memory = self.exports["memory"]
|
||||
|
||||
# Initialize if present
|
||||
if "bu_init" in self.exports:
|
||||
self.exports["bu_init"](self.store)
|
||||
|
||||
print("[WASM Encoder] Loaded:", self.wasm_path)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Access raw linear memory buffer
|
||||
# ------------------------------------------------------
|
||||
def _buf(self):
|
||||
raw_ptr = self.memory.data_ptr(self.store)
|
||||
size = self.memory.data_len(self.store)
|
||||
addr = ctypes.addressof(raw_ptr.contents)
|
||||
return (ctypes.c_ubyte * size).from_address(addr)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Version
|
||||
# ------------------------------------------------------
|
||||
def get_version(self):
|
||||
return self.exports["bu_get_version"](self.store)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Memory alloc/free
|
||||
# ------------------------------------------------------
|
||||
def alloc(self, size):
|
||||
return self.exports["bu_alloc"](self.store, size)
|
||||
|
||||
def free(self, ptr):
|
||||
self.exports["bu_free"](self.store, ptr)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Params
|
||||
# ------------------------------------------------------
|
||||
def new_params(self):
|
||||
return self.exports["bu_new_comp_params"](self.store)
|
||||
|
||||
def delete_params(self, params):
|
||||
return self.exports["bu_delete_comp_params"](self.store, params)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Image input
|
||||
# ------------------------------------------------------
|
||||
def set_image_rgba32(self, params, index, ptr, w, h, pitch):
|
||||
return self.exports["bu_comp_params_set_image_rgba32"](
|
||||
self.store, params, index, ptr, w, h, pitch
|
||||
)
|
||||
|
||||
def set_image_float_rgba(self, params, index, ptr, w, h, pitch):
|
||||
return self.exports["bu_comp_params_set_image_float_rgba"](
|
||||
self.store, params, index, ptr, w, h, pitch
|
||||
)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Compression
|
||||
# ------------------------------------------------------
|
||||
def compress(self, params, fmt, quality, effort, flags, rdo):
|
||||
return bool(self.exports["bu_compress_texture"](
|
||||
self.store, params, fmt, quality, effort, flags, rdo
|
||||
))
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Output blob
|
||||
# ------------------------------------------------------
|
||||
def get_comp_data_size(self, params):
|
||||
return self.exports["bu_comp_params_get_comp_data_size"](self.store, params)
|
||||
|
||||
def get_comp_data_ofs(self, params):
|
||||
return self.exports["bu_comp_params_get_comp_data_ofs"](self.store, params)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Raw memory I/O
|
||||
# ------------------------------------------------------
|
||||
def write_bytes(self, ptr, data):
|
||||
buf = self._buf()
|
||||
buf[ptr:ptr + len(data)] = data
|
||||
|
||||
def read_bytes(self, ptr, size):
|
||||
buf = self._buf()
|
||||
return bytes(buf[ptr:ptr + size])
|
||||
|
||||
# NEW unified names:
|
||||
def write_memory(self, ptr, data):
|
||||
self.write_bytes(ptr, data)
|
||||
|
||||
def read_memory(self, ptr, size):
|
||||
return self.read_bytes(ptr, size)
|
||||
326
python/basisu_py/wasm/wasm_transcoder.py
Normal file
326
python/basisu_py/wasm/wasm_transcoder.py
Normal file
@@ -0,0 +1,326 @@
|
||||
# basisu_py/wasm/wasm_transcoder.py
|
||||
|
||||
import wasmtime
|
||||
import ctypes
|
||||
|
||||
|
||||
class BasisuWasmTranscoder:
|
||||
"""
|
||||
Lowest-level WASM transcoder wrapper.
|
||||
Direct mapping to basisu_wasm_transcoder_api.h/.cpp
|
||||
|
||||
NOTE:
|
||||
- This layer does NOT interpret formats or block sizes.
|
||||
- It only wraps the raw C API (bt_* and basis_* exports).
|
||||
- Higher-level logic (TranscoderCore, Transcoder) will build on top.
|
||||
"""
|
||||
|
||||
def __init__(self, wasm_path: str):
|
||||
self.wasm_path = wasm_path
|
||||
self.engine = None
|
||||
self.store = None
|
||||
self.memory = None
|
||||
self.exports = None
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Internal: initialize WASM + WASI
|
||||
# ------------------------------------------------------
|
||||
def _init_engine(self):
|
||||
self.engine = wasmtime.Engine()
|
||||
self.store = wasmtime.Store(self.engine)
|
||||
|
||||
wasi = wasmtime.WasiConfig()
|
||||
wasi.argv = ["basisu-transcoder"]
|
||||
wasi.inherit_stdout()
|
||||
wasi.inherit_stderr()
|
||||
self.store.set_wasi(wasi)
|
||||
|
||||
def load(self):
|
||||
self._init_engine()
|
||||
|
||||
module = wasmtime.Module.from_file(self.engine, self.wasm_path)
|
||||
linker = wasmtime.Linker(self.engine)
|
||||
linker.define_wasi()
|
||||
|
||||
instance = linker.instantiate(self.store, module)
|
||||
self.exports = instance.exports(self.store)
|
||||
self.memory = self.exports["memory"]
|
||||
|
||||
# Mandatory transcoder init
|
||||
if "bt_init" in self.exports:
|
||||
self.exports["bt_init"](self.store)
|
||||
|
||||
print("[WASM Transcoder] Loaded:", self.wasm_path)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Linear memory access helpers
|
||||
# ------------------------------------------------------
|
||||
def _buf(self):
|
||||
raw_ptr = self.memory.data_ptr(self.store)
|
||||
size = self.memory.data_len(self.store)
|
||||
addr = ctypes.addressof(raw_ptr.contents)
|
||||
return (ctypes.c_ubyte * size).from_address(addr)
|
||||
|
||||
def write_bytes(self, ptr: int, data: bytes):
|
||||
buf = self._buf()
|
||||
buf[ptr:ptr + len(data)] = data
|
||||
|
||||
def read_bytes(self, ptr: int, num: int) -> bytes:
|
||||
buf = self._buf()
|
||||
return bytes(buf[ptr:ptr + num])
|
||||
|
||||
# NEW unified names:
|
||||
def write_memory(self, ptr, data):
|
||||
self.write_bytes(ptr, data)
|
||||
|
||||
def read_memory(self, ptr, size):
|
||||
return self.read_bytes(ptr, size)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Memory alloc/free
|
||||
# ------------------------------------------------------
|
||||
def alloc(self, size: int) -> int:
|
||||
return self.exports["bt_alloc"](self.store, size)
|
||||
|
||||
def free(self, ptr: int):
|
||||
return self.exports["bt_free"](self.store, ptr)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# High-level functions: version, init, debug
|
||||
# ------------------------------------------------------
|
||||
def get_version(self) -> int:
|
||||
return self.exports["bt_get_version"](self.store)
|
||||
|
||||
def enable_debug_printf(self, flag: bool = True):
|
||||
return self.exports["bt_enable_debug_printf"](self.store, 1 if flag else 0)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# basis_tex_format helpers
|
||||
# ------------------------------------------------------
|
||||
def basis_tex_format_is_xuastc_ldr(self, basis_tex_fmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_tex_format_is_xuastc_ldr"](self.store, basis_tex_fmt_u32))
|
||||
|
||||
def basis_tex_format_is_astc_ldr(self, basis_tex_fmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_tex_format_is_astc_ldr"](self.store, basis_tex_fmt_u32))
|
||||
|
||||
def basis_tex_format_get_block_width(self, basis_tex_fmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_tex_format_get_block_width"](self.store, basis_tex_fmt_u32)
|
||||
|
||||
def basis_tex_format_get_block_height(self, basis_tex_fmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_tex_format_get_block_height"](self.store, basis_tex_fmt_u32)
|
||||
|
||||
def basis_tex_format_is_hdr(self, basis_tex_fmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_tex_format_is_hdr"](self.store, basis_tex_fmt_u32))
|
||||
|
||||
def basis_tex_format_is_ldr(self, basis_tex_fmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_tex_format_is_ldr"](self.store, basis_tex_fmt_u32))
|
||||
|
||||
# ------------------------------------------------------
|
||||
# transcoder_texture_format helpers
|
||||
# ------------------------------------------------------
|
||||
def basis_get_bytes_per_block_or_pixel(self, tfmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_get_bytes_per_block_or_pixel"](self.store, tfmt_u32)
|
||||
|
||||
def basis_transcoder_format_has_alpha(self, tfmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_transcoder_format_has_alpha"](self.store, tfmt_u32))
|
||||
|
||||
def basis_transcoder_format_is_hdr(self, tfmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_transcoder_format_is_hdr"](self.store, tfmt_u32))
|
||||
|
||||
def basis_transcoder_format_is_ldr(self, tfmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_transcoder_format_is_ldr"](self.store, tfmt_u32))
|
||||
|
||||
def basis_transcoder_texture_format_is_astc(self, tfmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_transcoder_texture_format_is_astc"](self.store, tfmt_u32))
|
||||
|
||||
def basis_transcoder_format_is_uncompressed(self, tfmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_transcoder_format_is_uncompressed"](self.store, tfmt_u32))
|
||||
|
||||
def basis_get_uncompressed_bytes_per_pixel(self, tfmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_get_uncompressed_bytes_per_pixel"](self.store, tfmt_u32)
|
||||
|
||||
def basis_get_block_width(self, tfmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_get_block_width"](self.store, tfmt_u32)
|
||||
|
||||
def basis_get_block_height(self, tfmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_get_block_height"](self.store, tfmt_u32)
|
||||
|
||||
def basis_get_transcoder_texture_format_from_basis_tex_format(self, basis_tex_fmt_u32: int) -> int:
|
||||
return self.exports["bt_basis_get_transcoder_texture_format_from_basis_tex_format"](self.store, basis_tex_fmt_u32)
|
||||
|
||||
def basis_is_format_supported(self, tfmt_u32: int, basis_tex_fmt_u32: int) -> bool:
|
||||
return bool(self.exports["bt_basis_is_format_supported"](self.store, tfmt_u32, basis_tex_fmt_u32))
|
||||
|
||||
def basis_compute_transcoded_image_size_in_bytes(self, tfmt_u32: int, orig_width: int, orig_height: int) -> int:
|
||||
return self.exports["bt_basis_compute_transcoded_image_size_in_bytes"](
|
||||
self.store, tfmt_u32, orig_width, orig_height
|
||||
)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# KTX2 handle management
|
||||
# ------------------------------------------------------
|
||||
def ktx2_open(self, data_ptr: int, data_len: int) -> int:
|
||||
return self.exports["bt_ktx2_open"](self.store, data_ptr, data_len)
|
||||
|
||||
def ktx2_close(self, handle: int):
|
||||
return self.exports["bt_ktx2_close"](self.store, handle)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Basic KTX2 metadata
|
||||
# ------------------------------------------------------
|
||||
def ktx2_get_width(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_width"](self.store, handle)
|
||||
|
||||
def ktx2_get_height(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_height"](self.store, handle)
|
||||
|
||||
def ktx2_get_levels(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_levels"](self.store, handle)
|
||||
|
||||
def ktx2_get_faces(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_faces"](self.store, handle)
|
||||
|
||||
def ktx2_get_layers(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_layers"](self.store, handle)
|
||||
|
||||
def ktx2_get_basis_tex_format(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_basis_tex_format"](self.store, handle)
|
||||
|
||||
# KTX2 format checks
|
||||
def ktx2_is_etc1s(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_etc1s"](self.store, handle))
|
||||
|
||||
def ktx2_is_uastc_ldr_4x4(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_uastc_ldr_4x4"](self.store, handle))
|
||||
|
||||
def ktx2_is_hdr(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_hdr"](self.store, handle))
|
||||
|
||||
def ktx2_is_hdr_4x4(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_hdr_4x4"](self.store, handle))
|
||||
|
||||
def ktx2_is_hdr_6x6(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_hdr_6x6"](self.store, handle))
|
||||
|
||||
def ktx2_is_ldr(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_ldr"](self.store, handle))
|
||||
|
||||
def ktx2_is_astc_ldr(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_astc_ldr"](self.store, handle))
|
||||
|
||||
def ktx2_is_xuastc_ldr(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_xuastc_ldr"](self.store, handle))
|
||||
|
||||
def ktx2_get_block_width(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_block_width"](self.store, handle)
|
||||
|
||||
def ktx2_get_block_height(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_block_height"](self.store, handle)
|
||||
|
||||
def ktx2_has_alpha(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_has_alpha"](self.store, handle))
|
||||
|
||||
def ktx2_get_dfd_color_model(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_color_model"](self.store, handle)
|
||||
|
||||
def ktx2_get_dfd_color_primaries(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_color_primaries"](self.store, handle)
|
||||
|
||||
def ktx2_get_dfd_transfer_func(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_transfer_func"](self.store, handle)
|
||||
|
||||
def ktx2_is_srgb(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_srgb"](self.store, handle))
|
||||
|
||||
def ktx2_get_dfd_flags(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_flags"](self.store, handle)
|
||||
|
||||
def ktx2_get_dfd_total_samples(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_total_samples"](self.store, handle)
|
||||
|
||||
def ktx2_get_dfd_channel_id0(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_channel_id0"](self.store, handle)
|
||||
|
||||
def ktx2_get_dfd_channel_id1(self, handle: int) -> int:
|
||||
return self.exports["bt_ktx2_get_dfd_channel_id1"](self.store, handle)
|
||||
|
||||
def ktx2_is_video(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_is_video"](self.store, handle))
|
||||
|
||||
def ktx2_get_ldr_hdr_upconversion_nit_multiplier(self, handle: int) -> float:
|
||||
return self.exports["bt_ktx2_get_ldr_hdr_upconversion_nit_multiplier"](self.store, handle)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Per-level metadata
|
||||
# ------------------------------------------------------
|
||||
def ktx2_get_level_orig_width(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_orig_width"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_orig_height(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_orig_height"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_actual_width(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_actual_width"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_actual_height(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_actual_height"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_num_blocks_x(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_num_blocks_x"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_num_blocks_y(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_num_blocks_y"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_total_blocks(self, h, lvl, layer, face) -> int:
|
||||
return self.exports["bt_ktx2_get_level_total_blocks"](self.store, h, lvl, layer, face)
|
||||
|
||||
def ktx2_get_level_alpha_flag(self, h, lvl, layer, face) -> bool:
|
||||
return bool(self.exports["bt_ktx2_get_level_alpha_flag"](self.store, h, lvl, layer, face))
|
||||
|
||||
def ktx2_get_level_iframe_flag(self, h, lvl, layer, face) -> bool:
|
||||
return bool(self.exports["bt_ktx2_get_level_iframe_flag"](self.store, h, lvl, layer, face))
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Transcoding control
|
||||
# ------------------------------------------------------
|
||||
def ktx2_start_transcoding(self, handle: int) -> bool:
|
||||
return bool(self.exports["bt_ktx2_start_transcoding"](self.store, handle))
|
||||
|
||||
def ktx2_create_transcode_state(self) -> int:
|
||||
return self.exports["bt_ktx2_create_transcode_state"](self.store)
|
||||
|
||||
def ktx2_destroy_transcode_state(self, handle: int):
|
||||
return self.exports["bt_ktx2_destroy_transcode_state"](self.store, handle)
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Actual transcoding call
|
||||
# ------------------------------------------------------
|
||||
def ktx2_transcode_image_level(
|
||||
self,
|
||||
ktx2_handle: int,
|
||||
level_index: int,
|
||||
layer_index: int,
|
||||
face_index: int,
|
||||
output_block_mem_ofs: int,
|
||||
output_blocks_buf_size_in_blocks_or_pixels: int,
|
||||
transcoder_texture_format_u32: int,
|
||||
decode_flags: int,
|
||||
output_row_pitch_in_blocks_or_pixels: int,
|
||||
output_rows_in_pixels: int,
|
||||
channel0: int,
|
||||
channel1: int,
|
||||
state_handle: int,
|
||||
) -> bool:
|
||||
return bool(self.exports["bt_ktx2_transcode_image_level"](
|
||||
self.store,
|
||||
ktx2_handle,
|
||||
level_index, layer_index, face_index,
|
||||
output_block_mem_ofs,
|
||||
output_blocks_buf_size_in_blocks_or_pixels,
|
||||
transcoder_texture_format_u32,
|
||||
decode_flags,
|
||||
output_row_pitch_in_blocks_or_pixels,
|
||||
output_rows_in_pixels,
|
||||
channel0, channel1,
|
||||
state_handle
|
||||
))
|
||||
264
python/basisu_transcoder_pybind11.cpp
Normal file
264
python/basisu_transcoder_pybind11.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
// File: basisu_transcoder_pybind11.cpp
|
||||
// pybind11 native bindings for the transcoder's pure C API basisu_wasm_transcoder_api.h
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../encoder/basisu_wasm_transcoder_api.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
// wasm_bool_t is uint32_t — convert to Python bool
|
||||
static inline bool to_bool(wasm_bool_t v) { return v != 0; }
|
||||
|
||||
PYBIND11_MODULE(basisu_transcoder_python, m) {
|
||||
m.doc() = "Native Basis Universal transcoder (pybind11 binding over basisu_wasm_transcoder_api)";
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// High-level functions
|
||||
// ------------------------------------------------------------------------
|
||||
m.def("get_version", &bt_get_version,
|
||||
"Get BasisU transcoder version");
|
||||
|
||||
m.def("enable_debug_printf",
|
||||
[](bool flag) { bt_enable_debug_printf(flag ? 1u : 0u); },
|
||||
"Enable or disable debug printf output");
|
||||
|
||||
m.def("init", &bt_init,
|
||||
"Initialize transcoder library");
|
||||
|
||||
m.def("alloc", &bt_alloc,
|
||||
"Allocate a buffer, returns uint64 offset/pointer");
|
||||
m.def("free", &bt_free,
|
||||
"Free a buffer allocated by bt_alloc");
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// basis_tex_format helpers
|
||||
// ------------------------------------------------------------------------
|
||||
m.def("basis_tex_format_is_xuastc_ldr",
|
||||
[](uint32_t fmt) { return to_bool(bt_basis_tex_format_is_xuastc_ldr(fmt)); });
|
||||
|
||||
m.def("basis_tex_format_is_astc_ldr",
|
||||
[](uint32_t fmt) { return to_bool(bt_basis_tex_format_is_astc_ldr(fmt)); });
|
||||
|
||||
m.def("basis_tex_format_get_block_width",
|
||||
&bt_basis_tex_format_get_block_width);
|
||||
|
||||
m.def("basis_tex_format_get_block_height",
|
||||
&bt_basis_tex_format_get_block_height);
|
||||
|
||||
m.def("basis_tex_format_is_hdr",
|
||||
[](uint32_t fmt) { return to_bool(bt_basis_tex_format_is_hdr(fmt)); });
|
||||
|
||||
m.def("basis_tex_format_is_ldr",
|
||||
[](uint32_t fmt) { return to_bool(bt_basis_tex_format_is_ldr(fmt)); });
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// transcoder_texture_format helpers
|
||||
// ------------------------------------------------------------------------
|
||||
m.def("basis_get_bytes_per_block_or_pixel",
|
||||
&bt_basis_get_bytes_per_block_or_pixel);
|
||||
|
||||
m.def("basis_transcoder_format_has_alpha",
|
||||
[](uint32_t tfmt) { return to_bool(bt_basis_transcoder_format_has_alpha(tfmt)); });
|
||||
|
||||
m.def("basis_transcoder_format_is_hdr",
|
||||
[](uint32_t tfmt) { return to_bool(bt_basis_transcoder_format_is_hdr(tfmt)); });
|
||||
|
||||
m.def("basis_transcoder_format_is_ldr",
|
||||
[](uint32_t tfmt) { return to_bool(bt_basis_transcoder_format_is_ldr(tfmt)); });
|
||||
|
||||
m.def("basis_transcoder_texture_format_is_astc",
|
||||
[](uint32_t tfmt) { return to_bool(bt_basis_transcoder_texture_format_is_astc(tfmt)); });
|
||||
|
||||
m.def("basis_transcoder_format_is_uncompressed",
|
||||
[](uint32_t tfmt) { return to_bool(bt_basis_transcoder_format_is_uncompressed(tfmt)); });
|
||||
|
||||
m.def("basis_get_uncompressed_bytes_per_pixel",
|
||||
&bt_basis_get_uncompressed_bytes_per_pixel);
|
||||
|
||||
m.def("basis_get_block_width",
|
||||
&bt_basis_get_block_width);
|
||||
|
||||
m.def("basis_get_block_height",
|
||||
&bt_basis_get_block_height);
|
||||
|
||||
m.def("basis_get_transcoder_texture_format_from_basis_tex_format",
|
||||
&bt_basis_get_transcoder_texture_format_from_basis_tex_format);
|
||||
|
||||
m.def("basis_is_format_supported",
|
||||
[](uint32_t tfmt, uint32_t basis_fmt) {
|
||||
return to_bool(bt_basis_is_format_supported(tfmt, basis_fmt));
|
||||
});
|
||||
|
||||
m.def("basis_compute_transcoded_image_size_in_bytes",
|
||||
&bt_basis_compute_transcoded_image_size_in_bytes);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// KTX2 open/close & basic info
|
||||
// ------------------------------------------------------------------------
|
||||
m.def("ktx2_open", &bt_ktx2_open,
|
||||
"Open a KTX2 image from memory; returns handle");
|
||||
|
||||
m.def("ktx2_close", &bt_ktx2_close,
|
||||
"Close a previously opened KTX2 handle");
|
||||
|
||||
m.def("ktx2_get_width", &bt_ktx2_get_width);
|
||||
m.def("ktx2_get_height", &bt_ktx2_get_height);
|
||||
m.def("ktx2_get_levels", &bt_ktx2_get_levels);
|
||||
m.def("ktx2_get_faces", &bt_ktx2_get_faces);
|
||||
m.def("ktx2_get_layers", &bt_ktx2_get_layers);
|
||||
|
||||
m.def("ktx2_get_basis_tex_format", &bt_ktx2_get_basis_tex_format);
|
||||
|
||||
m.def("ktx2_is_etc1s",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_etc1s(h)); });
|
||||
|
||||
m.def("ktx2_is_uastc_ldr_4x4",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_uastc_ldr_4x4(h)); });
|
||||
|
||||
m.def("ktx2_is_hdr",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_hdr(h)); });
|
||||
|
||||
m.def("ktx2_is_hdr_4x4",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_hdr_4x4(h)); });
|
||||
|
||||
m.def("ktx2_is_hdr_6x6",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_hdr_6x6(h)); });
|
||||
|
||||
m.def("ktx2_is_ldr",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_ldr(h)); });
|
||||
|
||||
m.def("ktx2_is_astc_ldr",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_astc_ldr(h)); });
|
||||
|
||||
m.def("ktx2_is_xuastc_ldr",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_xuastc_ldr(h)); });
|
||||
|
||||
m.def("ktx2_get_block_width", &bt_ktx2_get_block_width);
|
||||
|
||||
m.def("ktx2_get_block_height", &bt_ktx2_get_block_height);
|
||||
|
||||
m.def("ktx2_has_alpha",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_has_alpha(h)); });
|
||||
|
||||
m.def("ktx2_get_dfd_color_model", &bt_ktx2_get_dfd_color_model);
|
||||
m.def("ktx2_get_dfd_color_primaries", &bt_ktx2_get_dfd_color_primaries);
|
||||
m.def("ktx2_get_dfd_transfer_func", &bt_ktx2_get_dfd_transfer_func);
|
||||
|
||||
m.def("ktx2_is_srgb",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_srgb(h)); });
|
||||
|
||||
m.def("ktx2_get_dfd_flags", &bt_ktx2_get_dfd_flags);
|
||||
m.def("ktx2_get_dfd_total_samples", &bt_ktx2_get_dfd_total_samples);
|
||||
m.def("ktx2_get_dfd_channel_id0", &bt_ktx2_get_dfd_channel_id0);
|
||||
m.def("ktx2_get_dfd_channel_id1", &bt_ktx2_get_dfd_channel_id1);
|
||||
|
||||
m.def("ktx2_is_video",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_is_video(h)); });
|
||||
|
||||
m.def("ktx2_get_ldr_hdr_upconversion_nit_multiplier",
|
||||
&bt_ktx2_get_ldr_hdr_upconversion_nit_multiplier);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// KTX2 per-level info
|
||||
// ------------------------------------------------------------------------
|
||||
m.def("ktx2_get_level_orig_width",
|
||||
&bt_ktx2_get_level_orig_width);
|
||||
|
||||
m.def("ktx2_get_level_orig_height",
|
||||
&bt_ktx2_get_level_orig_height);
|
||||
|
||||
m.def("ktx2_get_level_actual_width",
|
||||
&bt_ktx2_get_level_actual_width);
|
||||
|
||||
m.def("ktx2_get_level_actual_height",
|
||||
&bt_ktx2_get_level_actual_height);
|
||||
|
||||
m.def("ktx2_get_level_num_blocks_x",
|
||||
&bt_ktx2_get_level_num_blocks_x);
|
||||
|
||||
m.def("ktx2_get_level_num_blocks_y",
|
||||
&bt_ktx2_get_level_num_blocks_y);
|
||||
|
||||
m.def("ktx2_get_level_total_blocks",
|
||||
&bt_ktx2_get_level_total_blocks);
|
||||
|
||||
m.def("ktx2_get_level_alpha_flag",
|
||||
[](uint64_t h, uint32_t level, uint32_t layer, uint32_t face) {
|
||||
return to_bool(bt_ktx2_get_level_alpha_flag(h, level, layer, face));
|
||||
});
|
||||
|
||||
m.def("ktx2_get_level_iframe_flag",
|
||||
[](uint64_t h, uint32_t level, uint32_t layer, uint32_t face) {
|
||||
return to_bool(bt_ktx2_get_level_iframe_flag(h, level, layer, face));
|
||||
});
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Transcoding state and operations
|
||||
// ------------------------------------------------------------------------
|
||||
m.def("ktx2_start_transcoding",
|
||||
[](uint64_t h) { return to_bool(bt_ktx2_start_transcoding(h)); });
|
||||
|
||||
m.def("ktx2_create_transcode_state",
|
||||
&bt_ktx2_create_transcode_state);
|
||||
|
||||
m.def("ktx2_destroy_transcode_state",
|
||||
&bt_ktx2_destroy_transcode_state);
|
||||
|
||||
m.def("ktx2_transcode_image_level",
|
||||
[](uint64_t ktx2_handle,
|
||||
uint32_t level_index, uint32_t layer_index, uint32_t face_index,
|
||||
uint64_t out_mem_ofs,
|
||||
uint32_t out_blocks_or_pixels,
|
||||
uint32_t transcoder_texture_format_u32,
|
||||
uint32_t decode_flags,
|
||||
uint32_t row_pitch_blocks_or_pixels,
|
||||
uint32_t rows_in_pixels,
|
||||
int channel0, int channel1,
|
||||
uint64_t state_handle)
|
||||
{
|
||||
return to_bool(bt_ktx2_transcode_image_level(
|
||||
ktx2_handle,
|
||||
level_index, layer_index, face_index,
|
||||
out_mem_ofs,
|
||||
out_blocks_or_pixels,
|
||||
transcoder_texture_format_u32,
|
||||
decode_flags,
|
||||
row_pitch_blocks_or_pixels,
|
||||
rows_in_pixels,
|
||||
channel0, channel1,
|
||||
state_handle));
|
||||
},
|
||||
py::arg("ktx2_handle"),
|
||||
py::arg("level_index"),
|
||||
py::arg("layer_index"),
|
||||
py::arg("face_index"),
|
||||
py::arg("output_block_mem_ofs"),
|
||||
py::arg("output_blocks_buf_size_in_blocks_or_pixels"),
|
||||
py::arg("transcoder_texture_format_u32"),
|
||||
py::arg("decode_flags"),
|
||||
py::arg("output_row_pitch_in_blocks_or_pixels") = 0,
|
||||
py::arg("output_rows_in_pixels") = 0,
|
||||
py::arg("channel0") = -1,
|
||||
py::arg("channel1") = -1,
|
||||
py::arg("state_handle") = 0);
|
||||
|
||||
m.def("read_memory",
|
||||
[](uint64_t ptr, uint32_t size) {
|
||||
return py::bytes((const char*)ptr, size);
|
||||
},
|
||||
"Read `size` bytes starting at native memory address `ptr`");
|
||||
|
||||
m.def("write_memory",
|
||||
[](uint64_t dest_ptr, py::buffer src) {
|
||||
py::buffer_info info = src.request();
|
||||
memcpy((void*)dest_ptr, info.ptr, info.size * info.itemsize);
|
||||
},
|
||||
"Write bytes/buffer-like object into native memory at address `ptr`");
|
||||
}
|
||||
332
python/dds_writer.py
Normal file
332
python/dds_writer.py
Normal file
@@ -0,0 +1,332 @@
|
||||
# dds_writer.py
|
||||
#
|
||||
# Minimal DDS writer that mirrors the C/C++ save_dds() implementation you provided.
|
||||
# It writes a DX9-style DDS header, and optionally a DX10 extension header,
|
||||
# followed by the raw compressed blocks.
|
||||
#
|
||||
# No mipmaps, no cubes, no 3D volumes – exactly like the original C code.
|
||||
|
||||
import struct
|
||||
import sys
|
||||
from typing import Union
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FourCC helper (same as PIXEL_FMT_FOURCC macro)
|
||||
# ---------------------------------------------------------------------------
|
||||
def make_fourcc(a: str, b: str, c: str, d: str) -> int:
|
||||
return (ord(a) |
|
||||
(ord(b) << 8) |
|
||||
(ord(c) << 16) |
|
||||
(ord(d) << 24))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# DDS-related constants (only the ones we actually use)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# DDSD flags
|
||||
DDSD_CAPS = 0x00000001
|
||||
DDSD_HEIGHT = 0x00000002
|
||||
DDSD_WIDTH = 0x00000004
|
||||
DDSD_PIXELFORMAT= 0x00001000
|
||||
DDSD_LINEARSIZE = 0x00080000
|
||||
|
||||
# DDPF flags
|
||||
DDPF_FOURCC = 0x00000004
|
||||
|
||||
# DDSCAPS flags
|
||||
DDSCAPS_TEXTURE = 0x00001000
|
||||
|
||||
# DXGI_FORMAT subset (values must match the C enum)
|
||||
class DXGI_FORMAT:
|
||||
UNKNOWN = 0
|
||||
BC1_UNORM = 71
|
||||
BC3_UNORM = 77
|
||||
BC4_UNORM = 80
|
||||
BC5_UNORM = 83
|
||||
# You can add more as needed; for DX10 header we just write the integer value.
|
||||
|
||||
# DX10 resource dimension
|
||||
class D3D10_RESOURCE_DIMENSION:
|
||||
UNKNOWN = 0
|
||||
BUFFER = 1
|
||||
TEXTURE1D = 2
|
||||
TEXTURE2D = 3
|
||||
TEXTURE3D = 4
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# DDS writer class
|
||||
# ---------------------------------------------------------------------------
|
||||
class DDSWriter:
|
||||
"""
|
||||
Python port of the C save_dds() function.
|
||||
|
||||
Usage:
|
||||
writer = DDSWriter()
|
||||
ok = writer.save_dds(
|
||||
filename="out.dds",
|
||||
width=width,
|
||||
height=height,
|
||||
blocks=bc_data, # bytes or bytearray
|
||||
pixel_format_bpp=4, # e.g. 4 for BC1, 8 for BC3/4/5/etc.
|
||||
dxgi_format=DXGI_FORMAT.BC1_UNORM,
|
||||
srgb=False,
|
||||
force_dx10_header=False,
|
||||
)
|
||||
"""
|
||||
|
||||
DDS_MAGIC = b"DDS " # same as fwrite("DDS ", 4, 1, pFile);
|
||||
|
||||
def save_dds(
|
||||
self,
|
||||
filename: str,
|
||||
width: int,
|
||||
height: int,
|
||||
blocks: Union[bytes, bytearray, memoryview],
|
||||
pixel_format_bpp: int,
|
||||
dxgi_format: int,
|
||||
srgb: bool = False,
|
||||
force_dx10_header: bool = False,
|
||||
) -> bool:
|
||||
"""
|
||||
Port of:
|
||||
bool save_dds(const char* pFilename,
|
||||
uint32_t width, uint32_t height,
|
||||
const void* pBlocks,
|
||||
uint32_t pixel_format_bpp,
|
||||
DXGI_FORMAT dxgi_format,
|
||||
bool srgb,
|
||||
bool force_dx10_header);
|
||||
|
||||
The 'blocks' buffer is written as-is (up to computed linear size).
|
||||
"""
|
||||
|
||||
# srgb is intentionally unused in the original C code (commented logic).
|
||||
_ = srgb
|
||||
|
||||
# Open file like the C code
|
||||
try:
|
||||
f = open(filename, "wb")
|
||||
except OSError:
|
||||
print(f"Failed creating file {filename}!", file=sys.stderr)
|
||||
return False
|
||||
|
||||
try:
|
||||
# Write the "DDS " magic
|
||||
f.write(self.DDS_MAGIC)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Build DDSURFACEDESC2 equivalent
|
||||
# -----------------------------------------------------------------
|
||||
# We'll pack DDSURFACEDESC2 as 31 uint32's (124 bytes) in little-endian:
|
||||
# struct DDSURFACEDESC2 {
|
||||
# uint32 dwSize;
|
||||
# uint32 dwFlags;
|
||||
# uint32 dwHeight;
|
||||
# uint32 dwWidth;
|
||||
# uint32 lPitch_or_dwLinearSize;
|
||||
# uint32 dwBackBufferCount;
|
||||
# uint32 dwMipMapCount;
|
||||
# uint32 dwAlphaBitDepth;
|
||||
# uint32 dwUnused0;
|
||||
# uint32 lpSurface;
|
||||
# DDCOLORKEY unused0; (2 * uint32)
|
||||
# DDCOLORKEY unused1; (2 * uint32)
|
||||
# DDCOLORKEY unused2; (2 * uint32)
|
||||
# DDCOLORKEY unused3; (2 * uint32)
|
||||
# DDPIXELFORMAT ddpfPixelFormat; (8 * uint32)
|
||||
# DDSCAPS2 ddsCaps; (4 * uint32)
|
||||
# uint32 dwUnused1;
|
||||
# };
|
||||
|
||||
dwSize = 124 # sizeof(DDSURFACEDESC2)
|
||||
|
||||
dwFlags = (
|
||||
DDSD_WIDTH |
|
||||
DDSD_HEIGHT |
|
||||
DDSD_PIXELFORMAT |
|
||||
DDSD_CAPS
|
||||
)
|
||||
|
||||
dwWidth = int(width)
|
||||
dwHeight = int(height)
|
||||
|
||||
# lPitch (actually LinearSize for compressed formats), same as:
|
||||
# (((dwWidth + 3) & ~3) * ((dwHeight + 3) & ~3) * pixel_format_bpp) >> 3;
|
||||
lPitch = (
|
||||
((dwWidth + 3) & ~3)
|
||||
* ((dwHeight + 3) & ~3)
|
||||
* int(pixel_format_bpp)
|
||||
) >> 3
|
||||
|
||||
dwFlags |= DDSD_LINEARSIZE
|
||||
|
||||
dwBackBufferCount = 0
|
||||
dwMipMapCount = 0
|
||||
dwAlphaBitDepth = 0
|
||||
dwUnused0 = 0
|
||||
lpSurface = 0
|
||||
|
||||
# DDCOLORKEY unused0..3, all zero
|
||||
ddcolorkey_zero = [0, 0] * 4 # 4 DDCOLORKEY structs
|
||||
|
||||
# DDPIXELFORMAT
|
||||
# struct DDPIXELFORMAT {
|
||||
# uint32 dwSize;
|
||||
# uint32 dwFlags;
|
||||
# uint32 dwFourCC;
|
||||
# uint32 dwRGBBitCount;
|
||||
# uint32 dwRBitMask;
|
||||
# uint32 dwGBitMask;
|
||||
# uint32 dwBBitMask;
|
||||
# uint32 dwRGBAlphaBitMask;
|
||||
# };
|
||||
ddpf_dwSize = 32
|
||||
ddpf_dwFlags = DDPF_FOURCC
|
||||
ddpf_dwFourCC = 0
|
||||
ddpf_dwRGBBitCount = 0
|
||||
ddpf_dwRBitMask = 0
|
||||
ddpf_dwGBitMask = 0
|
||||
ddpf_dwBBitMask = 0
|
||||
ddpf_dwRGBAlphaBitMask = 0
|
||||
|
||||
# DDSCAPS2
|
||||
# struct DDSCAPS2 {
|
||||
# uint32 dwCaps;
|
||||
# uint32 dwCaps2;
|
||||
# uint32 dwCaps3;
|
||||
# uint32 dwCaps4;
|
||||
# };
|
||||
ddsCaps_dwCaps = DDSCAPS_TEXTURE
|
||||
ddsCaps_dwCaps2 = 0
|
||||
ddsCaps_dwCaps3 = 0
|
||||
ddsCaps_dwCaps4 = 0
|
||||
|
||||
dwUnused1 = 0
|
||||
|
||||
# Decide whether to use legacy FourCC (DXT1/DXT5/ATI1/ATI2) or DX10 header
|
||||
use_legacy = (
|
||||
not force_dx10_header and
|
||||
dxgi_format in (
|
||||
DXGI_FORMAT.BC1_UNORM,
|
||||
DXGI_FORMAT.BC3_UNORM,
|
||||
DXGI_FORMAT.BC4_UNORM,
|
||||
DXGI_FORMAT.BC5_UNORM,
|
||||
)
|
||||
)
|
||||
|
||||
if use_legacy:
|
||||
if dxgi_format == DXGI_FORMAT.BC1_UNORM:
|
||||
ddpf_dwFourCC = make_fourcc('D', 'X', 'T', '1')
|
||||
elif dxgi_format == DXGI_FORMAT.BC3_UNORM:
|
||||
ddpf_dwFourCC = make_fourcc('D', 'X', 'T', '5')
|
||||
elif dxgi_format == DXGI_FORMAT.BC4_UNORM:
|
||||
ddpf_dwFourCC = make_fourcc('A', 'T', 'I', '1')
|
||||
elif dxgi_format == DXGI_FORMAT.BC5_UNORM:
|
||||
ddpf_dwFourCC = make_fourcc('A', 'T', 'I', '2')
|
||||
else:
|
||||
# Write DX10 header, FourCC = "DX10"
|
||||
ddpf_dwFourCC = make_fourcc('D', 'X', '1', '0')
|
||||
|
||||
# Build the 31 uint32's for DDSURFACEDESC2
|
||||
header_values = [
|
||||
dwSize,
|
||||
dwFlags,
|
||||
dwHeight,
|
||||
dwWidth,
|
||||
lPitch,
|
||||
dwBackBufferCount,
|
||||
dwMipMapCount,
|
||||
dwAlphaBitDepth,
|
||||
dwUnused0,
|
||||
lpSurface,
|
||||
]
|
||||
|
||||
header_values.extend(ddcolorkey_zero) # 8 uint32's
|
||||
|
||||
ddpf_values = [
|
||||
ddpf_dwSize,
|
||||
ddpf_dwFlags,
|
||||
ddpf_dwFourCC,
|
||||
ddpf_dwRGBBitCount,
|
||||
ddpf_dwRBitMask,
|
||||
ddpf_dwGBitMask,
|
||||
ddpf_dwBBitMask,
|
||||
ddpf_dwRGBAlphaBitMask,
|
||||
]
|
||||
header_values.extend(ddpf_values) # 8 uint32's
|
||||
|
||||
ddsCaps_values = [
|
||||
ddsCaps_dwCaps,
|
||||
ddsCaps_dwCaps2,
|
||||
ddsCaps_dwCaps3,
|
||||
ddsCaps_dwCaps4,
|
||||
]
|
||||
header_values.extend(ddsCaps_values) # 4 uint32's
|
||||
|
||||
header_values.append(dwUnused1) # final uint32
|
||||
|
||||
if len(header_values) != 31:
|
||||
raise RuntimeError("Internal error: DDSURFACEDESC2 must contain 31 uint32's")
|
||||
|
||||
# Pack and write DDSURFACEDESC2
|
||||
dds_header = struct.pack("<31I", *header_values)
|
||||
f.write(dds_header)
|
||||
|
||||
# If needed, write the DX10 header (DDS_HEADER_DXT10)
|
||||
if not use_legacy:
|
||||
# struct DDS_HEADER_DXT10 {
|
||||
# DXGI_FORMAT dxgiFormat;
|
||||
# D3D10_RESOURCE_DIMENSION resourceDimension;
|
||||
# uint32 miscFlag;
|
||||
# uint32 arraySize;
|
||||
# uint32 miscFlags2;
|
||||
# };
|
||||
dxgiFormat = int(dxgi_format)
|
||||
resourceDimension = D3D10_RESOURCE_DIMENSION.TEXTURE2D
|
||||
miscFlag = 0
|
||||
arraySize = 1
|
||||
miscFlags2 = 0
|
||||
|
||||
dxt10_header = struct.pack(
|
||||
"<5I",
|
||||
dxgiFormat,
|
||||
resourceDimension,
|
||||
miscFlag,
|
||||
arraySize,
|
||||
miscFlags2,
|
||||
)
|
||||
f.write(dxt10_header)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Write the actual texture data blocks (pBlocks)
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
# C code: fwrite(pBlocks, desc.lPitch, 1, pFile);
|
||||
# i.e. write exactly lPitch bytes.
|
||||
data = memoryview(blocks)
|
||||
if len(data) < lPitch:
|
||||
raise ValueError(
|
||||
f"blocks buffer too small: need at least {lPitch} bytes, got {len(data)}"
|
||||
)
|
||||
f.write(data[:lPitch])
|
||||
|
||||
except Exception as e:
|
||||
# Mimic the C-style error reporting as much as practical
|
||||
print(f"Failed writing to DDS file {filename}: {e}", file=sys.stderr)
|
||||
try:
|
||||
f.close()
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
# Close file
|
||||
try:
|
||||
f.close()
|
||||
except OSError:
|
||||
print(f"Failed closing DDS file {filename}!", file=sys.stderr)
|
||||
return False
|
||||
|
||||
return True
|
||||
413
python/explode_ktx2_file.py
Normal file
413
python/explode_ktx2_file.py
Normal file
@@ -0,0 +1,413 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
explode_ktx2_file.py
|
||||
FULL LDR/HDR KTX2 EXPLODER + FULL API INTROSPECTION + ASTC + BC7/BC6H OUTPUT
|
||||
|
||||
Usage:
|
||||
python3 explode_ktx2_file.py input.ktx2
|
||||
python3 explode_ktx2_file.py input.ktx2 --info-only
|
||||
"""
|
||||
|
||||
# Python Dependencies (beyond basisu_py):
|
||||
# numpy
|
||||
# pillow
|
||||
# imageio (v3+)
|
||||
# wasmtime
|
||||
#
|
||||
# System Dependencies:
|
||||
# OpenImageIO ("oiiotool") -- required for EXR output
|
||||
#
|
||||
# Install Python deps:
|
||||
# pip install numpy pillow imageio wasmtime
|
||||
#
|
||||
# On Ubuntu:
|
||||
# sudo apt install openimageio-tools
|
||||
#
|
||||
# On macOS (Homebrew):
|
||||
# brew install openimageio
|
||||
|
||||
import sys
|
||||
import os
|
||||
import numpy as np
|
||||
import subprocess
|
||||
import tempfile
|
||||
import imageio.v3 as iio
|
||||
from PIL import Image
|
||||
|
||||
from basisu_py import Transcoder
|
||||
from basisu_py.constants import TranscoderTextureFormat as TF
|
||||
|
||||
# Writers located in same directory as this script
|
||||
from astc_writer import write_astc_file
|
||||
from dds_writer import DDSWriter
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# File-writing helpers
|
||||
# ============================================================================
|
||||
def save_exr(path, rgba32f):
|
||||
"""
|
||||
Save float32 RGBA as EXR if possible.
|
||||
If oiiotool is not available, save TIFF instead (Windows-safe).
|
||||
"""
|
||||
import numpy as np
|
||||
import imageio.v3 as iio
|
||||
import subprocess, tempfile, os
|
||||
|
||||
# Write temp TIFF
|
||||
with tempfile.NamedTemporaryFile(suffix=".tiff", delete=False) as tmp:
|
||||
temp_path = tmp.name
|
||||
|
||||
iio.imwrite(temp_path, rgba32f.astype(np.float32))
|
||||
|
||||
# Try EXR via oiiotool
|
||||
try:
|
||||
subprocess.run(["oiiotool", temp_path, "-o", path], check=True)
|
||||
os.remove(temp_path)
|
||||
print(" Wrote EXR:", path)
|
||||
return
|
||||
|
||||
except Exception:
|
||||
# --- FALLBACK: save TIFF ---
|
||||
fallback_path = path + ".tiff"
|
||||
|
||||
# Windows cannot overwrite files via rename(), so remove first
|
||||
if os.path.exists(fallback_path):
|
||||
os.remove(fallback_path)
|
||||
|
||||
# os.replace() always overwrites
|
||||
os.replace(temp_path, fallback_path)
|
||||
|
||||
print(" [Fallback] Wrote TIFF instead:", fallback_path)
|
||||
|
||||
|
||||
def save_png(path, rgba8):
|
||||
img = Image.fromarray(rgba8, mode="RGBA")
|
||||
img.save(path)
|
||||
print(f" PNG saved: {path}")
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Pretty header
|
||||
# ============================================================================
|
||||
def print_header(title):
|
||||
print("\n" + "=" * 90)
|
||||
print(title)
|
||||
print("=" * 90)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Full top-level metadata dump (ALL API)
|
||||
# ============================================================================
|
||||
def dump_all_top_level(t, h):
|
||||
print_header("TOP-LEVEL KTX2 METADATA FULL API")
|
||||
|
||||
print("Backend :", t.backend_name)
|
||||
print("Version :", t.get_version())
|
||||
print("Width :", t.get_width(h))
|
||||
print("Height :", t.get_height(h))
|
||||
print("Levels :", t.get_levels(h))
|
||||
print("Faces :", t.get_faces(h))
|
||||
|
||||
layers = t.get_layers(h)
|
||||
eff_layers = layers if layers > 0 else 1
|
||||
print("Layers (raw) :", layers)
|
||||
print("Layers (effective) :", eff_layers)
|
||||
|
||||
fmt = t.get_basis_tex_format(h)
|
||||
print("\nBasisTexFormat :", fmt)
|
||||
|
||||
print("\nKTX2 Format Flags:")
|
||||
print(" is_etc1s :", t.is_etc1s(h))
|
||||
print(" is_uastc_ldr_4x4 :", t.is_uastc_ldr_4x4(h))
|
||||
print(" is_xuastc_ldr :", t.is_xuastc_ldr(h))
|
||||
print(" is_astc_ldr :", t.is_astc_ldr(h))
|
||||
print(" is_hdr :", t.is_hdr(h))
|
||||
print(" is_hdr_4x4 :", t.is_hdr_4x4(h))
|
||||
print(" is_hdr_6x6 :", t.is_hdr_6x6(h))
|
||||
print(" is_ldr :", t.is_ldr(h))
|
||||
print(" is_srgb :", t.is_srgb(h))
|
||||
print(" is_video :", t.is_video(h))
|
||||
print(" has_alpha :", t.has_alpha(h))
|
||||
|
||||
print("\nBlock Info:")
|
||||
print(" block_width :", t.get_block_width(h))
|
||||
print(" block_height :", t.get_block_height(h))
|
||||
|
||||
print("\nDFD Info:")
|
||||
print(" color_model :", t.get_dfd_color_model(h))
|
||||
print(" color_primaries :", t.get_dfd_color_primaries(h))
|
||||
print(" transfer_func :", t.get_dfd_transfer_func(h))
|
||||
print(" flags :", t.get_dfd_flags(h))
|
||||
print(" total_samples :", t.get_dfd_total_samples(h))
|
||||
print(" channel_id0 :", t.get_dfd_channel_id0(h))
|
||||
print(" channel_id1 :", t.get_dfd_channel_id1(h))
|
||||
|
||||
if t.is_hdr(h):
|
||||
print(" hdr_nit_multiplier :", t.get_ldr_hdr_upconversion_nit_multiplier(h))
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# BasisTexFormat helpers
|
||||
# ============================================================================
|
||||
def dump_basis_tex_format_helpers(t, h):
|
||||
print_header("BasisTexFormat HELPERS (FULL)")
|
||||
|
||||
fmt = t.get_basis_tex_format(h)
|
||||
print("basis_tex_format:", fmt)
|
||||
|
||||
print("is_xuastc_ldr :", t.basis_tex_format_is_xuastc_ldr(fmt))
|
||||
print("is_astc_ldr :", t.basis_tex_format_is_astc_ldr(fmt))
|
||||
print("block width :", t.basis_tex_format_get_block_width(fmt))
|
||||
print("block height :", t.basis_tex_format_get_block_height(fmt))
|
||||
print("is_hdr :", t.basis_tex_format_is_hdr(fmt))
|
||||
print("is_ldr :", t.basis_tex_format_is_ldr(fmt))
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Level / Layer / Face metadata dump
|
||||
# ============================================================================
|
||||
def dump_per_level_info(t, h):
|
||||
print_header("PER-LEVEL / PER-LAYER / PER-FACE METADATA")
|
||||
|
||||
levels = t.get_levels(h)
|
||||
faces = t.get_faces(h)
|
||||
layers = t.get_layers(h)
|
||||
if layers == 0:
|
||||
layers = 1
|
||||
|
||||
for level in range(levels):
|
||||
for layer in range(layers):
|
||||
for face in range(faces):
|
||||
print(f"\nLevel={level}, Layer={layer}, Face={face}")
|
||||
print(" orig_width :", t.get_level_orig_width(h, level, layer, face))
|
||||
print(" orig_height :", t.get_level_orig_height(h, level, layer, face))
|
||||
print(" actual_width :", t.get_level_actual_width(h, level, layer, face))
|
||||
print(" actual_height:", t.get_level_actual_height(h, level, layer, face))
|
||||
print(" blocks_x :", t.get_level_num_blocks_x(h, level, layer, face))
|
||||
print(" blocks_y :", t.get_level_num_blocks_y(h, level, layer, face))
|
||||
print(" total_blocks :", t.get_level_total_blocks(h, level, layer, face))
|
||||
print(" alpha_flag :", t.get_level_alpha_flag(h, level, layer, face))
|
||||
print(" iframe_flag :", t.get_level_iframe_flag(h, level, layer, face))
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# ASTC Selection
|
||||
# ============================================================================
|
||||
def choose_astc_format(t, h):
|
||||
fmt = t.get_basis_tex_format(h)
|
||||
tfmt = t.basis_get_transcoder_texture_format_from_basis_tex_format(fmt)
|
||||
bw = t.basis_get_block_width(tfmt)
|
||||
bh = t.basis_get_block_height(tfmt)
|
||||
|
||||
print_header("ASTC SELECTION")
|
||||
print("ASTC TF:", tfmt)
|
||||
print(f"Block dims: {bw}x{bh}")
|
||||
return tfmt, bw, bh
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# BC Format Selection
|
||||
# ============================================================================
|
||||
def choose_bc_format(t, h):
|
||||
if t.is_hdr(h):
|
||||
print_header("HDR -> BC6H")
|
||||
return TF.TF_BC6H, 8, 95 # DXGI_FORMAT_BC6H_UF16
|
||||
else:
|
||||
print_header("LDR -> BC7")
|
||||
return TF.TF_BC7_RGBA, 8, 98 # DXGI_FORMAT_BC7_UNORM
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Full explode transcoding (using handle API + per-level dims)
|
||||
# ============================================================================
|
||||
def explode_transcode(t, h):
|
||||
levels = t.get_levels(h)
|
||||
faces = t.get_faces(h)
|
||||
layers = t.get_layers(h)
|
||||
if layers == 0:
|
||||
layers = 1
|
||||
|
||||
astc_tfmt, astc_bw, astc_bh = choose_astc_format(t, h)
|
||||
bc_tfmt, bc_bpp, bc_dxgi = choose_bc_format(t, h)
|
||||
|
||||
ddsw = DDSWriter()
|
||||
print_header("BEGIN EXPLODE TRANSCODING (handle API)")
|
||||
|
||||
for level in range(levels):
|
||||
for layer in range(layers):
|
||||
for face in range(faces):
|
||||
|
||||
print(f"\n- Level={level} Layer={layer} Face={face}")
|
||||
|
||||
ow = t.get_level_orig_width(h, level, layer, face)
|
||||
oh = t.get_level_orig_height(h, level, layer, face)
|
||||
print(f" Level orig dims: {ow}x{oh}")
|
||||
|
||||
# ASTC
|
||||
astc_blocks = t.transcode_tfmt_handle(
|
||||
h, astc_tfmt,
|
||||
level=level, layer=layer, face=face,
|
||||
decode_flags=0, channel0=-1, channel1=-1
|
||||
)
|
||||
astc_name = f"astc_L{level}_Y{layer}_F{face}.astc"
|
||||
write_astc_file(astc_name, astc_blocks, astc_bw, astc_bh, ow, oh)
|
||||
print(" ASTC saved:", astc_name)
|
||||
|
||||
# BC6H / BC7
|
||||
bc_blocks = t.transcode_tfmt_handle(
|
||||
h, bc_tfmt,
|
||||
level=level, layer=layer, face=face,
|
||||
decode_flags=0, channel0=-1, channel1=-1
|
||||
)
|
||||
if t.is_hdr(h):
|
||||
dds_name = f"bc6h_L{level}_Y{layer}_F{face}.dds"
|
||||
else:
|
||||
dds_name = f"bc7_L{level}_Y{layer}_F{face}.dds"
|
||||
|
||||
ddsw.save_dds(
|
||||
dds_name,
|
||||
width=ow, height=oh,
|
||||
blocks=bc_blocks,
|
||||
pixel_format_bpp=bc_bpp,
|
||||
dxgi_format=bc_dxgi,
|
||||
srgb=False,
|
||||
force_dx10_header=True,
|
||||
)
|
||||
print(" DDS saved :", dds_name)
|
||||
|
||||
print_header("EXPLODE TRANSCODING COMPLETE")
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Decode each (Level, Layer, Face) to PNG or EXR
|
||||
# ============================================================================
|
||||
def explode_decode_images(t, h):
|
||||
print_header("BEGIN EXPLODE IMAGE DECODE (PNG/EXR)")
|
||||
|
||||
levels = t.get_levels(h)
|
||||
faces = t.get_faces(h)
|
||||
layers = t.get_layers(h)
|
||||
if layers == 0:
|
||||
layers = 1
|
||||
|
||||
hdr = t.is_hdr(h)
|
||||
|
||||
for level in range(levels):
|
||||
for layer in range(layers):
|
||||
for face in range(faces):
|
||||
|
||||
print(f"\n- Decode Level={level} Layer={layer} Face={face}")
|
||||
|
||||
ow = t.get_level_orig_width(h, level, layer, face)
|
||||
oh = t.get_level_orig_height(h, level, layer, face)
|
||||
|
||||
if hdr:
|
||||
rgba32f = t.decode_rgba_hdr_handle(h, level, layer, face)
|
||||
outname = f"exr_L{level}_Y{layer}_F{face}.exr"
|
||||
save_exr(outname, rgba32f)
|
||||
else:
|
||||
rgba8 = t.decode_rgba_handle(h, level, layer, face)
|
||||
outname = f"png_L{level}_Y{layer}_F{face}.png"
|
||||
save_png(outname, rgba8)
|
||||
|
||||
print_header("IMAGE DECODE COMPLETE")
|
||||
|
||||
def dump_transcoder_texture_format_helpers(t):
|
||||
print_header("TranscoderTextureFormat HELPERS (FULL)")
|
||||
|
||||
test_formats = [
|
||||
# uncompressed
|
||||
TF.TF_RGBA32, TF.TF_RGB565, TF.TF_BGR565,
|
||||
TF.TF_RGBA4444, TF.TF_RGB_HALF, TF.TF_RGBA_HALF, TF.TF_RGB_9E5,
|
||||
|
||||
# basic compressed
|
||||
TF.TF_ETC1_RGB, TF.TF_ETC2_RGBA,
|
||||
TF.TF_BC1_RGB, TF.TF_BC3_RGBA,
|
||||
TF.TF_BC4_R, TF.TF_BC5_RG,
|
||||
TF.TF_BC7_RGBA, TF.TF_BC6H,
|
||||
TF.TF_ETC2_EAC_R11, TF.TF_ETC2_EAC_RG11,
|
||||
TF.TF_FXT1_RGB,
|
||||
TF.TF_PVRTC1_4_RGB, TF.TF_PVRTC1_4_RGBA,
|
||||
TF.TF_PVRTC2_4_RGB, TF.TF_PVRTC2_4_RGBA,
|
||||
TF.TF_ATC_RGB, TF.TF_ATC_RGBA,
|
||||
|
||||
# HDR ASTC
|
||||
TF.TF_ASTC_HDR_4X4_RGBA,
|
||||
TF.TF_ASTC_HDR_6X6_RGBA,
|
||||
|
||||
# LDR ASTC
|
||||
TF.TF_ASTC_LDR_4X4_RGBA,
|
||||
TF.TF_ASTC_LDR_5X4_RGBA, TF.TF_ASTC_LDR_5X5_RGBA,
|
||||
TF.TF_ASTC_LDR_6X5_RGBA, TF.TF_ASTC_LDR_6X6_RGBA,
|
||||
TF.TF_ASTC_LDR_8X5_RGBA, TF.TF_ASTC_LDR_8X6_RGBA,
|
||||
TF.TF_ASTC_LDR_10X5_RGBA, TF.TF_ASTC_LDR_10X6_RGBA,
|
||||
TF.TF_ASTC_LDR_8X8_RGBA, TF.TF_ASTC_LDR_10X8_RGBA,
|
||||
TF.TF_ASTC_LDR_10X10_RGBA, TF.TF_ASTC_LDR_12X10_RGBA,
|
||||
TF.TF_ASTC_LDR_12X12_RGBA,
|
||||
]
|
||||
|
||||
for tfmt in test_formats:
|
||||
print(f"\nTF={tfmt}")
|
||||
print(" has_alpha :", t.basis_transcoder_format_has_alpha(tfmt))
|
||||
print(" is_hdr :", t.basis_transcoder_format_is_hdr(tfmt))
|
||||
print(" is_ldr :", t.basis_transcoder_format_is_ldr(tfmt))
|
||||
print(" is_astc :", t.basis_transcoder_texture_format_is_astc(tfmt))
|
||||
print(" is_uncompressed :", t.basis_transcoder_format_is_uncompressed(tfmt))
|
||||
print(" bytes/block :", t.basis_get_bytes_per_block_or_pixel(tfmt))
|
||||
print(" block_width :", t.basis_get_block_width(tfmt))
|
||||
print(" block_height :", t.basis_get_block_height(tfmt))
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python explode_ktx2_file.py input.ktx2 [--info-only] [--print-tf]")
|
||||
return 1
|
||||
|
||||
args = sys.argv[1:]
|
||||
info_only = "--info-only" in args
|
||||
print_tf = "--print-tf" in args or "--transcoder-formats" in args
|
||||
|
||||
# Determine input filename
|
||||
input_file = None
|
||||
for a in args:
|
||||
if not a.startswith("--"):
|
||||
input_file = a
|
||||
break
|
||||
|
||||
if input_file is None:
|
||||
print("Error: No input file provided.")
|
||||
return 1
|
||||
|
||||
ktx_bytes = open(input_file, "rb").read()
|
||||
|
||||
t = Transcoder()
|
||||
h = t.open(ktx_bytes)
|
||||
t.start_transcoding(h)
|
||||
|
||||
# Full metadata
|
||||
dump_all_top_level(t, h)
|
||||
dump_basis_tex_format_helpers(t, h)
|
||||
dump_per_level_info(t, h)
|
||||
|
||||
# Optional TF helpers
|
||||
if print_tf:
|
||||
dump_transcoder_texture_format_helpers(t)
|
||||
|
||||
if info_only:
|
||||
print_header("INFO-ONLY MODE NO FILES WRITTEN")
|
||||
t.close(h)
|
||||
return 0
|
||||
|
||||
# Full output
|
||||
explode_transcode(t, h)
|
||||
explode_decode_images(t, h)
|
||||
|
||||
t.close(h)
|
||||
print("Success")
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
||||
|
||||
1
python/lowlevel_test_native/__init__.py
Normal file
1
python/lowlevel_test_native/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# __init__.py
|
||||
127
python/lowlevel_test_native/basic_test.py
Normal file
127
python/lowlevel_test_native/basic_test.py
Normal file
@@ -0,0 +1,127 @@
|
||||
# basic_test.py
|
||||
import sys
|
||||
sys.path.append("basisu_py") # make sure Python can load the .so
|
||||
|
||||
import basisu_python as bu
|
||||
from constants import *
|
||||
|
||||
import ctypes
|
||||
import math
|
||||
|
||||
def generate_swirl_rgba8(width, height):
|
||||
"""
|
||||
Generate a smooth colorful swirl procedural RGBA8 test image.
|
||||
Returns: a ctypes array of type (c_ubyte * (width * height * 4))
|
||||
"""
|
||||
pixel_count = width * height * 4
|
||||
img = (ctypes.c_ubyte * pixel_count)()
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
i = (y * width + x) * 4
|
||||
|
||||
dx = x - width / 2
|
||||
dy = y - height / 2
|
||||
|
||||
dist = math.hypot(dx, dy)
|
||||
angle = math.atan2(dy, dx)
|
||||
|
||||
# Color swirl pattern
|
||||
r = int((math.sin(dist * 0.15) * 0.5 + 0.5) * 255)
|
||||
g = int((math.sin(angle * 3.0) * 0.5 + 0.5) * 255)
|
||||
b = int((math.cos(dist * 0.10 + angle * 2.0) * 0.5 + 0.5) * 255)
|
||||
|
||||
img[i + 0] = r & 255
|
||||
img[i + 1] = g & 255
|
||||
img[i + 2] = b & 255
|
||||
img[i + 3] = 255
|
||||
|
||||
return img
|
||||
|
||||
def generate_test_pattern_rgba8(width, height):
|
||||
"""
|
||||
Generate a simple deterministic RGBA8 test pattern:
|
||||
R = x
|
||||
G = y
|
||||
B = x^y
|
||||
A = 255
|
||||
"""
|
||||
import ctypes
|
||||
|
||||
pixel_count = width * height * 4
|
||||
img = (ctypes.c_ubyte * pixel_count)()
|
||||
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
i = (y * width + x) * 4
|
||||
|
||||
img[i + 0] = x & 0xFF
|
||||
img[i + 1] = y & 0xFF
|
||||
img[i + 2] = (x ^ y) & 0xFF
|
||||
img[i + 3] = 255
|
||||
|
||||
return img
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# BasisU compression test (NATIVE C++)
|
||||
# ------------------------------------------------------------
|
||||
|
||||
print("Native BasisU version:", bu.get_version())
|
||||
bu.init()
|
||||
|
||||
# Create comp params
|
||||
params = bu.new_params()
|
||||
print("Params handle:", params)
|
||||
|
||||
# Create RGBA8 swirl (64 x 64)
|
||||
W, H = 512, 512
|
||||
pixel_count = W * H * 4
|
||||
|
||||
# Generate swirl image in PYTHON memory
|
||||
|
||||
img = generate_swirl_rgba8(W, H)
|
||||
#img = generate_test_pattern_rgba8(W, H)
|
||||
|
||||
# Allocate memory inside NATIVE C++ heap
|
||||
img_ptr = bu.alloc(pixel_count)
|
||||
|
||||
# Copy Python swirl image ? C++ heap buffer
|
||||
ctypes.memmove(img_ptr, img, pixel_count)
|
||||
|
||||
# Set into BasisU
|
||||
pitch = W * 4
|
||||
ok = bu.set_image_rgba32(params, 0, img_ptr, W, H, pitch)
|
||||
print("Set image:", ok)
|
||||
|
||||
# Compress (UASTC LDR 4x4 = 1)
|
||||
ok = bu.compress(
|
||||
params,
|
||||
BasisTexFormat.cASTC_LDR_4x4, # basis_tex_format
|
||||
BasisQuality.MAX, # quality
|
||||
BasisEffort.DEFAULT, # effort
|
||||
BasisFlags.KTX2_OUTPUT | BasisFlags.SRGB | BasisFlags.THREADED | BasisFlags.DEBUG_OUTPUT | BasisFlags.VERBOSE, # flags
|
||||
0.0 # rdo
|
||||
)
|
||||
print("Compress:", ok)
|
||||
|
||||
# Retrieve compressed data
|
||||
size = bu.get_comp_data_size(params)
|
||||
ofs = bu.get_comp_data_ofs(params)
|
||||
|
||||
print("Output size =", size, "ptr =", ofs)
|
||||
|
||||
# Copy bytes out of native memory
|
||||
byte_ptr = ctypes.cast(ofs, ctypes.POINTER(ctypes.c_ubyte))
|
||||
blob = bytes(byte_ptr[i] for i in range(size))
|
||||
|
||||
print("First 16 bytes:", blob[:16])
|
||||
|
||||
# Save to KTX2
|
||||
with open("out_native.ktx2", "wb") as f:
|
||||
f.write(blob)
|
||||
|
||||
print("Saved out_native.ktx2")
|
||||
|
||||
# Cleanup
|
||||
bu.delete_params(params)
|
||||
bu.free(img_ptr)
|
||||
481
python/lowlevel_test_native/example_capi_python.py
Normal file
481
python/lowlevel_test_native/example_capi_python.py
Normal file
@@ -0,0 +1,481 @@
|
||||
#!/usr/bin/env python3
|
||||
# example_capi_python.py
|
||||
#
|
||||
# Simple Python port of example_capi.c using native C++ pybind11 bindings:
|
||||
# - basisu_python (encoder)
|
||||
# - basisu_transcoder_python (transcoder)
|
||||
#
|
||||
# Requires:
|
||||
# basisu_py/basisu_python*.so
|
||||
# basisu_py/basisu_transcoder_python*.so
|
||||
# basisu_py/constants.py
|
||||
|
||||
import sys
|
||||
import os
|
||||
import math
|
||||
import ctypes
|
||||
|
||||
# Make sure Python can see the native .so's and the shared constants
|
||||
sys.path.append("basisu_py")
|
||||
|
||||
import basisu_python as bu
|
||||
import basisu_transcoder_python as bt
|
||||
from constants import BasisTexFormat, BasisFlags
|
||||
from constants import TranscoderTextureFormat as TF
|
||||
from constants import TranscodeDecodeFlags as DF
|
||||
|
||||
TRUE = 1
|
||||
FALSE = 0
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Utility: write raw bytes to a file
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def write_blob_to_file(filename: str, data: bytes) -> int:
|
||||
print(f"write_blob_to_file: writing {len(data)} bytes to {filename!r}")
|
||||
if not filename or data is None:
|
||||
print(" ERROR: invalid filename or data")
|
||||
return FALSE
|
||||
|
||||
try:
|
||||
with open(filename, "wb") as f:
|
||||
f.write(data)
|
||||
print(" OK")
|
||||
return TRUE
|
||||
except OSError as e:
|
||||
print(" ERROR:", e)
|
||||
return FALSE
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TGA writer (24/32bpp) - port of write_tga_image()
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def write_tga_image(filename: str, w: int, h: int, has_alpha: bool, pixels_rgba_ptr: int) -> int:
|
||||
"""
|
||||
filename: path to TGA file
|
||||
w, h: image dimensions
|
||||
has_alpha: True for 32bpp, False for 24bpp
|
||||
pixels_rgba_ptr: C pointer (uint64) to RGBA or RGB data in native heap
|
||||
"""
|
||||
print(f"write_tga_image: {filename!r}, {w}x{h}, has_alpha={has_alpha}, ptr=0x{pixels_rgba_ptr:x}")
|
||||
if not filename or pixels_rgba_ptr == 0 or w <= 0 or h <= 0:
|
||||
print(" ERROR: invalid args")
|
||||
return -1
|
||||
|
||||
bytes_per_pixel = 4 if has_alpha else 3
|
||||
row_bytes = w * bytes_per_pixel
|
||||
total_bytes = row_bytes * h
|
||||
|
||||
# Create a ctypes buffer that views the native memory
|
||||
SrcArrayType = ctypes.c_ubyte * total_bytes
|
||||
src = SrcArrayType.from_address(pixels_rgba_ptr)
|
||||
|
||||
try:
|
||||
with open(filename, "wb") as f:
|
||||
header = bytearray(18)
|
||||
header[2] = 2 # uncompressed true-color
|
||||
header[12] = w & 0xFF
|
||||
header[13] = (w >> 8) & 0xFF
|
||||
header[14] = h & 0xFF
|
||||
header[15] = (h >> 8) & 0xFF
|
||||
header[16] = 32 if has_alpha else 24
|
||||
header[17] = 8 if has_alpha else 0 # bottom-left origin (with or without alpha)
|
||||
|
||||
f.write(header)
|
||||
|
||||
# temp row buffer for BGRA/BGR
|
||||
row_buf = bytearray(row_bytes)
|
||||
|
||||
# TGA expects rows bottom-to-top
|
||||
for y in range(h):
|
||||
src_y = h - 1 - y
|
||||
row_start = src_y * row_bytes
|
||||
src_row = src[row_start:row_start + row_bytes]
|
||||
|
||||
if has_alpha:
|
||||
# RGBA -> BGRA
|
||||
for x in range(w):
|
||||
si = x*4
|
||||
di = x*4
|
||||
row_buf[di + 0] = src_row[si + 2] # B
|
||||
row_buf[di + 1] = src_row[si + 1] # G
|
||||
row_buf[di + 2] = src_row[si + 0] # R
|
||||
row_buf[di + 3] = src_row[si + 3] # A
|
||||
else:
|
||||
# RGB -> BGR
|
||||
for x in range(w):
|
||||
si = x*3
|
||||
di = x*3
|
||||
row_buf[di + 0] = src_row[si + 2] # B
|
||||
row_buf[di + 1] = src_row[si + 1] # G
|
||||
row_buf[di + 2] = src_row[si + 0] # R
|
||||
|
||||
f.write(row_buf)
|
||||
|
||||
print(" Wrote TGA:", filename)
|
||||
return 0
|
||||
except OSError as e:
|
||||
print(" ERROR writing TGA:", e)
|
||||
return -2
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# ASTC writer - port of write_astc_file()
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def write_astc_file(filename: str,
|
||||
blocks_ptr: int,
|
||||
block_width: int,
|
||||
block_height: int,
|
||||
dim_x: int,
|
||||
dim_y: int) -> int:
|
||||
print(f"write_astc_file: {filename!r}, block={block_width}x{block_height}, dim={dim_x}x{dim_y}, ptr=0x{blocks_ptr:x}")
|
||||
if not filename or blocks_ptr == 0:
|
||||
print(" ERROR: invalid filename or pointer")
|
||||
return 0
|
||||
|
||||
assert dim_x > 0 and dim_y > 0
|
||||
assert 4 <= block_width <= 12
|
||||
assert 4 <= block_height <= 12
|
||||
|
||||
num_blocks_x = (dim_x + block_width - 1) // block_width
|
||||
num_blocks_y = (dim_y + block_height - 1) // block_height
|
||||
total_blocks = num_blocks_x * num_blocks_y
|
||||
total_bytes = total_blocks * 16 # 16 bytes per ASTC block
|
||||
|
||||
print(f" num_blocks_x={num_blocks_x}, num_blocks_y={num_blocks_y}, total_blocks={total_blocks}, total_bytes={total_bytes}")
|
||||
|
||||
# View native memory
|
||||
BlockArray = ctypes.c_ubyte * total_bytes
|
||||
src = BlockArray.from_address(blocks_ptr)
|
||||
|
||||
try:
|
||||
with open(filename, "wb") as f:
|
||||
# Magic
|
||||
f.write(bytes([0x13, 0xAB, 0xA1, 0x5C]))
|
||||
|
||||
# Block dimensions x,y,z (=1)
|
||||
f.write(bytes([block_width & 0xFF, block_height & 0xFF, 1]))
|
||||
|
||||
# dim_x (24-bit LE)
|
||||
f.write(bytes([dim_x & 0xFF, (dim_x >> 8) & 0xFF, (dim_x >> 16) & 0xFF]))
|
||||
|
||||
# dim_y (24-bit LE)
|
||||
f.write(bytes([dim_y & 0xFF, (dim_y >> 8) & 0xFF, (dim_y >> 16) & 0xFF]))
|
||||
|
||||
# dim_z = 1 (24-bit LE)
|
||||
f.write(bytes([1, 0, 0]))
|
||||
|
||||
# Block data
|
||||
f.write(bytes(src))
|
||||
|
||||
print(" Wrote ASTC:", filename)
|
||||
return 1
|
||||
except OSError as e:
|
||||
print(" ERROR writing ASTC:", e)
|
||||
return 0
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Procedural RGBA pattern (ported & fixed version)
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def create_pretty_rgba_pattern(w: int, h: int) -> bytes:
|
||||
print(f"create_pretty_rgba_pattern: {w}x{h}")
|
||||
if w <= 0 or h <= 0:
|
||||
return None
|
||||
|
||||
out = bytearray(w * h * 4)
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
fx = x / float(w)
|
||||
fy = y / float(h)
|
||||
|
||||
# Colorful plasma-type formula
|
||||
v = math.sin(fx * 12.0 + fy * 4.0)
|
||||
v += math.sin(fy * 9.0 - fx * 6.0)
|
||||
v += math.sin((fx + fy) * 7.0)
|
||||
v = v * 0.25 + 0.5 # scale 0..1
|
||||
|
||||
L = 1.5
|
||||
|
||||
r = int(round(255.0 * math.sin(v * 6.28) * L))
|
||||
g = int(round(255.0 * (1.0 - v) * L))
|
||||
b = int(round(255.0 * v * L))
|
||||
|
||||
if r < 0: r = 0
|
||||
elif r > 255: r = 255
|
||||
if g < 0: g = 0
|
||||
elif g > 255: g = 255
|
||||
if b < 0: b = 0
|
||||
elif b > 255: b = 255
|
||||
|
||||
i = (y * w + x) * 4
|
||||
out[i+0] = r
|
||||
out[i+1] = g
|
||||
out[i+2] = b
|
||||
out[i+3] = 255
|
||||
|
||||
return bytes(out)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Transcode a KTX2 blob (ported from transcode_ktx2_file)
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def transcode_ktx2_file(ktx2_data: bytes) -> int:
|
||||
if not ktx2_data:
|
||||
print("transcode_ktx2_file: empty data")
|
||||
return FALSE
|
||||
|
||||
size = len(ktx2_data)
|
||||
print(f"transcode_ktx2_file: size={size} bytes")
|
||||
|
||||
if size > 0xFFFFFFFF:
|
||||
print(" ERROR: size too large for 32-bit length")
|
||||
return FALSE
|
||||
|
||||
# Allocate memory in transcoder heap and copy KTX2 data
|
||||
ktx2_data_ofs = bt.alloc(size)
|
||||
if not ktx2_data_ofs:
|
||||
print(" ERROR: bt.alloc failed")
|
||||
return FALSE
|
||||
|
||||
print(f" KTX2 data allocated at 0x{ktx2_data_ofs:x}")
|
||||
ctypes.memmove(ktx2_data_ofs, ktx2_data, size)
|
||||
|
||||
# Open KTX2
|
||||
ktx2_handle = bt.ktx2_open(ktx2_data_ofs, size)
|
||||
if not ktx2_handle:
|
||||
print(" ERROR: bt.ktx2_open failed")
|
||||
bt.free(ktx2_data_ofs)
|
||||
return FALSE
|
||||
|
||||
print(f" KTX2 handle = 0x{ktx2_handle:x}")
|
||||
|
||||
if not bt.ktx2_is_ldr(ktx2_handle):
|
||||
print(" ERROR: This sample only handles LDR KTX2 files")
|
||||
bt.ktx2_close(ktx2_handle)
|
||||
bt.free(ktx2_data_ofs)
|
||||
return FALSE
|
||||
|
||||
if not bt.ktx2_start_transcoding(ktx2_handle):
|
||||
print(" ERROR: bt.ktx2_start_transcoding failed")
|
||||
bt.ktx2_close(ktx2_handle)
|
||||
bt.free(ktx2_data_ofs)
|
||||
return FALSE
|
||||
|
||||
width = bt.ktx2_get_width(ktx2_handle)
|
||||
height = bt.ktx2_get_height(ktx2_handle)
|
||||
levels = bt.ktx2_get_levels(ktx2_handle)
|
||||
faces = bt.ktx2_get_faces(ktx2_handle)
|
||||
layers = bt.ktx2_get_layers(ktx2_handle)
|
||||
|
||||
basis_tex_format = bt.ktx2_get_basis_tex_format(ktx2_handle)
|
||||
block_width = bt.ktx2_get_block_width(ktx2_handle)
|
||||
block_height = bt.ktx2_get_block_height(ktx2_handle)
|
||||
is_srgb = bt.ktx2_is_srgb(ktx2_handle)
|
||||
|
||||
print(f"KTX2 Dimensions: {width}x{height}, Levels={levels}, Faces={faces}, Layers={layers}")
|
||||
print(f"basis_tex_format: {basis_tex_format}")
|
||||
print(f"Block dimensions: {block_width}x{block_height}")
|
||||
print(f"is sRGB: {is_srgb}")
|
||||
|
||||
if layers < 1:
|
||||
layers = 1
|
||||
|
||||
assert width >= 1 and height >= 1
|
||||
assert levels >= 1
|
||||
assert faces in (1, 6)
|
||||
|
||||
# Optional: separate transcode state (thread-local)
|
||||
trans_state = bt.ktx2_create_transcode_state()
|
||||
print(f"trans_state handle = 0x{trans_state:x}")
|
||||
|
||||
for level_index in range(levels):
|
||||
for layer_index in range(layers):
|
||||
for face_index in range(faces):
|
||||
print(f"- Level {level_index}, layer {layer_index}, face {face_index}")
|
||||
ow = bt.ktx2_get_level_orig_width(ktx2_handle, level_index, layer_index, face_index)
|
||||
oh = bt.ktx2_get_level_orig_height(ktx2_handle, level_index, layer_index, face_index)
|
||||
aw = bt.ktx2_get_level_actual_width(ktx2_handle, level_index, layer_index, face_index)
|
||||
ah = bt.ktx2_get_level_actual_height(ktx2_handle, level_index, layer_index, face_index)
|
||||
nbx = bt.ktx2_get_level_num_blocks_x(ktx2_handle, level_index, layer_index, face_index)
|
||||
nby = bt.ktx2_get_level_num_blocks_y(ktx2_handle, level_index, layer_index, face_index)
|
||||
tblocks = bt.ktx2_get_level_total_blocks(ktx2_handle, level_index, layer_index, face_index)
|
||||
alpha_flag = bt.ktx2_get_level_alpha_flag(ktx2_handle, level_index, layer_index, face_index)
|
||||
iframe_flag = bt.ktx2_get_level_iframe_flag(ktx2_handle, level_index, layer_index, face_index)
|
||||
|
||||
print(f" Orig dimensions: {ow}x{oh}, actual: {aw}x{ah}")
|
||||
print(f" Block dims: {nbx}x{nby}, total blocks: {tblocks}")
|
||||
print(f" Alpha={alpha_flag}, I-frame={iframe_flag}")
|
||||
|
||||
# 1) Transcode to RGBA32 and write TGA
|
||||
tga_name = f"transcoded_{level_index}_{layer_index}_{face_index}.tga"
|
||||
trans_size_rgba = bt.basis_compute_transcoded_image_size_in_bytes(TF.TF_RGBA32, ow, oh)
|
||||
assert trans_size_rgba > 0
|
||||
rgba_ofs = bt.alloc(trans_size_rgba)
|
||||
print(f" RGBA buf ofs=0x{rgba_ofs:x}, size={trans_size_rgba}")
|
||||
|
||||
decode_flags = 0
|
||||
ok = bt.ktx2_transcode_image_level(
|
||||
ktx2_handle,
|
||||
level_index, layer_index, face_index,
|
||||
rgba_ofs,
|
||||
trans_size_rgba,
|
||||
TF.TF_RGBA32,
|
||||
decode_flags,
|
||||
0, 0, -1, -1,
|
||||
trans_state
|
||||
)
|
||||
print(" ktx2_transcode_image_level(RGBA32):", ok)
|
||||
if not ok:
|
||||
bt.free(rgba_ofs)
|
||||
bt.ktx2_destroy_transcode_state(trans_state)
|
||||
bt.ktx2_close(ktx2_handle)
|
||||
bt.free(ktx2_data_ofs)
|
||||
return FALSE
|
||||
|
||||
write_tga_image(tga_name, ow, oh, True, rgba_ofs)
|
||||
bt.free(rgba_ofs)
|
||||
|
||||
# 2) Transcode to ASTC and write .astc file
|
||||
astc_name = f"transcoded_{level_index}_{layer_index}_{face_index}.astc"
|
||||
target_tf = bt.basis_get_transcoder_texture_format_from_basis_tex_format(basis_tex_format)
|
||||
print(f" Target ASTC TF={target_tf}")
|
||||
|
||||
trans_size_astc = bt.basis_compute_transcoded_image_size_in_bytes(target_tf, ow, oh)
|
||||
assert trans_size_astc > 0
|
||||
astc_ofs = bt.alloc(trans_size_astc)
|
||||
print(f" ASTC buf ofs=0x{astc_ofs:x}, size={trans_size_astc}")
|
||||
|
||||
ok = bt.ktx2_transcode_image_level(
|
||||
ktx2_handle,
|
||||
level_index, layer_index, face_index,
|
||||
astc_ofs,
|
||||
trans_size_astc,
|
||||
target_tf,
|
||||
0, 0, 0, -1, -1,
|
||||
trans_state
|
||||
)
|
||||
print(" ktx2_transcode_image_level(ASTC):", ok)
|
||||
if not ok:
|
||||
bt.free(astc_ofs)
|
||||
bt.ktx2_destroy_transcode_state(trans_state)
|
||||
bt.ktx2_close(ktx2_handle)
|
||||
bt.free(ktx2_data_ofs)
|
||||
return FALSE
|
||||
|
||||
write_astc_file(astc_name, astc_ofs, block_width, block_height, ow, oh)
|
||||
bt.free(astc_ofs)
|
||||
|
||||
bt.ktx2_destroy_transcode_state(trans_state)
|
||||
bt.ktx2_close(ktx2_handle)
|
||||
bt.free(ktx2_data_ofs)
|
||||
|
||||
print("transcode_ktx2_file: success")
|
||||
return TRUE
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# main() equivalent
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
print("example_capi_python:")
|
||||
|
||||
# Init encoder (which initializes transcoder)
|
||||
print("Calling bu.init() ...")
|
||||
bu.init()
|
||||
|
||||
print("Calling bt.init() ...")
|
||||
bt.init()
|
||||
|
||||
# Optional debug control if bound
|
||||
if hasattr(bu, "enable_debug_printf"):
|
||||
print("Disabling debug printf from encoder")
|
||||
bu.enable_debug_printf(False)
|
||||
|
||||
# Generate test image
|
||||
W, H = 512, 512
|
||||
src_image = create_pretty_rgba_pattern(W, H)
|
||||
if src_image is None:
|
||||
print("ERROR: create_pretty_rgba_pattern failed")
|
||||
return 1
|
||||
|
||||
# Save test image for inspection
|
||||
print("Writing test_image.tga ...")
|
||||
# use Python-level TGA writer by allocating a temporary native buffer
|
||||
tmp_ofs = bt.alloc(len(src_image))
|
||||
ctypes.memmove(tmp_ofs, src_image, len(src_image))
|
||||
write_tga_image("test_image.tga", W, H, True, tmp_ofs)
|
||||
bt.free(tmp_ofs)
|
||||
|
||||
# Compress to KTX2
|
||||
print("Creating comp_params ...")
|
||||
comp_params = bu.new_params()
|
||||
print(" comp_params handle:", comp_params)
|
||||
|
||||
img_ofs = bu.alloc(W * H * 4)
|
||||
print(f"Allocated encoder image buffer at 0x{img_ofs:x}")
|
||||
ctypes.memmove(img_ofs, src_image, W * H * 4)
|
||||
|
||||
print("Calling bu.comp_params_set_image_rgba32(...)")
|
||||
ok = bu.set_image_rgba32(comp_params, 0, img_ofs, W, H, W * 4)
|
||||
print(" set_image_rgba32:", ok)
|
||||
if not ok:
|
||||
print("ERROR: bu_comp_params_set_image_rgba32 failed")
|
||||
return 1
|
||||
|
||||
bu.free(img_ofs)
|
||||
|
||||
print("Compressing to XUASTC LDR 8x5 KTX2 ...")
|
||||
basis_tex_format = BasisTexFormat.cXUASTC_LDR_8x5
|
||||
quality_level = 85
|
||||
effort_level = 2
|
||||
flags = (BasisFlags.KTX2_OUTPUT |
|
||||
BasisFlags.SRGB |
|
||||
BasisFlags.THREADED |
|
||||
BasisFlags.GEN_MIPS_CLAMP |
|
||||
BasisFlags.PRINT_STATS |
|
||||
BasisFlags.PRINT_STATUS)
|
||||
|
||||
ok = bu.compress(comp_params,
|
||||
tex_format=basis_tex_format,
|
||||
quality=quality_level,
|
||||
effort=effort_level,
|
||||
flags=flags,
|
||||
rdo_quality=0.0)
|
||||
print(" bu.compress:", ok)
|
||||
if not ok:
|
||||
print("ERROR: bu_compress_texture failed")
|
||||
return 1
|
||||
|
||||
comp_size = bu.get_comp_data_size(comp_params)
|
||||
print("Compressed size:", comp_size)
|
||||
if comp_size == 0:
|
||||
print("ERROR: bu_comp_params_get_comp_data_size failed")
|
||||
return 1
|
||||
|
||||
comp_ofs = bu.get_comp_data_ofs(comp_params)
|
||||
print(f"Compressed data ptr=0x{comp_ofs:x}")
|
||||
|
||||
# Copy compressed data into Python bytes
|
||||
CompArray = ctypes.c_ubyte * comp_size
|
||||
comp_buf = CompArray.from_address(comp_ofs)
|
||||
comp_bytes = bytes(comp_buf)
|
||||
|
||||
print("Writing test.ktx2 ...")
|
||||
if not write_blob_to_file("test.ktx2", comp_bytes):
|
||||
print("ERROR: write_blob_to_file failed")
|
||||
return 1
|
||||
|
||||
# Transcode using the native transcoder API
|
||||
print("Now transcoding test.ktx2 via C API ...")
|
||||
if not transcode_ktx2_file(comp_bytes):
|
||||
print("ERROR: transcode_ktx2_file failed")
|
||||
return 1
|
||||
|
||||
bu.delete_params(comp_params)
|
||||
|
||||
print("Success")
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
24
python/lowlevel_test_native/test_transcoder_basic.py
Normal file
24
python/lowlevel_test_native/test_transcoder_basic.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# test_transcoder_basic.py
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Make sure Python can find the .so file
|
||||
sys.path.append("basisu_py") # Adjust if needed
|
||||
|
||||
try:
|
||||
import basisu_transcoder_python as bt
|
||||
except ImportError as e:
|
||||
print("Failed to import basisu_transcoder_python:", e)
|
||||
raise
|
||||
|
||||
print("Successfully loaded basisu_transcoder_python")
|
||||
|
||||
# Call bt_get_version() via the pybind11 binding
|
||||
try:
|
||||
version = bt.get_version()
|
||||
print("Transcoder version:", version)
|
||||
except Exception as e:
|
||||
print("Error calling bt_get_version:", e)
|
||||
raise
|
||||
|
||||
print("Basic transcoder test complete.")
|
||||
1
python/lowlevel_test_wasm/__init__.py
Normal file
1
python/lowlevel_test_wasm/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# __init__.py
|
||||
58
python/lowlevel_test_wasm/basic_test.py
Normal file
58
python/lowlevel_test_wasm/basic_test.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import wasmtime
|
||||
import ctypes
|
||||
|
||||
# --- Engine ---
|
||||
engine = wasmtime.Engine()
|
||||
|
||||
# --- Store ---
|
||||
store = wasmtime.Store(engine)
|
||||
|
||||
# --- WASI config ---
|
||||
wasi = wasmtime.WasiConfig()
|
||||
wasi.argv = ["basisu_module_st"]
|
||||
wasi.inherit_stdout() # <-- tell WASI to use the host stdout
|
||||
wasi.inherit_stderr()
|
||||
store.set_wasi(wasi)
|
||||
|
||||
# --- Load module ---
|
||||
module = wasmtime.Module.from_file(engine, "basisu_py/wasm/basisu_module_st.wasm")
|
||||
|
||||
# --- Linker + WASI ---
|
||||
linker = wasmtime.Linker(engine)
|
||||
linker.define_wasi()
|
||||
|
||||
# --- Instantiate ---
|
||||
instance = linker.instantiate(store, module)
|
||||
print("Single-threaded WASM instantiated OK")
|
||||
|
||||
# --- Exports ---
|
||||
exports = instance.exports(store)
|
||||
|
||||
get_version = exports["bu_get_version"]
|
||||
alloc = exports["bu_alloc"]
|
||||
free = exports["bu_free"]
|
||||
memory = exports["memory"]
|
||||
|
||||
# --- Version ---
|
||||
version = get_version(store)
|
||||
print("Version =", version)
|
||||
|
||||
# --- Alloc ---
|
||||
ptr = alloc(store, 64)
|
||||
print("Allocated ptr =", ptr)
|
||||
|
||||
# --- Access WASM memory properly ---
|
||||
data_len = memory.data_len(store)
|
||||
raw_ptr = memory.data_ptr(store) # ctypes pointer
|
||||
addr = ctypes.addressof(raw_ptr.contents) # convert to integer pointer
|
||||
|
||||
# Create a byte array view into WASM memory
|
||||
buf = (ctypes.c_ubyte * data_len).from_address(addr)
|
||||
|
||||
# Write TEST at allocated ptr
|
||||
buf[ptr : ptr + 4] = b"TEST"
|
||||
print("Wrote TEST into WASM memory.")
|
||||
|
||||
# --- Free ---
|
||||
free(store, ptr)
|
||||
print("Memory free OK.")
|
||||
148
python/lowlevel_test_wasm/basisu_wasm.py
Normal file
148
python/lowlevel_test_wasm/basisu_wasm.py
Normal file
@@ -0,0 +1,148 @@
|
||||
# basisu_wasm.py
|
||||
import wasmtime
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
sys.path.append("basisu_py") # our shared .py files
|
||||
|
||||
from constants import *
|
||||
|
||||
class BasisuWasm:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.engine = None
|
||||
self.store = None
|
||||
self.memory = None
|
||||
self.exports = None
|
||||
|
||||
# -----------------------------------------------
|
||||
# Internal helper: build WASI + Wasmtime engine
|
||||
# -----------------------------------------------
|
||||
def _init_engine(self):
|
||||
self.engine = wasmtime.Engine()
|
||||
self.store = wasmtime.Store(self.engine)
|
||||
|
||||
wasi = wasmtime.WasiConfig()
|
||||
wasi.argv = ["basisu"]
|
||||
wasi.inherit_stdout()
|
||||
wasi.inherit_stderr()
|
||||
self.store.set_wasi(wasi)
|
||||
|
||||
return wasi
|
||||
|
||||
# -----------------------------------------------
|
||||
# Create linker and instantiate WASM module
|
||||
# -----------------------------------------------
|
||||
def load(self):
|
||||
self._init_engine()
|
||||
|
||||
module = wasmtime.Module.from_file(self.engine, self.path)
|
||||
linker = wasmtime.Linker(self.engine)
|
||||
linker.define_wasi()
|
||||
|
||||
instance = linker.instantiate(self.store, module)
|
||||
|
||||
self.exports = instance.exports(self.store)
|
||||
self.memory = self.exports["memory"]
|
||||
|
||||
if "bu_init" in self.exports:
|
||||
self.exports["bu_init"](self.store)
|
||||
|
||||
print("WASM loaded:", self.path)
|
||||
|
||||
# -----------------------------------------------
|
||||
# Read/write WASM linear memory via ctypes
|
||||
# -----------------------------------------------
|
||||
def _wasm_buf(self):
|
||||
raw_ptr = self.memory.data_ptr(self.store)
|
||||
length = self.memory.data_len(self.store)
|
||||
addr = ctypes.addressof(raw_ptr.contents)
|
||||
return (ctypes.c_ubyte * length).from_address(addr)
|
||||
|
||||
# -----------------------------------------------
|
||||
# Exported API accessors
|
||||
# -----------------------------------------------
|
||||
def init(self):
|
||||
return self.exports["bu_init"](self.store)
|
||||
|
||||
def version(self):
|
||||
return self.exports["bu_get_version"](self.store)
|
||||
|
||||
def alloc(self, size):
|
||||
return self.exports["bu_alloc"](self.store, size)
|
||||
|
||||
def free(self, ptr):
|
||||
return self.exports["bu_free"](self.store, ptr)
|
||||
|
||||
def new_params(self):
|
||||
return self.exports["bu_new_comp_params"](self.store)
|
||||
|
||||
def delete_params(self, ptr):
|
||||
return self.exports["bu_delete_comp_params"](self.store, ptr)
|
||||
|
||||
def set_image_rgba32(self, params, image_index, img_ptr, w, h, pitch):
|
||||
return self.exports["bu_comp_params_set_image_rgba32"](
|
||||
self.store, params, image_index, img_ptr, w, h, pitch
|
||||
)
|
||||
|
||||
def set_image_float_rgba(self, params, image_index, img_ptr, w, h, pitch):
|
||||
return self.exports["bu_comp_params_set_image_float_rgba"](
|
||||
self.store, params, image_index, img_ptr, w, h, pitch
|
||||
)
|
||||
|
||||
# Normally quality_level controls the quality.
|
||||
# If quality_level==-1, then rdo_quality (a low-level parameter) directly
|
||||
# controls each codec's quality setting. Normally set to 0.
|
||||
|
||||
def compress_texture_lowlevel(self, params,
|
||||
tex_format,
|
||||
quality_level,
|
||||
effort_level,
|
||||
flags_and_quality,
|
||||
rdo_quality):
|
||||
|
||||
return self.exports["bu_compress_texture"](
|
||||
self.store,
|
||||
params,
|
||||
tex_format,
|
||||
quality_level,
|
||||
effort_level,
|
||||
flags_and_quality,
|
||||
rdo_quality
|
||||
)
|
||||
|
||||
def compress(self, params,
|
||||
tex_format=BasisTexFormat.cUASTC_LDR_4x4,
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.NONE,
|
||||
rdo_quality=0.0):
|
||||
|
||||
return bool(self.compress_texture_lowlevel(
|
||||
params,
|
||||
tex_format,
|
||||
quality,
|
||||
effort,
|
||||
flags,
|
||||
rdo_quality
|
||||
))
|
||||
|
||||
def get_comp_data_ofs(self, params):
|
||||
return self.exports["bu_comp_params_get_comp_data_ofs"](self.store, params)
|
||||
|
||||
def get_comp_data_size(self, params):
|
||||
return self.exports["bu_comp_params_get_comp_data_size"](self.store, params)
|
||||
|
||||
# -----------------------------------------------
|
||||
# Copy bytes into WASM memory
|
||||
# -----------------------------------------------
|
||||
def write_bytes(self, wasm_ptr, data: bytes):
|
||||
buf = self._wasm_buf()
|
||||
buf[wasm_ptr:wasm_ptr+len(data)] = data
|
||||
|
||||
# -----------------------------------------------
|
||||
# Read bytes from WASM memory
|
||||
# -----------------------------------------------
|
||||
def read_bytes(self, wasm_ptr, size):
|
||||
buf = self._wasm_buf()
|
||||
return bytes(buf[wasm_ptr:wasm_ptr+size])
|
||||
63
python/lowlevel_test_wasm/compress_test.py
Normal file
63
python/lowlevel_test_wasm/compress_test.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# compress_test.py
|
||||
from .basisu_wasm import *
|
||||
|
||||
# === Load WASM ===
|
||||
codec = BasisuWasm("basisu_py/wasm/basisu_module_st.wasm")
|
||||
codec.load()
|
||||
|
||||
print("Version =", codec.version())
|
||||
|
||||
# === Build test image ===
|
||||
W, H = 256, 256
|
||||
BYTES_PER_PIXEL = 4
|
||||
pitch = W * BYTES_PER_PIXEL
|
||||
|
||||
img = bytearray(W * H * 4)
|
||||
|
||||
for y in range(H):
|
||||
for x in range(W):
|
||||
i = (y * W + x) * 4
|
||||
img[i + 0] = x & 0xFF # R
|
||||
img[i + 1] = y & 0xFF # G
|
||||
img[i + 2] = (x ^ y) & 0xFF # B
|
||||
img[i + 3] = 255 # A
|
||||
|
||||
# === Upload image to WASM memory ===
|
||||
img_ptr = codec.alloc(len(img))
|
||||
codec.write_bytes(img_ptr, img)
|
||||
|
||||
# === Create comp_params ===
|
||||
params = codec.new_params()
|
||||
|
||||
# === Set image into comp_params ===
|
||||
ok = codec.set_image_rgba32(params, 0, img_ptr, W, H, pitch)
|
||||
print("Set image:", ok)
|
||||
|
||||
# === Compress ===
|
||||
ok = codec.compress(
|
||||
params,
|
||||
tex_format=BasisTexFormat.cUASTC_LDR_4x4,
|
||||
quality=100,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT | BasisFlags.SRGB,
|
||||
rdo_quality=0.0
|
||||
)
|
||||
print("Compress result:", ok)
|
||||
|
||||
# === Retrieve compressed blob ===
|
||||
ofs = codec.get_comp_data_ofs(params)
|
||||
size = codec.get_comp_data_size(params)
|
||||
print("Output size =", size)
|
||||
|
||||
comp_data = codec.read_bytes(ofs, size)
|
||||
print("First 16 bytes:", comp_data[:16])
|
||||
|
||||
# === Save to KTX2 ===
|
||||
with open("test.ktx2", "wb") as f:
|
||||
f.write(comp_data)
|
||||
|
||||
print("File written: test.ktx2")
|
||||
|
||||
# === Cleanup ===
|
||||
codec.delete_params(params)
|
||||
codec.free(img_ptr)
|
||||
76
python/lowlevel_test_wasm/compress_test_float.py
Normal file
76
python/lowlevel_test_wasm/compress_test_float.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# compress_test_float.py
|
||||
|
||||
from .basisu_wasm import BasisuWasm, BasisTexFormat, BasisEffort, BasisFlags, BasisQuality
|
||||
import struct # for packing floats
|
||||
|
||||
# === Load WASM ===
|
||||
codec = BasisuWasm("basisu_py/wasm/basisu_module_st.wasm")
|
||||
codec.load()
|
||||
|
||||
print("Version =", codec.version())
|
||||
|
||||
# === Build a 256x256 FLOAT RGBA image ===
|
||||
W, H = 256, 256
|
||||
BYTES_PER_PIXEL = 16 # float32 * 4
|
||||
pitch = W * BYTES_PER_PIXEL
|
||||
|
||||
# Float image stored as bytearray of packed floats
|
||||
img = bytearray(W * H * BYTES_PER_PIXEL)
|
||||
|
||||
for y in range(H):
|
||||
for x in range(W):
|
||||
# Create some float HDR gradient pattern
|
||||
r = float(x) / W # 0.0 ? 1.0
|
||||
g = float(y) / H # 0.0 ? 1.0
|
||||
b = float(x ^ y) / 255.0 # quirky pattern
|
||||
a = 1.0
|
||||
|
||||
i = (y * W + x) * 4
|
||||
|
||||
# pack into img bytearray
|
||||
struct.pack_into("ffff", img, i*4, r, g, b, a)
|
||||
|
||||
print("Created FLOAT RGBA image.")
|
||||
|
||||
# === Upload to WASM memory ===
|
||||
img_ptr = codec.alloc(len(img))
|
||||
codec.write_bytes(img_ptr, img)
|
||||
print("Copied float image into WASM heap at", img_ptr)
|
||||
|
||||
# === Create params ===
|
||||
params = codec.new_params()
|
||||
|
||||
# === Set FLOAT RGBA image ===
|
||||
ok = codec.set_image_float_rgba(params, 0, img_ptr, W, H, pitch)
|
||||
print("Set float RGBA:", ok)
|
||||
|
||||
# === Compress using HDR UASTC 4x4 ===
|
||||
ok = codec.compress(
|
||||
params,
|
||||
tex_format=BasisTexFormat.cUASTC_HDR_4x4,
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT | BasisFlags.REC2020, # optional: HDR color space
|
||||
rdo_quality=0.0
|
||||
)
|
||||
|
||||
print("Compression result:", ok)
|
||||
|
||||
# === Retrieve compressed HDR KTX2 ===
|
||||
ofs = codec.get_comp_data_ofs(params)
|
||||
size = codec.get_comp_data_size(params)
|
||||
|
||||
print("Output size =", size)
|
||||
data = codec.read_bytes(ofs, size)
|
||||
|
||||
print("First 16 bytes:", data[:16])
|
||||
|
||||
# === Save to test_hdr.ktx2 ===
|
||||
with open("test_hdr.ktx2", "wb") as f:
|
||||
f.write(data)
|
||||
|
||||
print("Wrote test_hdr.ktx2")
|
||||
|
||||
# === Cleanup ===
|
||||
codec.delete_params(params)
|
||||
codec.free(img_ptr)
|
||||
44
python/pyproject.toml
Normal file
44
python/pyproject.toml
Normal file
@@ -0,0 +1,44 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=65", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "basisu-py"
|
||||
version = "0.2.0"
|
||||
description = "Python bindings for Basis Universal encoder/transcoder v2.x with native + WASM backend"
|
||||
authors = [
|
||||
{ name = "Binomial LLC", email = "stephanie@binomial.info" }
|
||||
]
|
||||
license = { text = "Apache 2.0" }
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
|
||||
dependencies = [
|
||||
"numpy",
|
||||
"Pillow",
|
||||
"imageio>=2.22",
|
||||
"wasmtime",
|
||||
]
|
||||
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: C++",
|
||||
"Operating System :: OS Independent",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
]
|
||||
|
||||
[tool.setuptools]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
include = ["basisu_py*"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
basisu_py = [
|
||||
"*.so",
|
||||
"*.pyd",
|
||||
"*.py",
|
||||
"wasm/*.wasm",
|
||||
"wasm/*.py",
|
||||
"README.md",
|
||||
]
|
||||
1
python/tests/__init__.py
Normal file
1
python/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# python/tests/__init__.py
|
||||
70
python/tests/test_backend_loading.py
Normal file
70
python/tests/test_backend_loading.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
from basisu_py.codec import Encoder, EncoderBackend
|
||||
from basisu_py.constants import BasisTexFormat
|
||||
|
||||
print("========== BACKEND LOADING TEST ==========\n")
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# 1. Test native backend (if available)
|
||||
# --------------------------------------------------------------
|
||||
print("Testing native backend...")
|
||||
|
||||
try:
|
||||
enc_native = Encoder(backend=EncoderBackend.NATIVE)
|
||||
print(" [OK] Native backend loaded")
|
||||
except Exception as e:
|
||||
print(" [FAIL] Native backend failed to load:", e)
|
||||
enc_native = None
|
||||
|
||||
# If native loaded, test very basic functionality
|
||||
if enc_native:
|
||||
try:
|
||||
version = enc_native._native.get_version()
|
||||
print(f" Native get_version() ? {version}")
|
||||
|
||||
ptr = enc_native._native.alloc(16)
|
||||
print(f" Native alloc() returned ptr = {ptr}")
|
||||
|
||||
enc_native._native.free(ptr)
|
||||
print(f" Native free() OK")
|
||||
|
||||
print(" [OK] Native basic operations working.\n")
|
||||
except Exception as e:
|
||||
print(" [FAIL] Native operations error:", e)
|
||||
else:
|
||||
print(" Skipping native basic operations.\n")
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# 2. Test WASM backend
|
||||
# --------------------------------------------------------------
|
||||
print("\nTesting WASM backend...")
|
||||
|
||||
try:
|
||||
enc_wasm = Encoder(backend=EncoderBackend.WASM)
|
||||
print(" [OK] WASM backend loaded")
|
||||
except Exception as e:
|
||||
print(" [FAIL] WASM backend failed to load:", e)
|
||||
enc_wasm = None
|
||||
|
||||
# If WASM loaded, test basic methods
|
||||
if enc_wasm and enc_wasm._wasm is not None:
|
||||
try:
|
||||
version = enc_wasm._wasm.get_version()
|
||||
print(f" WASM get_version() ? {version}")
|
||||
|
||||
ptr = enc_wasm._wasm.alloc(16)
|
||||
print(f" WASM alloc() returned ptr = {ptr}")
|
||||
|
||||
enc_wasm._wasm.free(ptr)
|
||||
print(f" WASM free() OK")
|
||||
|
||||
print(" [OK] WASM basic operations working.\n")
|
||||
except Exception as e:
|
||||
print(" [FAIL] WASM operations error:", e)
|
||||
else:
|
||||
print(" Skipping WASM basic operations.\n")
|
||||
|
||||
print("\n========== DONE ==========\n")
|
||||
7
python/tests/test_basic_backend_selection.py
Normal file
7
python/tests/test_basic_backend_selection.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from basisu_py import Encoder
|
||||
|
||||
enc = Encoder() # AUTO mode
|
||||
print("Encoder backend:", enc.backend)
|
||||
print("Native loaded:", enc._native is not None)
|
||||
print("WASM loaded:", enc._wasm is not None)
|
||||
print("Version:", enc._native.get_version() if enc._native else enc._wasm.get_version())
|
||||
19
python/tests/test_basic_decode.py
Normal file
19
python/tests/test_basic_decode.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from basisu_py import Transcoder
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
# Load input file
|
||||
with open("test.ktx2", "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
# Decode (AUTO backend)
|
||||
t = Transcoder()
|
||||
rgba = t.decode_rgba(data) # returns HxWx4 uint8 NumPy array
|
||||
|
||||
print("Decoded:", rgba.shape, rgba.dtype)
|
||||
|
||||
# Convert to Pillow Image and save
|
||||
img = Image.fromarray(rgba, mode="RGBA")
|
||||
img.save("decoded.png")
|
||||
|
||||
print("Wrote decoded.png")
|
||||
10
python/tests/test_basic_transcode.py
Normal file
10
python/tests/test_basic_transcode.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from basisu_py import Transcoder
|
||||
|
||||
with open("test.ktx2", "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
t = Transcoder() # AUTO backend
|
||||
img = t.decode_rgba(data)
|
||||
|
||||
print("Decoded shape:", img.shape)
|
||||
print("dtype:", img.dtype)
|
||||
6
python/tests/test_basic_wasm_selection.py
Normal file
6
python/tests/test_basic_wasm_selection.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from basisu_py import Transcoder
|
||||
from basisu_py.transcoder import TranscoderBackend
|
||||
|
||||
t = Transcoder(backend=TranscoderBackend.WASM)
|
||||
print("Backend:", t.backend_name)
|
||||
t.decode_rgba(open("test.ktx2","rb").read())
|
||||
82
python/tests/test_compress_swirl.py
Normal file
82
python/tests/test_compress_swirl.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from math import sin, cos, atan2, hypot
|
||||
|
||||
from basisu_py.codec import Encoder, EncoderBackend
|
||||
from basisu_py.constants import BasisTexFormat, BasisQuality, BasisEffort, BasisFlags
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Procedural swirl pattern (RGBA8)
|
||||
# --------------------------------------------------------------
|
||||
def make_swirl_image(w=256, h=256):
|
||||
arr = np.zeros((h, w, 4), dtype=np.uint8)
|
||||
|
||||
cx = w / 2.0
|
||||
cy = h / 2.0
|
||||
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
dx = x - cx
|
||||
dy = y - cy
|
||||
|
||||
dist = hypot(dx, dy)
|
||||
angle = atan2(dy, dx)
|
||||
|
||||
r = int((sin(dist * 0.15) * 0.5 + 0.5) * 255)
|
||||
g = int((sin(angle * 3.0) * 0.5 + 0.5) * 255)
|
||||
b = int((cos(dist * 0.10 + angle * 2.0) * 0.5 + 0.5) * 255)
|
||||
|
||||
arr[y, x] = (r, g, b, 255)
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Test encode using a given backend
|
||||
# --------------------------------------------------------------
|
||||
def compress_swirl(backend, outfile):
|
||||
print(f"\n========== Testing {backend} backend ==========")
|
||||
|
||||
# Build procedural image
|
||||
swirl = make_swirl_image(256, 256)
|
||||
print("Generated swirl image:", swirl.shape)
|
||||
|
||||
# Create encoder
|
||||
enc = Encoder(backend=backend)
|
||||
|
||||
# Compress
|
||||
blob = enc.compress(
|
||||
swirl,
|
||||
format=BasisTexFormat.cUASTC_LDR_4x4,
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT | BasisFlags.SRGB
|
||||
)
|
||||
|
||||
print(f"Compressed blob size: {len(blob)} bytes")
|
||||
|
||||
# Save output
|
||||
with open(outfile, "wb") as f:
|
||||
f.write(blob)
|
||||
|
||||
print(f"Wrote: {outfile}")
|
||||
print("==============================================")
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Main
|
||||
# --------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
# Test native backend
|
||||
try:
|
||||
compress_swirl(EncoderBackend.NATIVE, "swirl_native.ktx2")
|
||||
except Exception as e:
|
||||
print("Native backend ERROR:", e)
|
||||
|
||||
# Test WASM backend
|
||||
try:
|
||||
compress_swirl(EncoderBackend.WASM, "swirl_wasm.ktx2")
|
||||
except Exception as e:
|
||||
print("WASM backend ERROR:", e)
|
||||
75
python/tests/test_compress_swirl_hdr.py
Normal file
75
python/tests/test_compress_swirl_hdr.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
import numpy as np
|
||||
from math import sin, cos, atan2, hypot
|
||||
from basisu_py.codec import Encoder, EncoderBackend
|
||||
from basisu_py.constants import BasisTexFormat, BasisQuality, BasisEffort, BasisFlags
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Procedural HDR swirl pattern (float32 RGBA)
|
||||
# --------------------------------------------------------------
|
||||
def make_hdr_swirl_image(w=256, h=256):
|
||||
arr = np.zeros((h, w, 4), dtype=np.float32)
|
||||
|
||||
cx = w / 2.0
|
||||
cy = h / 2.0
|
||||
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
dx = x - cx
|
||||
dy = y - cy
|
||||
dist = hypot(dx, dy)
|
||||
angle = atan2(dy, dx)
|
||||
|
||||
r = (sin(dist * 0.15) * 0.5 + 0.5)
|
||||
g = (sin(angle * 3.0) * 0.5 + 0.5)
|
||||
b = (cos(dist * 0.10 + angle * 2.0) * 0.5 + 0.5)
|
||||
|
||||
arr[y, x] = (r, g, b, 1.0) # full alpha
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Test encode using a given backend
|
||||
# --------------------------------------------------------------
|
||||
def compress_hdr_swirl(backend, outfile):
|
||||
print(f"\n========== Testing HDR {backend} backend ==========")
|
||||
|
||||
hdr = make_hdr_swirl_image(256, 256)
|
||||
print("Generated HDR swirl image:", hdr.shape, hdr.dtype)
|
||||
|
||||
enc = Encoder(backend=backend)
|
||||
|
||||
blob = enc.compress(
|
||||
hdr,
|
||||
format=-1, # auto-select HDR (UASTC_HDR_4x4)
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT | BasisFlags.SRGB
|
||||
)
|
||||
|
||||
print(f"Compressed blob size: {len(blob)} bytes")
|
||||
|
||||
with open(outfile, "wb") as f:
|
||||
f.write(blob)
|
||||
|
||||
print(f"Wrote: {outfile}")
|
||||
print("==============================================")
|
||||
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Main
|
||||
# --------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
# Native backend
|
||||
try:
|
||||
compress_hdr_swirl(EncoderBackend.NATIVE, "hdr_swirl_native.ktx2")
|
||||
except Exception as e:
|
||||
print("Native HDR backend ERROR:", e)
|
||||
|
||||
# WASM backend
|
||||
try:
|
||||
compress_hdr_swirl(EncoderBackend.WASM, "hdr_swirl_wasm.ktx2")
|
||||
except Exception as e:
|
||||
print("WASM HDR backend ERROR:", e)
|
||||
18
python/tests/test_transcoder_astc.py
Normal file
18
python/tests/test_transcoder_astc.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from basisu_py import Transcoder
|
||||
from astc_writer import write_astc_file
|
||||
|
||||
# Load a .ktx2
|
||||
data = open("input.ktx2", "rb").read()
|
||||
t = Transcoder()
|
||||
|
||||
# Transcode to ASTC
|
||||
h = t.open(data)
|
||||
bw = t.get_block_width(h) # or basis_get_block_width(astc_tfmt)
|
||||
bh = t.get_block_height(h)
|
||||
tfmt = t.basis_get_transcoder_texture_format_from_basis_tex_format(
|
||||
t.get_basis_tex_format(h)
|
||||
)
|
||||
|
||||
blocks = t.transcode_tfmt(data, tfmt)
|
||||
write_astc_file("output.astc", blocks, bw, bh, t.get_width(h), t.get_height(h))
|
||||
t.close(h)
|
||||
72
python/tests/test_transcoder_backend_loading.py
Normal file
72
python/tests/test_transcoder_backend_loading.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
from basisu_py.transcoder import Transcoder, TranscoderBackend
|
||||
from basisu_py.constants import BasisTexFormat
|
||||
|
||||
print("========== TESTING TRANSCODER BACKENDS ==========\n")
|
||||
|
||||
# Load some test data (ensure test.ktx2 exists)
|
||||
try:
|
||||
test_data = open("test.ktx2", "rb").read()
|
||||
print("[INFO] Loaded test.ktx2")
|
||||
except FileNotFoundError:
|
||||
print("[ERROR] test.ktx2 not found. Create one first via encoder tests.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# 1. Test NATIVE backend
|
||||
# -------------------------------------------------------------------
|
||||
print("\n--- Testing NATIVE transcoder backend ---")
|
||||
|
||||
try:
|
||||
t_native = Transcoder(TranscoderBackend.NATIVE)
|
||||
print(" [OK] Native backend loaded")
|
||||
|
||||
version = t_native.get_version()
|
||||
print(f" Native get_version() = {version}")
|
||||
|
||||
# Open KTX2
|
||||
raw = t_native.open(test_data)
|
||||
print(" [OK] Opened KTX2 (native)")
|
||||
|
||||
# Query some basic properties
|
||||
print(" Width :", t_native.get_width(raw))
|
||||
print(" Height:", t_native.get_height(raw))
|
||||
print(" Levels:", t_native.get_levels(raw))
|
||||
|
||||
# Cleanup
|
||||
t_native.close(raw)
|
||||
print(" [OK] Native transcoder basic operations working.")
|
||||
|
||||
except Exception as e:
|
||||
print(" [FAIL] Native transcoder error:", e)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# 2. Test WASM backend
|
||||
# -------------------------------------------------------------------
|
||||
print("\n--- Testing WASM transcoder backend ---")
|
||||
|
||||
try:
|
||||
t_wasm = Transcoder(TranscoderBackend.WASM)
|
||||
print(" [OK] WASM backend loaded")
|
||||
|
||||
version = t_wasm.get_version()
|
||||
print(f" WASM get_version() = {version}")
|
||||
|
||||
raw = t_wasm.open(test_data)
|
||||
print(" [OK] Opened KTX2 (wasm)")
|
||||
|
||||
print(" Width :", t_wasm.get_width(raw))
|
||||
print(" Height:", t_wasm.get_height(raw))
|
||||
print(" Levels:", t_wasm.get_levels(raw))
|
||||
|
||||
t_wasm.close(raw)
|
||||
print(" [OK] WASM transcoder basic operations working.")
|
||||
|
||||
except Exception as e:
|
||||
print(" [FAIL] WASM transcoder error:", e)
|
||||
|
||||
|
||||
print("\n========== DONE ==========")
|
||||
154
python/tests/test_transcoder_end_to_end.py
Normal file
154
python/tests/test_transcoder_end_to_end.py
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Full end-to-end transcoder test with automatic fallback.
|
||||
|
||||
- Generates a swirl image
|
||||
- Compresses it using native OR WASM (AUTO mode)
|
||||
- Writes test.ktx2
|
||||
- Decodes it using whichever backends are available:
|
||||
* AUTO (native if present, otherwise WASM)
|
||||
* Native (if available)
|
||||
* WASM (if available)
|
||||
- Produces PNG outputs for all successful backends
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from math import sin, cos, atan2, hypot
|
||||
from PIL import Image
|
||||
import sys
|
||||
|
||||
from basisu_py.codec import Encoder, EncoderBackend
|
||||
from basisu_py.transcoder import Transcoder, TranscoderBackend
|
||||
from basisu_py.constants import (
|
||||
BasisTexFormat,
|
||||
BasisQuality,
|
||||
BasisEffort,
|
||||
BasisFlags,
|
||||
)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Create an RGBA swirl test image
|
||||
# -------------------------------------------------------------------
|
||||
def make_swirl(w=256, h=256):
|
||||
arr = np.zeros((h, w, 4), dtype=np.uint8)
|
||||
|
||||
cx, cy = w / 2.0, h / 2.0
|
||||
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
dx, dy = x - cx, y - cy
|
||||
dist = hypot(dx, dy)
|
||||
angle = atan2(dy, dx)
|
||||
|
||||
r = int((sin(dist * 0.15) * 0.5 + 0.5) * 255)
|
||||
g = int((sin(angle * 3.0) * 0.5 + 0.5) * 255)
|
||||
b = int((cos(dist * 0.10 + angle * 2.0) * 0.5 + 0.5) * 255)
|
||||
|
||||
arr[y, x] = (r, g, b, 255)
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Try loading transcoder with a backend, return (success, transcoder)
|
||||
# -------------------------------------------------------------------
|
||||
def try_transcoder(backend):
|
||||
try:
|
||||
t = Transcoder(backend)
|
||||
print(f"[OK] Loaded transcoder backend '{backend}' ({t.backend_name})")
|
||||
return True, t
|
||||
except Exception as e:
|
||||
print(f"[SKIP] Backend '{backend}' unavailable:", e)
|
||||
return False, None
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Try loading encoder with a backend, return blob or None
|
||||
# -------------------------------------------------------------------
|
||||
def try_encoder(backend, img):
|
||||
try:
|
||||
enc = Encoder(backend)
|
||||
print(f"[OK] Loaded encoder backend '{backend}' ({enc.backend_name})")
|
||||
except Exception as e:
|
||||
print(f"[SKIP] Encoder backend '{backend}' unavailable:", e)
|
||||
return None
|
||||
|
||||
try:
|
||||
print(f"[Test] Compressing swirl -> KTX2 using {enc.backend_name}...")
|
||||
blob = enc.compress(
|
||||
img,
|
||||
format=-1,
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT | BasisFlags.SRGB
|
||||
)
|
||||
return blob
|
||||
except Exception as e:
|
||||
print(f"[FAIL] Compression failed on backend '{backend}':", e)
|
||||
return None
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Decode blob with a given transcoder
|
||||
# -------------------------------------------------------------------
|
||||
def decode_with_backend(name, t, blob):
|
||||
try:
|
||||
rgba = t.decode_rgba(blob)
|
||||
outname = f"decoded_{name}.png"
|
||||
Image.fromarray(rgba, mode="RGBA").save(outname)
|
||||
print(f" --> {name}: decoded successfully, wrote {outname}")
|
||||
except Exception as e:
|
||||
print(f" [FAIL] decode_rgba on backend '{name}':", e)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Main test
|
||||
# -------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
print("========== BasisU End-to-End Compression & Transcoding Test ==========")
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Generate swirl test
|
||||
# -------------------------------------------------------
|
||||
img = make_swirl(256, 256)
|
||||
print("[Test] Generated swirl:", img.shape)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Try AUTO encoder (native if available, else WASM)
|
||||
# -------------------------------------------------------
|
||||
blob = try_encoder(EncoderBackend.AUTO, img)
|
||||
if blob is None:
|
||||
print("[FAIL] Could not encode using AUTO backend; aborting.")
|
||||
sys.exit(1)
|
||||
|
||||
# Save test.ktx2
|
||||
with open("test.ktx2", "wb") as f:
|
||||
f.write(blob)
|
||||
print("[Test] Wrote: test.ktx2")
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Test transcoding using AUTO
|
||||
# -------------------------------------------------------
|
||||
print("\n[Test] Decoding via AUTO backend...")
|
||||
ok_auto, t_auto = try_transcoder(TranscoderBackend.AUTO)
|
||||
if ok_auto:
|
||||
decode_with_backend("auto", t_auto, blob)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Test NATIVE explicitly (if available)
|
||||
# -------------------------------------------------------
|
||||
print("\n[Test] Decoding via NATIVE backend...")
|
||||
ok_native, t_native = try_transcoder(TranscoderBackend.NATIVE)
|
||||
if ok_native:
|
||||
decode_with_backend("native", t_native, blob)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Test WASM explicitly (if available)
|
||||
# -------------------------------------------------------
|
||||
print("\n[Test] Decoding via WASM backend...")
|
||||
ok_wasm, t_wasm = try_transcoder(TranscoderBackend.WASM)
|
||||
if ok_wasm:
|
||||
decode_with_backend("wasm", t_wasm, blob)
|
||||
|
||||
print("\n========== DONE ==========")
|
||||
175
python/tests/test_transcoder_end_to_end_hdr.py
Normal file
175
python/tests/test_transcoder_end_to_end_hdr.py
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
HDR End-to-End Compression & Transcoding Test
|
||||
Works on all platforms:
|
||||
- native if available
|
||||
- WASM fallback otherwise
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from math import sin, cos, atan2, hypot
|
||||
from PIL import Image
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
import imageio.v3 as iio
|
||||
|
||||
from basisu_py.codec import Encoder, EncoderBackend
|
||||
from basisu_py.transcoder import Transcoder, TranscoderBackend
|
||||
from basisu_py.constants import (
|
||||
BasisTexFormat,
|
||||
BasisQuality,
|
||||
BasisEffort,
|
||||
BasisFlags
|
||||
)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Save EXR using TIFF temp + oiiotool (as required)
|
||||
# -------------------------------------------------------------------
|
||||
def save_exr(path, rgba32f):
|
||||
"""
|
||||
Save float32 RGBA as EXR if possible.
|
||||
If oiiotool is not available, save TIFF instead (Windows-safe).
|
||||
"""
|
||||
import numpy as np
|
||||
import imageio.v3 as iio
|
||||
import subprocess, tempfile, os
|
||||
|
||||
# Write temp TIFF
|
||||
with tempfile.NamedTemporaryFile(suffix=".tiff", delete=False) as tmp:
|
||||
temp_path = tmp.name
|
||||
|
||||
iio.imwrite(temp_path, rgba32f.astype(np.float32))
|
||||
|
||||
# Try EXR via oiiotool
|
||||
try:
|
||||
subprocess.run(["oiiotool", temp_path, "-o", path], check=True)
|
||||
os.remove(temp_path)
|
||||
print(" Wrote EXR:", path)
|
||||
return
|
||||
|
||||
except Exception:
|
||||
# --- FALLBACK: save TIFF ---
|
||||
fallback_path = path + ".tiff"
|
||||
|
||||
# Windows cannot overwrite files via rename(), so remove first
|
||||
if os.path.exists(fallback_path):
|
||||
os.remove(fallback_path)
|
||||
|
||||
# os.replace() always overwrites
|
||||
os.replace(temp_path, fallback_path)
|
||||
|
||||
print(" [Fallback] Wrote TIFF instead:", fallback_path)
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Generate HDR swirl image (float32)
|
||||
# -------------------------------------------------------------------
|
||||
def make_swirl_hdr(w=256, h=256):
|
||||
arr = np.zeros((h, w, 4), dtype=np.float32)
|
||||
cx, cy = w / 2.0, h / 2.0
|
||||
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
dx, dy = x - cx, y - cy
|
||||
dist = hypot(dx, dy)
|
||||
angle = atan2(dy, dx)
|
||||
|
||||
# HDR values range up to about 4.0
|
||||
r = (sin(dist * 0.08) * 0.5 + 0.5) * 4.0
|
||||
g = (sin(angle * 2.0) * 0.5 + 0.5) * 4.0
|
||||
b = (cos(dist * 0.06 + angle * 1.5) * 0.5 + 0.5) * 4.0
|
||||
|
||||
arr[y, x] = (r, g, b, 1.0)
|
||||
|
||||
return arr
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Try loading a transcoder backend
|
||||
# -------------------------------------------------------------------
|
||||
def try_transcoder(name, backend):
|
||||
try:
|
||||
t = Transcoder(backend)
|
||||
print(f"[OK] Loaded transcoder backend '{name}' ({t.backend_name})")
|
||||
return t
|
||||
except Exception as e:
|
||||
print(f"[SKIP] Backend '{name}' unavailable:", e)
|
||||
return None
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# MAIN
|
||||
# -------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
print("========== HDR End-to-End Compression & Transcoding Test ==========")
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Create HDR test image
|
||||
# -------------------------------------------------------
|
||||
img_hdr = make_swirl_hdr(256, 256)
|
||||
print("[HDR] swirl:", img_hdr.shape, img_hdr.dtype)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# ENCODE using AUTO backend (native ? or WASM)
|
||||
# -------------------------------------------------------
|
||||
try:
|
||||
enc = Encoder(EncoderBackend.AUTO)
|
||||
print(f"[HDR] Encoder backend = {enc.backend_name}")
|
||||
except Exception as e:
|
||||
print("[FATAL] Could not create encoder:", e)
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("[HDR] Compressing HDR swirl -> test_hdr.ktx2...")
|
||||
ktx2_blob = enc.compress(
|
||||
img_hdr,
|
||||
format=-1, # auto-select HDR format
|
||||
quality=BasisQuality.MAX,
|
||||
effort=BasisEffort.DEFAULT,
|
||||
flags=BasisFlags.KTX2_OUTPUT
|
||||
)
|
||||
print(" KTX2 size:", len(ktx2_blob))
|
||||
open("test_hdr.ktx2", "wb").write(ktx2_blob)
|
||||
print(" Wrote test_hdr.ktx2")
|
||||
except Exception as e:
|
||||
print("[FATAL] Encoding failed:", e)
|
||||
exit(1)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# DECODE using AUTO (native ? or WASM)
|
||||
# -------------------------------------------------------
|
||||
t_auto = try_transcoder("AUTO", TranscoderBackend.AUTO)
|
||||
if t_auto:
|
||||
try:
|
||||
hdr = t_auto.decode_rgba_hdr(ktx2_blob)
|
||||
print(" AUTO decoded:", hdr.shape, hdr.dtype)
|
||||
save_exr("decoded_auto_hdr.exr", hdr)
|
||||
except Exception as e:
|
||||
print(" [FAIL] AUTO decode failed:", e)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# DECODE using NATIVE if available
|
||||
# -------------------------------------------------------
|
||||
t_native = try_transcoder("NATIVE", TranscoderBackend.NATIVE)
|
||||
if t_native:
|
||||
try:
|
||||
hdr_n = t_native.decode_rgba_hdr(ktx2_blob)
|
||||
print(" Native decoded:", hdr_n.shape, hdr_n.dtype)
|
||||
save_exr("decoded_native_hdr.exr", hdr_n)
|
||||
except Exception as e:
|
||||
print(" [FAIL] Native decode failed:", e)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# DECODE using WASM if available
|
||||
# -------------------------------------------------------
|
||||
t_wasm = try_transcoder("WASM", TranscoderBackend.WASM)
|
||||
if t_wasm:
|
||||
try:
|
||||
hdr_w = t_wasm.decode_rgba_hdr(ktx2_blob)
|
||||
print(" WASM decoded:", hdr_w.shape, hdr_w.dtype)
|
||||
save_exr("decoded_wasm_hdr.exr", hdr_w)
|
||||
except Exception as e:
|
||||
print(" [FAIL] WASM decode failed:", e)
|
||||
|
||||
print("\n========== DONE ==========")
|
||||
190
python/tests/test_transcoder_helpers.py
Normal file
190
python/tests/test_transcoder_helpers.py
Normal file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
from basisu_py.transcoder import Transcoder, TranscoderBackend
|
||||
from basisu_py.constants import BasisTexFormat, TranscoderTextureFormat
|
||||
|
||||
print("========== TESTING TRANSCODER HELPERS & METADATA ==========\n")
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Load test KTX2 file
|
||||
# ----------------------------------------------------------------------------
|
||||
try:
|
||||
ktx2_bytes = open("test.ktx2", "rb").read()
|
||||
print("[INFO] Loaded test.ktx2")
|
||||
except FileNotFoundError:
|
||||
print("[ERROR] test.ktx2 not found. Run encoder tests first.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Utility: run helper tests on a given backend
|
||||
# ----------------------------------------------------------------------------
|
||||
def test_backend(name, backend):
|
||||
print(f"\n=== Testing {name} backend ===")
|
||||
|
||||
try:
|
||||
t = Transcoder(backend)
|
||||
except Exception as e:
|
||||
print(f"[FAIL] Could not initialize {name} backend:", e)
|
||||
return
|
||||
|
||||
print(f"[OK] {name} backend loaded")
|
||||
|
||||
# Version
|
||||
try:
|
||||
ver = t.get_version()
|
||||
print(f" version = {ver}")
|
||||
except Exception as e:
|
||||
print(" [FAIL] get_version() error:", e)
|
||||
return
|
||||
|
||||
# enable_debug_printf
|
||||
try:
|
||||
t.enable_debug_printf(True)
|
||||
except Exception as e:
|
||||
print(" [FAIL] enable_debug_printf() failed")
|
||||
return
|
||||
|
||||
# Open KTX2
|
||||
try:
|
||||
raw = t.open(ktx2_bytes)
|
||||
print(" [OK] open() success")
|
||||
except Exception as e:
|
||||
print(" [FAIL] open() failed:", e)
|
||||
return
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# KTX2 top-level metadata
|
||||
# ----------------------------------------------------------------------
|
||||
try:
|
||||
w = t.get_width(raw)
|
||||
h = t.get_height(raw)
|
||||
lv = t.get_levels(raw)
|
||||
fc = t.get_faces(raw)
|
||||
la = t.get_layers(raw)
|
||||
fmt = t.get_basis_tex_format(raw)
|
||||
|
||||
print(f" Width = {w}")
|
||||
print(f" Height = {h}")
|
||||
print(f" Levels = {lv}")
|
||||
print(f" Faces = {fc}")
|
||||
print(f" Layers = {la}")
|
||||
print(f" basis_tex_format = {fmt}")
|
||||
print(f" has_alpha = {t.has_alpha(raw)}")
|
||||
print(f" is_hdr = {t.is_hdr(raw)}")
|
||||
print(f" is_ldr = {t.is_ldr(raw)}")
|
||||
print(f" is_srgb = {t.is_srgb(raw)}")
|
||||
print(f" is_etc1s = {t.is_etc1s(raw)}")
|
||||
print(f" is_uastc_ldr_4x4 = {t.is_uastc_ldr_4x4(raw)}")
|
||||
print(f" is_xuastc_ldr = {t.is_xuastc_ldr(raw)}")
|
||||
print(f" is_astc_ldr = {t.is_astc_ldr(raw)}")
|
||||
print(f" block dims = {t.get_block_width(raw)} x {t.get_block_height(raw)}")
|
||||
|
||||
except Exception as e:
|
||||
print(" [FAIL] get_* metadata error:", e)
|
||||
t.close(raw)
|
||||
return
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Per-level metadata for each mipmap
|
||||
# ----------------------------------------------------------------------
|
||||
print("\n -- Level Metadata --")
|
||||
for level in range(lv):
|
||||
try:
|
||||
ow = t.get_level_orig_width(raw, level)
|
||||
oh = t.get_level_orig_height(raw, level)
|
||||
nbx = t.get_level_num_blocks_x(raw, level)
|
||||
nby = t.get_level_num_blocks_y(raw, level)
|
||||
tb = t.get_level_total_blocks(raw, level)
|
||||
af = t.get_level_alpha_flag(raw, level)
|
||||
ff = t.get_level_iframe_flag(raw, level)
|
||||
|
||||
print(f" Level {level}: orig={ow}x{oh}, blocks={nbx}x{nby}, total={tb}, alpha={af}, iframe={ff}")
|
||||
except Exception as e:
|
||||
print(f" [FAIL] Level {level} metadata error:", e)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Test ALL basis_tex_format helpers on the file's format
|
||||
# ----------------------------------------------------------------------
|
||||
print("\n -- basis_tex_format helpers --")
|
||||
|
||||
try:
|
||||
print(f" is_xuastc_ldr = {t.basis_tex_format_is_xuastc_ldr(fmt)}")
|
||||
print(f" is_astc_ldr = {t.basis_tex_format_is_astc_ldr(fmt)}")
|
||||
print(f" block W/H = {t.basis_tex_format_get_block_width(fmt)} x "
|
||||
f"{t.basis_tex_format_get_block_height(fmt)}")
|
||||
print(f" is_hdr = {t.basis_tex_format_is_hdr(fmt)}")
|
||||
print(f" is_ldr = {t.basis_tex_format_is_ldr(fmt)}")
|
||||
except Exception as e:
|
||||
print(" [FAIL] basis_tex_format_* error:", e)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Test transcoder_texture_format helpers using a few common formats
|
||||
# ----------------------------------------------------------------------
|
||||
print("\n -- transcoder_texture_format helpers --")
|
||||
|
||||
test_formats = [
|
||||
TranscoderTextureFormat.TF_RGBA32,
|
||||
TranscoderTextureFormat.TF_RGBA_HALF,
|
||||
TranscoderTextureFormat.TF_BC7_RGBA,
|
||||
TranscoderTextureFormat.TF_ETC1_RGB,
|
||||
]
|
||||
|
||||
for tfmt in test_formats:
|
||||
try:
|
||||
print(f" Format {tfmt}: hdr={t.basis_transcoder_format_is_hdr(tfmt)}, "
|
||||
f"ldr={t.basis_transcoder_format_is_ldr(tfmt)}, "
|
||||
f"has_alpha={t.basis_transcoder_format_has_alpha(tfmt)}, "
|
||||
f"uncompressed={t.basis_transcoder_format_is_uncompressed(tfmt)}, "
|
||||
f"bytes/pixel or block={t.basis_get_bytes_per_block_or_pixel(tfmt)}")
|
||||
except Exception as e:
|
||||
print(" [FAIL] transcoder_texture_format_* error:", e)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Compute transcode buffer sizes
|
||||
# ----------------------------------------------------------------------
|
||||
print("\n -- compute_transcoded_image_size_in_bytes --")
|
||||
try:
|
||||
for tfmt in test_formats:
|
||||
sz = t.basis_compute_transcoded_image_size_in_bytes(tfmt, w, h)
|
||||
print(f" Format {tfmt}: size = {sz}")
|
||||
except Exception as e:
|
||||
print(" [FAIL] size computation error:", e)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Decode RGBA (LDR)
|
||||
# ----------------------------------------------------------------------
|
||||
print("\n -- decode_rgba --")
|
||||
try:
|
||||
img_rgba = t.decode_rgba(ktx2_bytes)
|
||||
print(f" decode_rgba: shape={img_rgba.shape}, dtype={img_rgba.dtype}")
|
||||
except Exception as e:
|
||||
print(" [FAIL] decode_rgba error:", e)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Decode HDR if applicable
|
||||
# ----------------------------------------------------------------------
|
||||
if t.is_hdr(raw):
|
||||
print("\n -- decode_rgba_hdr --")
|
||||
try:
|
||||
img_hdr = t.decode_rgba_hdr(ktx2_bytes)
|
||||
print(f" decode_rgba_hdr: shape={img_hdr.shape}, dtype={img_hdr.dtype}")
|
||||
except Exception as e:
|
||||
print(" [FAIL] decode_rgba_hdr error:", e)
|
||||
else:
|
||||
print(" Texture is LDR; skipping decode_rgba_hdr().")
|
||||
|
||||
# Cleanup
|
||||
t.close(raw)
|
||||
print(f"\n=== {name} backend OK ===\n")
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Run tests for both backends
|
||||
# ----------------------------------------------------------------------------
|
||||
test_backend("NATIVE", TranscoderBackend.NATIVE)
|
||||
test_backend("WASM", TranscoderBackend.WASM)
|
||||
|
||||
print("\n========== DONE ==========\n")
|
||||
648
transcoder/basisu_astc_cfgs.inl
Normal file
648
transcoder/basisu_astc_cfgs.inl
Normal file
@@ -0,0 +1,648 @@
|
||||
const uint32_t BU_TOTAL_ASTC_CFGS = 10311;
|
||||
const uint8_t s_astc_cfg_table[BU_TOTAL_ASTC_CFGS*3] = {
|
||||
176,72,0,208,72,0,240,72,0,16,73,0,48,73,0,80,73,0,112,73,0,176,130,0,208,130,0,240,130,0,16,131,0,48,131,0,80,131,0,112,131,0,176,132,0,208,132,0,
|
||||
240,132,0,16,133,0,48,133,0,80,133,0,112,133,0,176,134,0,208,134,0,240,134,0,16,135,0,48,135,0,80,135,0,112,135,0,176,194,0,208,194,0,240,194,0,16,195,0,
|
||||
48,195,0,80,195,0,112,195,0,176,196,0,208,196,0,240,196,0,16,197,0,48,197,0,80,197,0,112,197,0,176,198,0,208,198,0,240,198,0,16,199,0,48,199,0,80,199,0,
|
||||
112,199,0,176,2,1,208,2,1,240,2,1,16,3,1,48,3,1,80,3,1,112,3,1,176,4,1,208,4,1,240,4,1,16,5,1,48,5,1,80,5,1,112,5,1,176,6,1,
|
||||
208,6,1,240,6,1,16,7,1,48,7,1,80,7,1,112,7,1,176,8,1,208,8,1,240,8,1,16,9,1,48,9,1,80,9,1,112,9,1,176,66,1,208,66,1,240,66,1,
|
||||
16,67,1,48,67,1,80,67,1,112,67,1,176,68,1,208,68,1,240,68,1,16,69,1,48,69,1,80,69,1,112,69,1,176,70,1,208,70,1,240,70,1,16,71,1,48,71,1,
|
||||
80,71,1,112,71,1,176,72,1,208,72,1,240,72,1,16,73,1,48,73,1,80,73,1,112,73,1,16,1,2,48,1,2,80,1,2,112,1,2,16,17,2,48,17,2,80,17,2,
|
||||
112,17,2,16,33,2,48,33,2,80,33,2,112,33,2,16,65,2,48,65,2,80,65,2,112,65,2,80,72,2,112,72,2,144,72,2,176,72,2,208,72,2,240,72,2,16,73,2,
|
||||
48,73,2,80,73,2,112,73,2,16,81,2,48,81,2,80,81,2,112,81,2,10,97,2,42,97,2,73,97,2,105,97,2,16,129,2,48,129,2,80,129,2,112,129,2,80,130,2,
|
||||
112,130,2,144,130,2,176,130,2,208,130,2,240,130,2,16,131,2,48,131,2,80,131,2,112,131,2,80,132,2,112,132,2,144,132,2,176,132,2,208,132,2,240,132,2,16,133,2,
|
||||
48,133,2,80,133,2,112,133,2,80,134,2,112,134,2,144,134,2,176,134,2,208,134,2,240,134,2,16,135,2,48,135,2,80,135,2,112,135,2,16,145,2,48,145,2,80,145,2,
|
||||
112,145,2,10,161,2,42,161,2,73,161,2,105,161,2,16,193,2,48,193,2,80,193,2,112,193,2,80,194,2,112,194,2,144,194,2,176,194,2,208,194,2,240,194,2,16,195,2,
|
||||
48,195,2,80,195,2,112,195,2,80,196,2,112,196,2,144,196,2,176,196,2,208,196,2,240,196,2,16,197,2,48,197,2,80,197,2,112,197,2,80,198,2,112,198,2,144,198,2,
|
||||
176,198,2,208,198,2,240,198,2,16,199,2,48,199,2,80,199,2,112,199,2,10,209,2,42,209,2,73,209,2,105,209,2,4,225,2,36,225,2,67,225,2,99,225,2,16,1,3,
|
||||
48,1,3,80,1,3,112,1,3,80,2,3,112,2,3,144,2,3,176,2,3,208,2,3,240,2,3,16,3,3,48,3,3,80,3,3,112,3,3,80,4,3,112,4,3,144,4,3,
|
||||
176,4,3,208,4,3,240,4,3,16,5,3,48,5,3,80,5,3,112,5,3,80,6,3,112,6,3,144,6,3,176,6,3,208,6,3,240,6,3,16,7,3,48,7,3,80,7,3,
|
||||
112,7,3,80,8,3,112,8,3,144,8,3,176,8,3,208,8,3,240,8,3,16,9,3,48,9,3,80,9,3,112,9,3,10,17,3,42,17,3,73,17,3,105,17,3,4,33,3,
|
||||
36,33,3,67,33,3,99,33,3,16,65,3,48,65,3,80,65,3,112,65,3,80,66,3,112,66,3,144,66,3,176,66,3,208,66,3,240,66,3,15,67,3,45,67,3,76,67,3,
|
||||
106,67,3,80,68,3,112,68,3,144,68,3,176,68,3,208,68,3,240,68,3,15,69,3,45,69,3,76,69,3,106,69,3,80,70,3,112,70,3,144,70,3,176,70,3,208,70,3,
|
||||
240,70,3,15,71,3,45,71,3,76,71,3,106,71,3,80,72,3,112,72,3,144,72,3,176,72,3,208,72,3,240,72,3,15,73,3,45,73,3,76,73,3,106,73,3,6,81,3,
|
||||
37,81,3,69,81,3,100,81,3,176,0,4,208,0,4,240,0,4,16,1,4,48,1,4,80,1,4,112,1,4,176,16,4,208,16,4,240,16,4,16,17,4,48,17,4,80,17,4,
|
||||
112,17,4,176,32,4,208,32,4,240,32,4,16,33,4,48,33,4,80,33,4,112,33,4,176,64,4,208,64,4,240,64,4,16,65,4,48,65,4,80,65,4,112,65,4,48,72,4,
|
||||
80,72,4,112,72,4,144,72,4,176,72,4,208,72,4,240,72,4,16,73,4,48,73,4,80,73,4,109,73,4,176,80,4,208,80,4,240,80,4,16,81,4,48,81,4,79,81,4,
|
||||
110,81,4,170,96,4,202,96,4,233,96,4,8,97,4,40,97,4,71,97,4,102,97,4,176,128,4,208,128,4,240,128,4,16,129,4,48,129,4,80,129,4,112,129,4,48,130,4,
|
||||
80,130,4,112,130,4,144,130,4,176,130,4,208,130,4,240,130,4,16,131,4,48,131,4,80,131,4,109,131,4,48,132,4,80,132,4,112,132,4,144,132,4,176,132,4,208,132,4,
|
||||
240,132,4,16,133,4,48,133,4,80,133,4,109,133,4,48,134,4,80,134,4,112,134,4,144,134,4,176,134,4,208,134,4,240,134,4,16,135,4,48,135,4,80,135,4,109,135,4,
|
||||
176,144,4,208,144,4,240,144,4,16,145,4,48,145,4,79,145,4,110,145,4,170,160,4,202,160,4,233,160,4,8,161,4,40,161,4,71,161,4,102,161,4,176,192,4,208,192,4,
|
||||
240,192,4,16,193,4,48,193,4,80,193,4,112,193,4,48,194,4,80,194,4,112,194,4,144,194,4,176,194,4,208,194,4,240,194,4,14,195,4,43,195,4,73,195,4,102,195,4,
|
||||
48,196,4,80,196,4,112,196,4,144,196,4,176,196,4,208,196,4,240,196,4,14,197,4,43,197,4,73,197,4,102,197,4,48,198,4,80,198,4,112,198,4,144,198,4,176,198,4,
|
||||
208,198,4,240,198,4,14,199,4,43,199,4,73,199,4,102,199,4,170,208,4,202,208,4,233,208,4,8,209,4,40,209,4,71,209,4,102,209,4,164,224,4,196,224,4,227,224,4,
|
||||
3,225,4,34,225,4,66,225,4,97,225,4,176,0,5,208,0,5,240,0,5,16,1,5,48,1,5,80,1,5,112,1,5,48,2,5,80,2,5,112,2,5,144,2,5,176,2,5,
|
||||
208,2,5,240,2,5,14,3,5,43,3,5,73,3,5,102,3,5,48,4,5,80,4,5,112,4,5,144,4,5,176,4,5,208,4,5,240,4,5,14,5,5,43,5,5,73,5,5,
|
||||
102,5,5,48,6,5,80,6,5,112,6,5,144,6,5,176,6,5,208,6,5,240,6,5,14,7,5,43,7,5,73,7,5,102,7,5,48,8,5,80,8,5,112,8,5,144,8,5,
|
||||
176,8,5,208,8,5,240,8,5,14,9,5,43,9,5,73,9,5,102,9,5,170,16,5,202,16,5,233,16,5,8,17,5,40,17,5,71,17,5,102,17,5,164,32,5,196,32,5,
|
||||
227,32,5,3,33,5,34,33,5,66,33,5,97,33,5,176,64,5,208,64,5,240,64,5,16,65,5,48,65,5,80,65,5,112,65,5,48,66,5,80,66,5,112,66,5,144,66,5,
|
||||
175,66,5,204,66,5,235,66,5,9,67,5,38,67,5,69,67,5,99,67,5,48,68,5,80,68,5,112,68,5,144,68,5,175,68,5,204,68,5,235,68,5,9,69,5,38,69,5,
|
||||
69,69,5,99,69,5,48,70,5,80,70,5,112,70,5,144,70,5,175,70,5,204,70,5,235,70,5,9,71,5,38,71,5,69,71,5,99,71,5,48,72,5,80,72,5,112,72,5,
|
||||
144,72,5,175,72,5,204,72,5,235,72,5,9,73,5,38,73,5,69,73,5,99,73,5,166,80,5,197,80,5,229,80,5,4,81,5,36,81,5,67,81,5,99,81,5,112,0,6,
|
||||
144,0,6,176,0,6,208,0,6,240,0,6,16,1,6,48,1,6,80,1,6,112,1,6,112,16,6,144,16,6,176,16,6,208,16,6,240,16,6,16,17,6,48,17,6,80,17,6,
|
||||
112,17,6,112,32,6,144,32,6,176,32,6,208,32,6,240,32,6,16,33,6,48,33,6,80,33,6,112,33,6,112,64,6,144,64,6,176,64,6,208,64,6,240,64,6,16,65,6,
|
||||
48,65,6,80,65,6,112,65,6,48,72,6,80,72,6,112,72,6,144,72,6,176,72,6,208,72,6,240,72,6,13,73,6,40,73,6,68,73,6,112,80,6,144,80,6,176,80,6,
|
||||
208,80,6,239,80,6,14,81,6,44,81,6,76,81,6,106,81,6,106,96,6,138,96,6,169,96,6,200,96,6,231,96,6,6,97,6,37,97,6,69,97,6,100,97,6,112,128,6,
|
||||
144,128,6,176,128,6,208,128,6,240,128,6,16,129,6,48,129,6,80,129,6,112,129,6,48,130,6,80,130,6,112,130,6,144,130,6,176,130,6,208,130,6,240,130,6,13,131,6,
|
||||
40,131,6,68,131,6,48,132,6,80,132,6,112,132,6,144,132,6,176,132,6,208,132,6,240,132,6,13,133,6,40,133,6,68,133,6,48,134,6,80,134,6,112,134,6,144,134,6,
|
||||
176,134,6,208,134,6,240,134,6,13,135,6,40,135,6,68,135,6,112,144,6,144,144,6,176,144,6,208,144,6,239,144,6,14,145,6,44,145,6,76,145,6,106,145,6,106,160,6,
|
||||
138,160,6,169,160,6,200,160,6,231,160,6,6,161,6,37,161,6,69,161,6,100,161,6,112,192,6,144,192,6,176,192,6,208,192,6,240,192,6,16,193,6,48,193,6,80,193,6,
|
||||
112,193,6,48,194,6,80,194,6,112,194,6,144,194,6,176,194,6,205,194,6,234,194,6,6,195,6,35,195,6,64,195,6,48,196,6,80,196,6,112,196,6,144,196,6,176,196,6,
|
||||
205,196,6,234,196,6,6,197,6,35,197,6,64,197,6,48,198,6,80,198,6,112,198,6,144,198,6,176,198,6,205,198,6,234,198,6,6,199,6,35,199,6,64,199,6,106,208,6,
|
||||
138,208,6,169,208,6,200,208,6,231,208,6,6,209,6,37,209,6,69,209,6,100,209,6,100,224,6,132,224,6,163,224,6,195,224,6,226,224,6,1,225,6,33,225,6,64,225,6,
|
||||
96,225,6,112,0,7,144,0,7,176,0,7,208,0,7,240,0,7,16,1,7,48,1,7,80,1,7,112,1,7,48,2,7,80,2,7,112,2,7,144,2,7,176,2,7,205,2,7,
|
||||
234,2,7,6,3,7,35,3,7,64,3,7,48,4,7,80,4,7,112,4,7,144,4,7,176,4,7,205,4,7,234,4,7,6,5,7,35,5,7,64,5,7,48,6,7,80,6,7,
|
||||
112,6,7,144,6,7,176,6,7,205,6,7,234,6,7,6,7,7,35,7,7,64,7,7,48,8,7,80,8,7,112,8,7,144,8,7,176,8,7,205,8,7,234,8,7,6,9,7,
|
||||
35,9,7,64,9,7,106,16,7,138,16,7,169,16,7,200,16,7,231,16,7,6,17,7,37,17,7,69,17,7,100,17,7,100,32,7,132,32,7,163,32,7,195,32,7,226,32,7,
|
||||
1,33,7,33,33,7,64,33,7,96,33,7,112,64,7,144,64,7,176,64,7,208,64,7,240,64,7,16,65,7,48,65,7,80,65,7,111,65,7,48,66,7,80,66,7,111,66,7,
|
||||
141,66,7,170,66,7,199,66,7,230,66,7,3,67,7,32,67,7,48,68,7,80,68,7,111,68,7,141,68,7,170,68,7,199,68,7,230,68,7,3,69,7,32,69,7,48,70,7,
|
||||
80,70,7,111,70,7,141,70,7,170,70,7,199,70,7,230,70,7,3,71,7,32,71,7,48,72,7,80,72,7,111,72,7,141,72,7,170,72,7,199,72,7,230,72,7,3,73,7,
|
||||
32,73,7,102,80,7,133,80,7,164,80,7,196,80,7,227,80,7,3,81,7,34,81,7,65,81,7,97,81,7,80,0,8,112,0,8,144,0,8,176,0,8,208,0,8,240,0,8,
|
||||
16,1,8,48,1,8,80,1,8,112,1,8,80,16,8,112,16,8,144,16,8,176,16,8,208,16,8,240,16,8,16,17,8,48,17,8,80,17,8,112,17,8,80,32,8,112,32,8,
|
||||
144,32,8,176,32,8,208,32,8,240,32,8,16,33,8,47,33,8,77,33,8,107,33,8,80,64,8,112,64,8,144,64,8,176,64,8,208,64,8,240,64,8,16,65,8,48,65,8,
|
||||
80,65,8,112,65,8,16,72,8,48,72,8,80,72,8,112,72,8,144,72,8,176,72,8,205,72,8,232,72,8,1,73,8,80,80,8,112,80,8,144,80,8,175,80,8,206,80,8,
|
||||
236,80,8,11,81,8,41,81,8,72,81,8,102,81,8,74,96,8,105,96,8,136,96,8,167,96,8,198,96,8,229,96,8,4,97,8,35,97,8,66,97,8,97,97,8,80,128,8,
|
||||
112,128,8,144,128,8,176,128,8,208,128,8,240,128,8,16,129,8,48,129,8,80,129,8,112,129,8,16,130,8,48,130,8,80,130,8,112,130,8,144,130,8,176,130,8,205,130,8,
|
||||
232,130,8,1,131,8,16,132,8,48,132,8,80,132,8,112,132,8,144,132,8,176,132,8,205,132,8,232,132,8,1,133,8,16,134,8,48,134,8,80,134,8,112,134,8,144,134,8,
|
||||
176,134,8,205,134,8,232,134,8,1,135,8,80,144,8,112,144,8,144,144,8,175,144,8,206,144,8,236,144,8,11,145,8,41,145,8,72,145,8,102,145,8,74,160,8,105,160,8,
|
||||
136,160,8,167,160,8,198,160,8,229,160,8,4,161,8,35,161,8,66,161,8,97,161,8,80,192,8,112,192,8,144,192,8,176,192,8,208,192,8,240,192,8,16,193,8,48,193,8,
|
||||
80,193,8,112,193,8,16,194,8,48,194,8,80,194,8,112,194,8,143,194,8,170,194,8,198,194,8,227,194,8,16,196,8,48,196,8,80,196,8,112,196,8,143,196,8,170,196,8,
|
||||
198,196,8,227,196,8,16,198,8,48,198,8,80,198,8,112,198,8,143,198,8,170,198,8,198,198,8,227,198,8,74,208,8,105,208,8,136,208,8,167,208,8,198,208,8,229,208,8,
|
||||
4,209,8,35,209,8,66,209,8,97,209,8,68,224,8,99,224,8,131,224,8,162,224,8,193,224,8,225,224,8,0,225,8,32,225,8,80,0,9,112,0,9,144,0,9,176,0,9,
|
||||
208,0,9,240,0,9,16,1,9,48,1,9,80,1,9,112,1,9,16,2,9,48,2,9,80,2,9,112,2,9,143,2,9,170,2,9,198,2,9,227,2,9,16,4,9,48,4,9,
|
||||
80,4,9,112,4,9,143,4,9,170,4,9,198,4,9,227,4,9,16,6,9,48,6,9,80,6,9,112,6,9,143,6,9,170,6,9,198,6,9,227,6,9,16,8,9,48,8,9,
|
||||
80,8,9,112,8,9,143,8,9,170,8,9,198,8,9,227,8,9,74,16,9,105,16,9,136,16,9,167,16,9,198,16,9,229,16,9,4,17,9,35,17,9,66,17,9,97,17,9,
|
||||
68,32,9,99,32,9,131,32,9,162,32,9,193,32,9,225,32,9,0,33,9,32,33,9,80,64,9,112,64,9,144,64,9,176,64,9,208,64,9,240,64,9,15,65,9,46,65,9,
|
||||
76,65,9,107,65,9,16,66,9,48,66,9,79,66,9,108,66,9,137,66,9,166,66,9,195,66,9,224,66,9,16,68,9,48,68,9,79,68,9,108,68,9,137,68,9,166,68,9,
|
||||
195,68,9,224,68,9,16,70,9,48,70,9,79,70,9,108,70,9,137,70,9,166,70,9,195,70,9,224,70,9,16,72,9,48,72,9,79,72,9,108,72,9,137,72,9,166,72,9,
|
||||
195,72,9,224,72,9,70,80,9,101,80,9,132,80,9,163,80,9,195,80,9,226,80,9,1,81,9,32,81,9,64,81,9,80,0,10,112,0,10,144,0,10,176,0,10,208,0,10,
|
||||
240,0,10,16,1,10,48,1,10,80,1,10,112,1,10,80,16,10,112,16,10,144,16,10,176,16,10,208,16,10,240,16,10,16,17,10,48,17,10,80,17,10,109,17,10,80,32,10,
|
||||
112,32,10,144,32,10,176,32,10,208,32,10,240,32,10,13,33,10,43,33,10,73,33,10,102,33,10,80,64,10,112,64,10,144,64,10,176,64,10,208,64,10,240,64,10,16,65,10,
|
||||
48,65,10,80,65,10,112,65,10,16,72,10,48,72,10,80,72,10,112,72,10,144,72,10,170,72,10,195,72,10,80,80,10,112,80,10,143,80,10,173,80,10,203,80,10,234,80,10,
|
||||
8,81,10,38,81,10,68,81,10,99,81,10,73,96,10,104,96,10,135,96,10,166,96,10,197,96,10,228,96,10,2,97,10,33,97,10,64,97,10,80,128,10,112,128,10,144,128,10,
|
||||
176,128,10,208,128,10,240,128,10,16,129,10,48,129,10,80,129,10,112,129,10,16,130,10,48,130,10,80,130,10,112,130,10,144,130,10,170,130,10,195,130,10,16,132,10,48,132,10,
|
||||
80,132,10,112,132,10,144,132,10,170,132,10,195,132,10,16,134,10,48,134,10,80,134,10,112,134,10,144,134,10,170,134,10,195,134,10,80,144,10,112,144,10,143,144,10,173,144,10,
|
||||
203,144,10,234,144,10,8,145,10,38,145,10,68,145,10,99,145,10,73,160,10,104,160,10,135,160,10,166,160,10,197,160,10,228,160,10,2,161,10,33,161,10,64,161,10,80,192,10,
|
||||
112,192,10,144,192,10,176,192,10,208,192,10,240,192,10,16,193,10,48,193,10,79,193,10,108,193,10,16,194,10,48,194,10,80,194,10,109,194,10,138,194,10,164,194,10,16,196,10,
|
||||
48,196,10,80,196,10,109,196,10,138,196,10,164,196,10,16,198,10,48,198,10,80,198,10,109,198,10,138,198,10,164,198,10,73,208,10,104,208,10,135,208,10,166,208,10,197,208,10,
|
||||
228,208,10,2,209,10,33,209,10,64,209,10,67,224,10,99,224,10,130,224,10,161,224,10,192,224,10,224,224,10,80,0,11,112,0,11,144,0,11,176,0,11,208,0,11,240,0,11,
|
||||
16,1,11,48,1,11,79,1,11,108,1,11,16,2,11,48,2,11,80,2,11,109,2,11,138,2,11,164,2,11,16,4,11,48,4,11,80,4,11,109,4,11,138,4,11,164,4,11,
|
||||
16,6,11,48,6,11,80,6,11,109,6,11,138,6,11,164,6,11,16,8,11,48,8,11,80,8,11,109,8,11,138,8,11,164,8,11,73,16,11,104,16,11,135,16,11,166,16,11,
|
||||
197,16,11,228,16,11,2,17,11,33,17,11,64,17,11,67,32,11,99,32,11,130,32,11,161,32,11,192,32,11,224,32,11,80,64,11,112,64,11,144,64,11,176,64,11,208,64,11,
|
||||
238,64,11,12,65,11,42,65,11,73,65,11,103,65,11,16,66,11,48,66,11,76,66,11,104,66,11,133,66,11,161,66,11,16,68,11,48,68,11,76,68,11,104,68,11,133,68,11,
|
||||
161,68,11,16,70,11,48,70,11,76,70,11,104,70,11,133,70,11,161,70,11,16,72,11,48,72,11,76,72,11,104,72,11,133,72,11,161,72,11,69,80,11,100,80,11,131,80,11,
|
||||
162,80,11,193,80,11,225,80,11,0,81,11,48,0,12,80,0,12,112,0,12,144,0,12,176,0,12,208,0,12,240,0,12,16,1,12,48,1,12,80,1,12,112,1,12,48,16,12,
|
||||
80,16,12,112,16,12,144,16,12,176,16,12,208,16,12,240,16,12,16,17,12,45,17,12,74,17,12,102,17,12,48,32,12,80,32,12,112,32,12,144,32,12,176,32,12,206,32,12,
|
||||
236,32,12,9,33,12,38,33,12,68,33,12,97,33,12,48,64,12,80,64,12,112,64,12,144,64,12,176,64,12,208,64,12,240,64,12,16,65,12,48,65,12,80,65,12,111,65,12,
|
||||
16,72,12,48,72,12,80,72,12,112,72,12,138,72,12,161,72,12,48,80,12,80,80,12,111,80,12,141,80,12,171,80,12,201,80,12,231,80,12,5,81,12,35,81,12,65,81,12,
|
||||
42,96,12,72,96,12,103,96,12,134,96,12,164,96,12,195,96,12,226,96,12,0,97,12,48,128,12,80,128,12,112,128,12,144,128,12,176,128,12,208,128,12,240,128,12,16,129,12,
|
||||
48,129,12,80,129,12,111,129,12,16,130,12,48,130,12,80,130,12,112,130,12,138,130,12,161,130,12,16,132,12,48,132,12,80,132,12,112,132,12,138,132,12,161,132,12,16,134,12,
|
||||
48,134,12,80,134,12,112,134,12,138,134,12,161,134,12,48,144,12,80,144,12,111,144,12,141,144,12,171,144,12,201,144,12,231,144,12,5,145,12,35,145,12,65,145,12,42,160,12,
|
||||
72,160,12,103,160,12,134,160,12,164,160,12,195,160,12,226,160,12,0,161,12,48,192,12,80,192,12,112,192,12,144,192,12,176,192,12,208,192,12,240,192,12,15,193,12,44,193,12,
|
||||
74,193,12,103,193,12,16,194,12,48,194,12,78,194,12,105,194,12,132,194,12,16,196,12,48,196,12,78,196,12,105,196,12,132,196,12,16,198,12,48,198,12,78,198,12,105,198,12,
|
||||
132,198,12,42,208,12,72,208,12,103,208,12,134,208,12,164,208,12,195,208,12,226,208,12,0,209,12,36,224,12,67,224,12,98,224,12,129,224,12,160,224,12,48,0,13,80,0,13,
|
||||
112,0,13,144,0,13,176,0,13,208,0,13,240,0,13,15,1,13,44,1,13,74,1,13,103,1,13,16,2,13,48,2,13,78,2,13,105,2,13,132,2,13,16,4,13,48,4,13,
|
||||
78,4,13,105,4,13,132,4,13,16,6,13,48,6,13,78,6,13,105,6,13,132,6,13,16,8,13,48,8,13,78,8,13,105,8,13,132,8,13,42,16,13,72,16,13,103,16,13,
|
||||
134,16,13,164,16,13,195,16,13,226,16,13,0,17,13,36,32,13,67,32,13,98,32,13,129,32,13,160,32,13,48,64,13,80,64,13,112,64,13,144,64,13,175,64,13,205,64,13,
|
||||
236,64,13,9,65,13,39,65,13,70,65,13,99,65,13,16,66,13,45,66,13,73,66,13,100,66,13,129,66,13,16,68,13,45,68,13,73,68,13,100,68,13,129,68,13,16,70,13,
|
||||
45,70,13,73,70,13,100,70,13,129,70,13,16,72,13,45,72,13,73,72,13,100,72,13,129,72,13,37,80,13,68,80,13,99,80,13,130,80,13,161,80,13,192,80,13,48,0,14,
|
||||
80,0,14,112,0,14,144,0,14,176,0,14,208,0,14,240,0,14,16,1,14,48,1,14,80,1,14,112,1,14,48,16,14,80,16,14,112,16,14,144,16,14,176,16,14,208,16,14,
|
||||
240,16,14,12,17,14,39,17,14,68,17,14,48,32,14,80,32,14,112,32,14,144,32,14,174,32,14,203,32,14,233,32,14,5,33,14,34,33,14,64,33,14,48,64,14,80,64,14,
|
||||
112,64,14,144,64,14,176,64,14,208,64,14,240,64,14,16,65,14,48,65,14,77,65,14,103,65,14,16,72,14,48,72,14,80,72,14,106,72,14,131,72,14,48,80,14,79,80,14,
|
||||
109,80,14,139,80,14,169,80,14,198,80,14,228,80,14,2,81,14,32,81,14,41,96,14,71,96,14,102,96,14,133,96,14,163,96,14,193,96,14,224,96,14,48,128,14,80,128,14,
|
||||
112,128,14,144,128,14,176,128,14,208,128,14,240,128,14,16,129,14,48,129,14,77,129,14,103,129,14,16,130,14,48,130,14,80,130,14,106,130,14,131,130,14,16,132,14,48,132,14,
|
||||
80,132,14,106,132,14,131,132,14,16,134,14,48,134,14,80,134,14,106,134,14,131,134,14,48,144,14,79,144,14,109,144,14,139,144,14,169,144,14,198,144,14,228,144,14,2,145,14,
|
||||
32,145,14,41,160,14,71,160,14,102,160,14,133,160,14,163,160,14,193,160,14,224,160,14,48,192,14,80,192,14,112,192,14,144,192,14,176,192,14,208,192,14,239,192,14,11,193,14,
|
||||
40,193,14,70,193,14,98,193,14,16,194,14,48,194,14,74,194,14,100,194,14,16,196,14,48,196,14,74,196,14,100,196,14,16,198,14,48,198,14,74,198,14,100,198,14,41,208,14,
|
||||
71,208,14,102,208,14,133,208,14,163,208,14,193,208,14,224,208,14,35,224,14,66,224,14,97,224,14,128,224,14,48,0,15,80,0,15,112,0,15,144,0,15,176,0,15,208,0,15,
|
||||
239,0,15,11,1,15,40,1,15,70,1,15,98,1,15,16,2,15,48,2,15,74,2,15,100,2,15,16,4,15,48,4,15,74,4,15,100,4,15,16,6,15,48,6,15,74,6,15,
|
||||
100,6,15,16,8,15,48,8,15,74,8,15,100,8,15,41,16,15,71,16,15,102,16,15,133,16,15,163,16,15,193,16,15,224,16,15,35,32,15,66,32,15,97,32,15,128,32,15,
|
||||
48,64,15,80,64,15,112,64,15,144,64,15,173,64,15,203,64,15,233,64,15,6,65,15,36,65,15,66,65,15,96,65,15,16,66,15,43,66,15,70,66,15,97,66,15,16,68,15,
|
||||
43,68,15,70,68,15,97,68,15,16,70,15,43,70,15,70,70,15,97,70,15,16,72,15,43,72,15,70,72,15,97,72,15,37,80,15,67,80,15,98,80,15,129,80,15,160,80,15,
|
||||
48,0,16,80,0,16,112,0,16,144,0,16,176,0,16,208,0,16,240,0,16,16,1,16,48,1,16,80,1,16,48,16,16,80,16,16,112,16,16,144,16,16,176,16,16,208,16,16,
|
||||
236,16,16,6,17,16,33,17,16,48,32,16,80,32,16,112,32,16,143,32,16,171,32,16,200,32,16,229,32,16,1,33,16,48,64,16,80,64,16,112,64,16,144,64,16,176,64,16,
|
||||
208,64,16,240,64,16,15,65,16,42,65,16,70,65,16,16,72,16,48,72,16,77,72,16,99,72,16,48,80,16,78,80,16,107,80,16,137,80,16,166,80,16,196,80,16,226,80,16,
|
||||
40,96,16,70,96,16,101,96,16,131,96,16,161,96,16,192,96,16,48,128,16,80,128,16,112,128,16,144,128,16,176,128,16,208,128,16,240,128,16,15,129,16,42,129,16,70,129,16,
|
||||
16,130,16,48,130,16,77,130,16,99,130,16,16,132,16,48,132,16,77,132,16,99,132,16,16,134,16,48,134,16,77,134,16,99,134,16,48,144,16,78,144,16,107,144,16,137,144,16,
|
||||
166,144,16,196,144,16,226,144,16,40,160,16,70,160,16,101,160,16,131,160,16,161,160,16,192,160,16,48,192,16,80,192,16,112,192,16,144,192,16,176,192,16,206,192,16,235,192,16,
|
||||
7,193,16,36,193,16,65,193,16,16,194,16,46,194,16,70,194,16,16,196,16,46,196,16,70,196,16,16,198,16,46,198,16,70,198,16,40,208,16,70,208,16,101,208,16,131,208,16,
|
||||
161,208,16,192,208,16,35,224,16,65,224,16,96,224,16,128,224,16,48,0,17,80,0,17,112,0,17,144,0,17,176,0,17,206,0,17,235,0,17,7,1,17,36,1,17,65,1,17,
|
||||
16,2,17,46,2,17,70,2,17,16,4,17,46,4,17,70,4,17,16,6,17,46,6,17,70,6,17,16,8,17,46,8,17,70,8,17,40,16,17,70,16,17,101,16,17,131,16,17,
|
||||
161,16,17,192,16,17,35,32,17,65,32,17,96,32,17,128,32,17,48,64,17,80,64,17,112,64,17,142,64,17,171,64,17,200,64,17,230,64,17,3,65,17,33,65,17,16,66,17,
|
||||
41,66,17,67,66,17,16,68,17,41,68,17,67,68,17,16,70,17,41,70,17,67,70,17,16,72,17,41,72,17,67,72,17,36,80,17,67,80,17,97,80,17,128,80,17,48,0,18,
|
||||
80,0,18,112,0,18,144,0,18,176,0,18,208,0,18,240,0,18,16,1,18,46,1,18,48,16,18,80,16,18,112,16,18,144,16,18,176,16,18,202,16,18,230,16,18,0,17,18,
|
||||
48,32,18,80,32,18,111,32,18,140,32,18,168,32,18,196,32,18,225,32,18,48,64,18,80,64,18,112,64,18,144,64,18,176,64,18,208,64,18,239,64,18,9,65,18,35,65,18,
|
||||
16,72,18,48,72,18,71,72,18,47,80,18,76,80,18,105,80,18,135,80,18,164,80,18,193,80,18,39,96,18,69,96,18,99,96,18,130,96,18,160,96,18,48,128,18,80,128,18,
|
||||
112,128,18,144,128,18,176,128,18,208,128,18,239,128,18,9,129,18,35,129,18,16,130,18,48,130,18,71,130,18,16,132,18,48,132,18,71,132,18,16,134,18,48,134,18,71,134,18,
|
||||
47,144,18,76,144,18,105,144,18,135,144,18,164,144,18,193,144,18,39,160,18,69,160,18,99,160,18,130,160,18,160,160,18,48,192,18,80,192,18,112,192,18,144,192,18,174,192,18,
|
||||
202,192,18,231,192,18,3,193,18,16,194,18,43,194,18,66,194,18,16,196,18,43,196,18,66,196,18,16,198,18,43,198,18,66,198,18,39,208,18,69,208,18,99,208,18,130,208,18,
|
||||
160,208,18,34,224,18,65,224,18,96,224,18,48,0,19,80,0,19,112,0,19,144,0,19,174,0,19,202,0,19,231,0,19,3,1,19,16,2,19,43,2,19,66,2,19,16,4,19,
|
||||
43,4,19,66,4,19,16,6,19,43,6,19,66,6,19,16,8,19,43,8,19,66,8,19,39,16,19,69,16,19,99,16,19,130,16,19,160,16,19,34,32,19,65,32,19,96,32,19,
|
||||
48,64,19,80,64,19,110,64,19,140,64,19,169,64,19,198,64,19,227,64,19,0,65,19,16,66,19,38,66,19,64,66,19,16,68,19,38,68,19,64,68,19,16,70,19,38,70,19,
|
||||
64,70,19,16,72,19,38,72,19,64,72,19,35,80,19,66,80,19,96,80,19,16,0,20,48,0,20,80,0,20,112,0,20,144,0,20,176,0,20,208,0,20,240,0,20,14,1,20,
|
||||
16,16,20,48,16,20,80,16,20,112,16,20,144,16,20,172,16,20,198,16,20,225,16,20,16,32,20,48,32,20,80,32,20,109,32,20,138,32,20,165,32,20,193,32,20,16,64,20,
|
||||
48,64,20,80,64,20,112,64,20,144,64,20,176,64,20,207,64,20,234,64,20,3,65,20,16,72,20,48,72,20,65,72,20,16,80,20,46,80,20,75,80,20,104,80,20,133,80,20,
|
||||
162,80,20,10,96,20,39,96,20,68,96,20,98,96,20,129,96,20,16,128,20,48,128,20,80,128,20,112,128,20,144,128,20,176,128,20,207,128,20,234,128,20,3,129,20,16,130,20,
|
||||
48,130,20,65,130,20,16,132,20,48,132,20,65,132,20,16,134,20,48,134,20,65,134,20,16,144,20,46,144,20,75,144,20,104,144,20,133,144,20,162,144,20,10,160,20,39,160,20,
|
||||
68,160,20,98,160,20,129,160,20,16,192,20,48,192,20,80,192,20,112,192,20,144,192,20,171,192,20,199,192,20,228,192,20,16,194,20,40,194,20,16,196,20,40,196,20,16,198,20,
|
||||
40,198,20,10,208,20,39,208,20,68,208,20,98,208,20,129,208,20,4,224,20,34,224,20,64,224,20,16,0,21,48,0,21,80,0,21,112,0,21,144,0,21,171,0,21,199,0,21,
|
||||
228,0,21,16,2,21,40,2,21,16,4,21,40,4,21,16,6,21,40,6,21,16,8,21,40,8,21,10,16,21,39,16,21,68,16,21,98,16,21,129,16,21,4,32,21,34,32,21,
|
||||
64,32,21,16,64,21,48,64,21,79,64,21,108,64,21,138,64,21,166,64,21,195,64,21,225,64,21,15,66,21,36,66,21,15,68,21,36,68,21,15,70,21,36,70,21,15,72,21,
|
||||
36,72,21,6,80,21,35,80,21,65,80,21,96,80,21,16,1,22,48,1,22,80,1,22,112,1,22,16,17,22,48,17,22,80,17,22,112,17,22,16,33,22,48,33,22,80,33,22,
|
||||
112,33,22,16,65,22,48,65,22,80,65,22,112,65,22,80,72,22,112,72,22,144,72,22,176,72,22,208,72,22,240,72,22,16,73,22,48,73,22,80,73,22,112,73,22,16,81,22,
|
||||
48,81,22,80,81,22,112,81,22,10,97,22,42,97,22,73,97,22,105,97,22,16,129,22,48,129,22,80,129,22,112,129,22,80,130,22,112,130,22,144,130,22,176,130,22,208,130,22,
|
||||
240,130,22,16,131,22,48,131,22,80,131,22,112,131,22,80,132,22,112,132,22,144,132,22,176,132,22,208,132,22,240,132,22,16,133,22,48,133,22,80,133,22,112,133,22,80,134,22,
|
||||
112,134,22,144,134,22,176,134,22,208,134,22,240,134,22,16,135,22,48,135,22,80,135,22,112,135,22,16,145,22,48,145,22,80,145,22,112,145,22,10,161,22,42,161,22,73,161,22,
|
||||
105,161,22,16,193,22,48,193,22,80,193,22,112,193,22,80,194,22,112,194,22,144,194,22,176,194,22,208,194,22,240,194,22,16,195,22,48,195,22,80,195,22,112,195,22,80,196,22,
|
||||
112,196,22,144,196,22,176,196,22,208,196,22,240,196,22,16,197,22,48,197,22,80,197,22,112,197,22,80,198,22,112,198,22,144,198,22,176,198,22,208,198,22,240,198,22,16,199,22,
|
||||
48,199,22,80,199,22,112,199,22,10,209,22,42,209,22,73,209,22,105,209,22,4,225,22,36,225,22,67,225,22,99,225,22,16,1,23,48,1,23,80,1,23,112,1,23,80,2,23,
|
||||
112,2,23,144,2,23,176,2,23,208,2,23,240,2,23,16,3,23,48,3,23,80,3,23,112,3,23,80,4,23,112,4,23,144,4,23,176,4,23,208,4,23,240,4,23,16,5,23,
|
||||
48,5,23,80,5,23,112,5,23,80,6,23,112,6,23,144,6,23,176,6,23,208,6,23,240,6,23,16,7,23,48,7,23,80,7,23,112,7,23,80,8,23,112,8,23,144,8,23,
|
||||
176,8,23,208,8,23,240,8,23,16,9,23,48,9,23,80,9,23,112,9,23,10,17,23,42,17,23,73,17,23,105,17,23,4,33,23,36,33,23,67,33,23,99,33,23,16,65,23,
|
||||
48,65,23,80,65,23,112,65,23,80,66,23,112,66,23,144,66,23,176,66,23,208,66,23,240,66,23,15,67,23,45,67,23,76,67,23,106,67,23,80,68,23,112,68,23,144,68,23,
|
||||
176,68,23,208,68,23,240,68,23,15,69,23,45,69,23,76,69,23,106,69,23,80,70,23,112,70,23,144,70,23,176,70,23,208,70,23,240,70,23,15,71,23,45,71,23,76,71,23,
|
||||
106,71,23,80,72,23,112,72,23,144,72,23,176,72,23,208,72,23,240,72,23,15,73,23,45,73,23,76,73,23,106,73,23,6,81,23,37,81,23,69,81,23,100,81,23,144,0,24,
|
||||
176,0,24,208,0,24,240,0,24,16,1,24,48,1,24,80,1,24,112,1,24,144,16,24,176,16,24,208,16,24,240,16,24,16,17,24,48,17,24,80,17,24,112,17,24,144,32,24,
|
||||
176,32,24,208,32,24,240,32,24,16,33,24,48,33,24,80,33,24,112,33,24,144,64,24,176,64,24,208,64,24,240,64,24,16,65,24,48,65,24,80,65,24,112,65,24,48,72,24,
|
||||
80,72,24,112,72,24,144,72,24,176,72,24,208,72,24,240,72,24,16,73,24,47,73,24,75,73,24,102,73,24,144,80,24,176,80,24,208,80,24,240,80,24,15,81,24,46,81,24,
|
||||
77,81,24,108,81,24,138,96,24,170,96,24,201,96,24,232,96,24,7,97,24,39,97,24,70,97,24,101,97,24,144,128,24,176,128,24,208,128,24,240,128,24,16,129,24,48,129,24,
|
||||
80,129,24,112,129,24,48,130,24,80,130,24,112,130,24,144,130,24,176,130,24,208,130,24,240,130,24,16,131,24,47,131,24,75,131,24,102,131,24,48,132,24,80,132,24,112,132,24,
|
||||
144,132,24,176,132,24,208,132,24,240,132,24,16,133,24,47,133,24,75,133,24,102,133,24,48,134,24,80,134,24,112,134,24,144,134,24,176,134,24,208,134,24,240,134,24,16,135,24,
|
||||
47,135,24,75,135,24,102,135,24,144,144,24,176,144,24,208,144,24,240,144,24,15,145,24,46,145,24,77,145,24,108,145,24,138,160,24,170,160,24,201,160,24,232,160,24,7,161,24,
|
||||
39,161,24,70,161,24,101,161,24,144,192,24,176,192,24,208,192,24,240,192,24,16,193,24,48,193,24,80,193,24,112,193,24,48,194,24,80,194,24,112,194,24,144,194,24,176,194,24,
|
||||
208,194,24,238,194,24,10,195,24,39,195,24,69,195,24,97,195,24,48,196,24,80,196,24,112,196,24,144,196,24,176,196,24,208,196,24,238,196,24,10,197,24,39,197,24,69,197,24,
|
||||
97,197,24,48,198,24,80,198,24,112,198,24,144,198,24,176,198,24,208,198,24,238,198,24,10,199,24,39,199,24,69,199,24,97,199,24,138,208,24,170,208,24,201,208,24,232,208,24,
|
||||
7,209,24,39,209,24,70,209,24,101,209,24,132,224,24,164,224,24,195,224,24,227,224,24,2,225,24,34,225,24,65,225,24,97,225,24,144,0,25,176,0,25,208,0,25,240,0,25,
|
||||
16,1,25,48,1,25,80,1,25,112,1,25,48,2,25,80,2,25,112,2,25,144,2,25,176,2,25,208,2,25,238,2,25,10,3,25,39,3,25,69,3,25,97,3,25,48,4,25,
|
||||
80,4,25,112,4,25,144,4,25,176,4,25,208,4,25,238,4,25,10,5,25,39,5,25,69,5,25,97,5,25,48,6,25,80,6,25,112,6,25,144,6,25,176,6,25,208,6,25,
|
||||
238,6,25,10,7,25,39,7,25,69,7,25,97,7,25,48,8,25,80,8,25,112,8,25,144,8,25,176,8,25,208,8,25,238,8,25,10,9,25,39,9,25,69,9,25,97,9,25,
|
||||
138,16,25,170,16,25,201,16,25,232,16,25,7,17,25,39,17,25,70,17,25,101,17,25,132,32,25,164,32,25,195,32,25,227,32,25,2,33,25,34,33,25,65,33,25,97,33,25,
|
||||
144,64,25,176,64,25,208,64,25,240,64,25,16,65,25,48,65,25,80,65,25,112,65,25,48,66,25,80,66,25,112,66,25,143,66,25,172,66,25,202,66,25,232,66,25,6,67,25,
|
||||
35,67,25,65,67,25,48,68,25,80,68,25,112,68,25,143,68,25,172,68,25,202,68,25,232,68,25,6,69,25,35,69,25,65,69,25,48,70,25,80,70,25,112,70,25,143,70,25,
|
||||
172,70,25,202,70,25,232,70,25,6,71,25,35,71,25,65,71,25,48,72,25,80,72,25,112,72,25,143,72,25,172,72,25,202,72,25,232,72,25,6,73,25,35,73,25,65,73,25,
|
||||
134,80,25,165,80,25,196,80,25,228,80,25,3,81,25,35,81,25,66,81,25,98,81,25,80,0,26,112,0,26,144,0,26,176,0,26,208,0,26,240,0,26,16,1,26,48,1,26,
|
||||
80,1,26,112,1,26,80,16,26,112,16,26,144,16,26,176,16,26,208,16,26,240,16,26,16,17,26,48,17,26,80,17,26,112,17,26,80,32,26,112,32,26,144,32,26,176,32,26,
|
||||
208,32,26,240,32,26,16,33,26,47,33,26,77,33,26,107,33,26,80,64,26,112,64,26,144,64,26,176,64,26,208,64,26,240,64,26,16,65,26,48,65,26,80,65,26,112,65,26,
|
||||
16,72,26,48,72,26,80,72,26,112,72,26,144,72,26,176,72,26,205,72,26,232,72,26,1,73,26,80,80,26,112,80,26,144,80,26,175,80,26,206,80,26,236,80,26,11,81,26,
|
||||
41,81,26,72,81,26,102,81,26,74,96,26,105,96,26,136,96,26,167,96,26,198,96,26,229,96,26,4,97,26,35,97,26,66,97,26,97,97,26,80,128,26,112,128,26,144,128,26,
|
||||
176,128,26,208,128,26,240,128,26,16,129,26,48,129,26,80,129,26,112,129,26,16,130,26,48,130,26,80,130,26,112,130,26,144,130,26,176,130,26,205,130,26,232,130,26,1,131,26,
|
||||
16,132,26,48,132,26,80,132,26,112,132,26,144,132,26,176,132,26,205,132,26,232,132,26,1,133,26,16,134,26,48,134,26,80,134,26,112,134,26,144,134,26,176,134,26,205,134,26,
|
||||
232,134,26,1,135,26,80,144,26,112,144,26,144,144,26,175,144,26,206,144,26,236,144,26,11,145,26,41,145,26,72,145,26,102,145,26,74,160,26,105,160,26,136,160,26,167,160,26,
|
||||
198,160,26,229,160,26,4,161,26,35,161,26,66,161,26,97,161,26,80,192,26,112,192,26,144,192,26,176,192,26,208,192,26,240,192,26,16,193,26,48,193,26,80,193,26,112,193,26,
|
||||
16,194,26,48,194,26,80,194,26,112,194,26,143,194,26,170,194,26,198,194,26,227,194,26,16,196,26,48,196,26,80,196,26,112,196,26,143,196,26,170,196,26,198,196,26,227,196,26,
|
||||
16,198,26,48,198,26,80,198,26,112,198,26,143,198,26,170,198,26,198,198,26,227,198,26,74,208,26,105,208,26,136,208,26,167,208,26,198,208,26,229,208,26,4,209,26,35,209,26,
|
||||
66,209,26,97,209,26,68,224,26,99,224,26,131,224,26,162,224,26,193,224,26,225,224,26,0,225,26,32,225,26,80,0,27,112,0,27,144,0,27,176,0,27,208,0,27,240,0,27,
|
||||
16,1,27,48,1,27,80,1,27,112,1,27,16,2,27,48,2,27,80,2,27,112,2,27,143,2,27,170,2,27,198,2,27,227,2,27,16,4,27,48,4,27,80,4,27,112,4,27,
|
||||
143,4,27,170,4,27,198,4,27,227,4,27,16,6,27,48,6,27,80,6,27,112,6,27,143,6,27,170,6,27,198,6,27,227,6,27,16,8,27,48,8,27,80,8,27,112,8,27,
|
||||
143,8,27,170,8,27,198,8,27,227,8,27,74,16,27,105,16,27,136,16,27,167,16,27,198,16,27,229,16,27,4,17,27,35,17,27,66,17,27,97,17,27,68,32,27,99,32,27,
|
||||
131,32,27,162,32,27,193,32,27,225,32,27,0,33,27,32,33,27,80,64,27,112,64,27,144,64,27,176,64,27,208,64,27,240,64,27,15,65,27,46,65,27,76,65,27,107,65,27,
|
||||
16,66,27,48,66,27,79,66,27,108,66,27,137,66,27,166,66,27,195,66,27,224,66,27,16,68,27,48,68,27,79,68,27,108,68,27,137,68,27,166,68,27,195,68,27,224,68,27,
|
||||
16,70,27,48,70,27,79,70,27,108,70,27,137,70,27,166,70,27,195,70,27,224,70,27,16,72,27,48,72,27,79,72,27,108,72,27,137,72,27,166,72,27,195,72,27,224,72,27,
|
||||
70,80,27,101,80,27,132,80,27,163,80,27,195,80,27,226,80,27,1,81,27,32,81,27,64,81,27,48,0,28,80,0,28,112,0,28,144,0,28,176,0,28,208,0,28,240,0,28,
|
||||
16,1,28,48,1,28,80,1,28,112,1,28,48,16,28,80,16,28,112,16,28,144,16,28,176,16,28,208,16,28,240,16,28,16,17,28,48,17,28,78,17,28,106,17,28,48,32,28,
|
||||
80,32,28,112,32,28,144,32,28,176,32,28,208,32,28,238,32,28,11,33,28,41,33,28,71,33,28,100,33,28,48,64,28,80,64,28,112,64,28,144,64,28,176,64,28,208,64,28,
|
||||
240,64,28,16,65,28,48,65,28,80,65,28,112,65,28,16,72,28,48,72,28,80,72,28,112,72,28,143,72,28,166,72,28,48,80,28,80,80,28,112,80,28,142,80,28,172,80,28,
|
||||
202,80,28,233,80,28,6,81,28,36,81,28,67,81,28,97,81,28,42,96,28,73,96,28,104,96,28,135,96,28,165,96,28,196,96,28,227,96,28,1,97,28,32,97,28,48,128,28,
|
||||
80,128,28,112,128,28,144,128,28,176,128,28,208,128,28,240,128,28,16,129,28,48,129,28,80,129,28,112,129,28,16,130,28,48,130,28,80,130,28,112,130,28,143,130,28,166,130,28,
|
||||
16,132,28,48,132,28,80,132,28,112,132,28,143,132,28,166,132,28,16,134,28,48,134,28,80,134,28,112,134,28,143,134,28,166,134,28,48,144,28,80,144,28,112,144,28,142,144,28,
|
||||
172,144,28,202,144,28,233,144,28,6,145,28,36,145,28,67,145,28,97,145,28,42,160,28,73,160,28,104,160,28,135,160,28,165,160,28,196,160,28,227,160,28,1,161,28,32,161,28,
|
||||
48,192,28,80,192,28,112,192,28,144,192,28,176,192,28,208,192,28,240,192,28,16,193,28,47,193,28,77,193,28,106,193,28,16,194,28,48,194,28,80,194,28,107,194,28,135,194,28,
|
||||
161,194,28,16,196,28,48,196,28,80,196,28,107,196,28,135,196,28,161,196,28,16,198,28,48,198,28,80,198,28,107,198,28,135,198,28,161,198,28,42,208,28,73,208,28,104,208,28,
|
||||
135,208,28,165,208,28,196,208,28,227,208,28,1,209,28,32,209,28,36,224,28,67,224,28,98,224,28,130,224,28,161,224,28,192,224,28,48,0,29,80,0,29,112,0,29,144,0,29,
|
||||
176,0,29,208,0,29,240,0,29,16,1,29,47,1,29,77,1,29,106,1,29,16,2,29,48,2,29,80,2,29,107,2,29,135,2,29,161,2,29,16,4,29,48,4,29,80,4,29,
|
||||
107,4,29,135,4,29,161,4,29,16,6,29,48,6,29,80,6,29,107,6,29,135,6,29,161,6,29,16,8,29,48,8,29,80,8,29,107,8,29,135,8,29,161,8,29,42,16,29,
|
||||
73,16,29,104,16,29,135,16,29,165,16,29,196,16,29,227,16,29,1,17,29,32,17,29,36,32,29,67,32,29,98,32,29,130,32,29,161,32,29,192,32,29,48,64,29,80,64,29,
|
||||
112,64,29,144,64,29,176,64,29,207,64,29,237,64,29,11,65,29,41,65,29,71,65,29,101,65,29,16,66,29,47,66,29,74,66,29,102,66,29,131,66,29,16,68,29,47,68,29,
|
||||
74,68,29,102,68,29,131,68,29,16,70,29,47,70,29,74,70,29,102,70,29,131,70,29,16,72,29,47,72,29,74,72,29,102,72,29,131,72,29,38,80,29,68,80,29,100,80,29,
|
||||
131,80,29,162,80,29,193,80,29,224,80,29,48,0,30,80,0,30,112,0,30,144,0,30,176,0,30,208,0,30,240,0,30,16,1,30,48,1,30,80,1,30,112,1,30,48,16,30,
|
||||
80,16,30,112,16,30,144,16,30,176,16,30,208,16,30,240,16,30,12,17,30,39,17,30,68,17,30,48,32,30,80,32,30,112,32,30,144,32,30,174,32,30,203,32,30,233,32,30,
|
||||
5,33,30,34,33,30,64,33,30,48,64,30,80,64,30,112,64,30,144,64,30,176,64,30,208,64,30,240,64,30,16,65,30,48,65,30,77,65,30,103,65,30,16,72,30,48,72,30,
|
||||
80,72,30,106,72,30,131,72,30,48,80,30,79,80,30,109,80,30,139,80,30,169,80,30,198,80,30,228,80,30,2,81,30,32,81,30,41,96,30,71,96,30,102,96,30,133,96,30,
|
||||
163,96,30,193,96,30,224,96,30,48,128,30,80,128,30,112,128,30,144,128,30,176,128,30,208,128,30,240,128,30,16,129,30,48,129,30,77,129,30,103,129,30,16,130,30,48,130,30,
|
||||
80,130,30,106,130,30,131,130,30,16,132,30,48,132,30,80,132,30,106,132,30,131,132,30,16,134,30,48,134,30,80,134,30,106,134,30,131,134,30,48,144,30,79,144,30,109,144,30,
|
||||
139,144,30,169,144,30,198,144,30,228,144,30,2,145,30,32,145,30,41,160,30,71,160,30,102,160,30,133,160,30,163,160,30,193,160,30,224,160,30,48,192,30,80,192,30,112,192,30,
|
||||
144,192,30,176,192,30,208,192,30,239,192,30,11,193,30,40,193,30,70,193,30,98,193,30,16,194,30,48,194,30,74,194,30,100,194,30,16,196,30,48,196,30,74,196,30,100,196,30,
|
||||
16,198,30,48,198,30,74,198,30,100,198,30,41,208,30,71,208,30,102,208,30,133,208,30,163,208,30,193,208,30,224,208,30,35,224,30,66,224,30,97,224,30,128,224,30,48,0,31,
|
||||
80,0,31,112,0,31,144,0,31,176,0,31,208,0,31,239,0,31,11,1,31,40,1,31,70,1,31,98,1,31,16,2,31,48,2,31,74,2,31,100,2,31,16,4,31,48,4,31,
|
||||
74,4,31,100,4,31,16,6,31,48,6,31,74,6,31,100,6,31,16,8,31,48,8,31,74,8,31,100,8,31,41,16,31,71,16,31,102,16,31,133,16,31,163,16,31,193,16,31,
|
||||
224,16,31,35,32,31,66,32,31,97,32,31,128,32,31,48,64,31,80,64,31,112,64,31,144,64,31,173,64,31,203,64,31,233,64,31,6,65,31,36,65,31,66,65,31,96,65,31,
|
||||
16,66,31,43,66,31,70,66,31,97,66,31,16,68,31,43,68,31,70,68,31,97,68,31,16,70,31,43,70,31,70,70,31,97,70,31,16,72,31,43,72,31,70,72,31,97,72,31,
|
||||
37,80,31,67,80,31,98,80,31,129,80,31,160,80,31,48,0,32,80,0,32,112,0,32,144,0,32,176,0,32,208,0,32,240,0,32,16,1,32,48,1,32,48,16,32,80,16,32,
|
||||
112,16,32,144,16,32,176,16,32,205,16,32,233,16,32,3,17,32,48,32,32,80,32,32,112,32,32,142,32,32,170,32,32,198,32,32,227,32,32,48,64,32,80,64,32,112,64,32,
|
||||
144,64,32,176,64,32,208,64,32,240,64,32,12,65,32,39,65,32,16,72,32,48,72,32,74,72,32,48,80,32,77,80,32,106,80,32,136,80,32,165,80,32,195,80,32,224,80,32,
|
||||
40,96,32,70,96,32,100,96,32,131,96,32,161,96,32,48,128,32,80,128,32,112,128,32,144,128,32,176,128,32,208,128,32,240,128,32,12,129,32,39,129,32,16,130,32,48,130,32,
|
||||
74,130,32,16,132,32,48,132,32,74,132,32,16,134,32,48,134,32,74,134,32,48,144,32,77,144,32,106,144,32,136,144,32,165,144,32,195,144,32,224,144,32,40,160,32,70,160,32,
|
||||
100,160,32,131,160,32,161,160,32,48,192,32,80,192,32,112,192,32,144,192,32,176,192,32,204,192,32,233,192,32,5,193,32,34,193,32,16,194,32,44,194,32,68,194,32,16,196,32,
|
||||
44,196,32,68,196,32,16,198,32,44,198,32,68,198,32,40,208,32,70,208,32,100,208,32,131,208,32,161,208,32,35,224,32,65,224,32,96,224,32,48,0,33,80,0,33,112,0,33,
|
||||
144,0,33,176,0,33,204,0,33,233,0,33,5,1,33,34,1,33,16,2,33,44,2,33,68,2,33,16,4,33,44,4,33,68,4,33,16,6,33,44,6,33,68,6,33,16,8,33,
|
||||
44,8,33,68,8,33,40,16,33,70,16,33,100,16,33,131,16,33,161,16,33,35,32,33,65,32,33,96,32,33,48,64,33,80,64,33,111,64,33,141,64,33,170,64,33,199,64,33,
|
||||
229,64,33,2,65,33,16,66,33,39,66,33,65,66,33,16,68,33,39,68,33,65,68,33,16,70,33,39,70,33,65,70,33,16,72,33,39,72,33,65,72,33,36,80,33,66,80,33,
|
||||
97,80,33,128,80,33,16,0,34,48,0,34,80,0,34,112,0,34,144,0,34,176,0,34,208,0,34,240,0,34,14,1,34,16,16,34,48,16,34,80,16,34,112,16,34,144,16,34,
|
||||
172,16,34,198,16,34,225,16,34,16,32,34,48,32,34,80,32,34,109,32,34,138,32,34,165,32,34,193,32,34,16,64,34,48,64,34,80,64,34,112,64,34,144,64,34,176,64,34,
|
||||
207,64,34,234,64,34,3,65,34,16,72,34,48,72,34,65,72,34,16,80,34,46,80,34,75,80,34,104,80,34,133,80,34,162,80,34,10,96,34,39,96,34,68,96,34,98,96,34,
|
||||
129,96,34,16,128,34,48,128,34,80,128,34,112,128,34,144,128,34,176,128,34,207,128,34,234,128,34,3,129,34,16,130,34,48,130,34,65,130,34,16,132,34,48,132,34,65,132,34,
|
||||
16,134,34,48,134,34,65,134,34,16,144,34,46,144,34,75,144,34,104,144,34,133,144,34,162,144,34,10,160,34,39,160,34,68,160,34,98,160,34,129,160,34,16,192,34,48,192,34,
|
||||
80,192,34,112,192,34,144,192,34,171,192,34,199,192,34,228,192,34,16,194,34,40,194,34,16,196,34,40,196,34,16,198,34,40,198,34,10,208,34,39,208,34,68,208,34,98,208,34,
|
||||
129,208,34,4,224,34,34,224,34,64,224,34,16,0,35,48,0,35,80,0,35,112,0,35,144,0,35,171,0,35,199,0,35,228,0,35,16,2,35,40,2,35,16,4,35,40,4,35,
|
||||
16,6,35,40,6,35,16,8,35,40,8,35,10,16,35,39,16,35,68,16,35,98,16,35,129,16,35,4,32,35,34,32,35,64,32,35,16,64,35,48,64,35,79,64,35,108,64,35,
|
||||
138,64,35,166,64,35,195,64,35,225,64,35,15,66,35,36,66,35,15,68,35,36,68,35,15,70,35,36,70,35,15,72,35,36,72,35,6,80,35,35,80,35,65,80,35,96,80,35,
|
||||
16,0,36,48,0,36,80,0,36,112,0,36,144,0,36,176,0,36,208,0,36,16,16,36,48,16,36,80,16,36,112,16,36,141,16,36,165,16,36,16,32,36,48,32,36,78,32,36,
|
||||
106,32,36,134,32,36,161,32,36,16,64,36,48,64,36,80,64,36,112,64,36,144,64,36,174,64,36,199,64,36,16,72,36,40,72,36,16,80,36,44,80,36,73,80,36,101,80,36,
|
||||
130,80,36,10,96,36,37,96,36,67,96,36,97,96,36,16,128,36,48,128,36,80,128,36,112,128,36,144,128,36,174,128,36,199,128,36,16,130,36,40,130,36,16,132,36,40,132,36,
|
||||
16,134,36,40,134,36,16,144,36,44,144,36,73,144,36,101,144,36,130,144,36,10,160,36,37,160,36,67,160,36,97,160,36,16,192,36,48,192,36,80,192,36,112,192,36,140,192,36,
|
||||
167,192,36,194,192,36,16,194,36,35,194,36,16,196,36,35,196,36,16,198,36,35,198,36,10,208,36,37,208,36,67,208,36,97,208,36,4,224,36,33,224,36,16,0,37,48,0,37,
|
||||
80,0,37,112,0,37,140,0,37,167,0,37,194,0,37,16,2,37,35,2,37,16,4,37,35,4,37,16,6,37,35,6,37,16,8,37,35,8,37,10,16,37,37,16,37,67,16,37,
|
||||
97,16,37,4,32,37,33,32,37,16,64,37,48,64,37,77,64,37,106,64,37,135,64,37,163,64,37,192,64,37,12,66,37,32,66,37,12,68,37,32,68,37,12,70,37,32,70,37,
|
||||
12,72,37,32,72,37,5,80,37,34,80,37,64,80,37,16,0,38,48,0,38,80,0,38,112,0,38,144,0,38,176,0,38,16,16,38,48,16,38,80,16,38,109,16,38,135,16,38,
|
||||
16,32,38,48,32,38,75,32,38,102,32,38,130,32,38,16,64,38,48,64,38,80,64,38,112,64,38,144,64,38,167,64,38,16,72,38,33,72,38,16,80,38,43,80,38,70,80,38,
|
||||
99,80,38,128,80,38,9,96,38,36,96,38,65,96,38,16,128,38,48,128,38,80,128,38,112,128,38,144,128,38,167,128,38,16,130,38,33,130,38,16,132,38,33,132,38,16,134,38,
|
||||
33,134,38,16,144,38,43,144,38,70,144,38,99,144,38,128,144,38,9,160,38,36,160,38,65,160,38,16,192,38,48,192,38,80,192,38,108,192,38,136,192,38,162,192,38,16,194,38,
|
||||
16,196,38,16,198,38,9,208,38,36,208,38,65,208,38,3,224,38,32,224,38,16,0,39,48,0,39,80,0,39,108,0,39,136,0,39,162,0,39,16,2,39,16,4,39,16,6,39,
|
||||
16,8,39,9,16,39,36,16,39,65,16,39,3,32,39,32,32,39,16,64,39,47,64,39,75,64,39,103,64,39,132,64,39,160,64,39,10,66,39,10,68,39,10,70,39,10,72,39,
|
||||
4,80,39,33,80,39,16,0,40,48,0,40,80,0,40,112,0,40,144,0,40,16,16,40,48,16,40,80,16,40,104,16,40,129,16,40,16,32,40,47,32,40,72,32,40,99,32,40,
|
||||
16,64,40,48,64,40,80,64,40,112,64,40,138,64,40,16,80,40,41,80,40,68,80,40,96,80,40,8,96,40,35,96,40,64,96,40,16,128,40,48,128,40,80,128,40,112,128,40,
|
||||
138,128,40,16,144,40,41,144,40,68,144,40,96,144,40,8,160,40,35,160,40,64,160,40,16,192,40,48,192,40,78,192,40,105,192,40,132,192,40,8,208,40,35,208,40,64,208,40,
|
||||
3,224,40,16,0,41,48,0,41,78,0,41,105,0,41,132,0,41,8,16,41,35,16,41,64,16,41,3,32,41,16,64,41,45,64,41,73,64,41,100,64,41,129,64,41,4,80,41,
|
||||
32,80,41,16,0,42,48,0,42,80,0,42,112,0,42,144,0,42,16,16,42,48,16,42,76,16,42,99,16,42,16,32,42,44,32,42,69,32,42,16,64,42,48,64,42,80,64,42,
|
||||
108,64,42,132,64,42,15,80,42,39,80,42,66,80,42,7,96,42,34,96,42,16,128,42,48,128,42,80,128,42,108,128,42,132,128,42,15,144,42,39,144,42,66,144,42,7,160,42,
|
||||
34,160,42,16,192,42,48,192,42,75,192,42,101,192,42,128,192,42,7,208,42,34,208,42,2,224,42,16,0,43,48,0,43,75,0,43,101,0,43,128,0,43,7,16,43,34,16,43,
|
||||
2,32,43,16,64,43,44,64,43,70,64,43,98,64,43,3,80,43,176,0,44,208,0,44,240,0,44,16,1,44,48,1,44,80,1,44,112,1,44,176,16,44,208,16,44,240,16,44,
|
||||
16,17,44,48,17,44,80,17,44,112,17,44,176,32,44,208,32,44,240,32,44,16,33,44,48,33,44,80,33,44,112,33,44,176,64,44,208,64,44,240,64,44,16,65,44,48,65,44,
|
||||
80,65,44,112,65,44,48,72,44,80,72,44,112,72,44,144,72,44,176,72,44,208,72,44,240,72,44,16,73,44,48,73,44,80,73,44,109,73,44,176,80,44,208,80,44,240,80,44,
|
||||
16,81,44,48,81,44,79,81,44,110,81,44,170,96,44,202,96,44,233,96,44,8,97,44,40,97,44,71,97,44,102,97,44,176,128,44,208,128,44,240,128,44,16,129,44,48,129,44,
|
||||
80,129,44,112,129,44,48,130,44,80,130,44,112,130,44,144,130,44,176,130,44,208,130,44,240,130,44,16,131,44,48,131,44,80,131,44,109,131,44,48,132,44,80,132,44,112,132,44,
|
||||
144,132,44,176,132,44,208,132,44,240,132,44,16,133,44,48,133,44,80,133,44,109,133,44,48,134,44,80,134,44,112,134,44,144,134,44,176,134,44,208,134,44,240,134,44,16,135,44,
|
||||
48,135,44,80,135,44,109,135,44,176,144,44,208,144,44,240,144,44,16,145,44,48,145,44,79,145,44,110,145,44,170,160,44,202,160,44,233,160,44,8,161,44,40,161,44,71,161,44,
|
||||
102,161,44,176,192,44,208,192,44,240,192,44,16,193,44,48,193,44,80,193,44,112,193,44,48,194,44,80,194,44,112,194,44,144,194,44,176,194,44,208,194,44,240,194,44,14,195,44,
|
||||
43,195,44,73,195,44,102,195,44,48,196,44,80,196,44,112,196,44,144,196,44,176,196,44,208,196,44,240,196,44,14,197,44,43,197,44,73,197,44,102,197,44,48,198,44,80,198,44,
|
||||
112,198,44,144,198,44,176,198,44,208,198,44,240,198,44,14,199,44,43,199,44,73,199,44,102,199,44,170,208,44,202,208,44,233,208,44,8,209,44,40,209,44,71,209,44,102,209,44,
|
||||
164,224,44,196,224,44,227,224,44,3,225,44,34,225,44,66,225,44,97,225,44,176,0,45,208,0,45,240,0,45,16,1,45,48,1,45,80,1,45,112,1,45,48,2,45,80,2,45,
|
||||
112,2,45,144,2,45,176,2,45,208,2,45,240,2,45,14,3,45,43,3,45,73,3,45,102,3,45,48,4,45,80,4,45,112,4,45,144,4,45,176,4,45,208,4,45,240,4,45,
|
||||
14,5,45,43,5,45,73,5,45,102,5,45,48,6,45,80,6,45,112,6,45,144,6,45,176,6,45,208,6,45,240,6,45,14,7,45,43,7,45,73,7,45,102,7,45,48,8,45,
|
||||
80,8,45,112,8,45,144,8,45,176,8,45,208,8,45,240,8,45,14,9,45,43,9,45,73,9,45,102,9,45,170,16,45,202,16,45,233,16,45,8,17,45,40,17,45,71,17,45,
|
||||
102,17,45,164,32,45,196,32,45,227,32,45,3,33,45,34,33,45,66,33,45,97,33,45,176,64,45,208,64,45,240,64,45,16,65,45,48,65,45,80,65,45,112,65,45,48,66,45,
|
||||
80,66,45,112,66,45,144,66,45,175,66,45,204,66,45,235,66,45,9,67,45,38,67,45,69,67,45,99,67,45,48,68,45,80,68,45,112,68,45,144,68,45,175,68,45,204,68,45,
|
||||
235,68,45,9,69,45,38,69,45,69,69,45,99,69,45,48,70,45,80,70,45,112,70,45,144,70,45,175,70,45,204,70,45,235,70,45,9,71,45,38,71,45,69,71,45,99,71,45,
|
||||
48,72,45,80,72,45,112,72,45,144,72,45,175,72,45,204,72,45,235,72,45,9,73,45,38,73,45,69,73,45,99,73,45,166,80,45,197,80,45,229,80,45,4,81,45,36,81,45,
|
||||
67,81,45,99,81,45,80,0,46,112,0,46,144,0,46,176,0,46,208,0,46,240,0,46,16,1,46,48,1,46,80,1,46,112,1,46,80,16,46,112,16,46,144,16,46,176,16,46,
|
||||
208,16,46,240,16,46,16,17,46,48,17,46,80,17,46,112,17,46,80,32,46,112,32,46,144,32,46,176,32,46,208,32,46,240,32,46,16,33,46,47,33,46,77,33,46,107,33,46,
|
||||
80,64,46,112,64,46,144,64,46,176,64,46,208,64,46,240,64,46,16,65,46,48,65,46,80,65,46,112,65,46,16,72,46,48,72,46,80,72,46,112,72,46,144,72,46,176,72,46,
|
||||
205,72,46,232,72,46,1,73,46,80,80,46,112,80,46,144,80,46,175,80,46,206,80,46,236,80,46,11,81,46,41,81,46,72,81,46,102,81,46,74,96,46,105,96,46,136,96,46,
|
||||
167,96,46,198,96,46,229,96,46,4,97,46,35,97,46,66,97,46,97,97,46,80,128,46,112,128,46,144,128,46,176,128,46,208,128,46,240,128,46,16,129,46,48,129,46,80,129,46,
|
||||
112,129,46,16,130,46,48,130,46,80,130,46,112,130,46,144,130,46,176,130,46,205,130,46,232,130,46,1,131,46,16,132,46,48,132,46,80,132,46,112,132,46,144,132,46,176,132,46,
|
||||
205,132,46,232,132,46,1,133,46,16,134,46,48,134,46,80,134,46,112,134,46,144,134,46,176,134,46,205,134,46,232,134,46,1,135,46,80,144,46,112,144,46,144,144,46,175,144,46,
|
||||
206,144,46,236,144,46,11,145,46,41,145,46,72,145,46,102,145,46,74,160,46,105,160,46,136,160,46,167,160,46,198,160,46,229,160,46,4,161,46,35,161,46,66,161,46,97,161,46,
|
||||
80,192,46,112,192,46,144,192,46,176,192,46,208,192,46,240,192,46,16,193,46,48,193,46,80,193,46,112,193,46,16,194,46,48,194,46,80,194,46,112,194,46,143,194,46,170,194,46,
|
||||
198,194,46,227,194,46,16,196,46,48,196,46,80,196,46,112,196,46,143,196,46,170,196,46,198,196,46,227,196,46,16,198,46,48,198,46,80,198,46,112,198,46,143,198,46,170,198,46,
|
||||
198,198,46,227,198,46,74,208,46,105,208,46,136,208,46,167,208,46,198,208,46,229,208,46,4,209,46,35,209,46,66,209,46,97,209,46,68,224,46,99,224,46,131,224,46,162,224,46,
|
||||
193,224,46,225,224,46,0,225,46,32,225,46,80,0,47,112,0,47,144,0,47,176,0,47,208,0,47,240,0,47,16,1,47,48,1,47,80,1,47,112,1,47,16,2,47,48,2,47,
|
||||
80,2,47,112,2,47,143,2,47,170,2,47,198,2,47,227,2,47,16,4,47,48,4,47,80,4,47,112,4,47,143,4,47,170,4,47,198,4,47,227,4,47,16,6,47,48,6,47,
|
||||
80,6,47,112,6,47,143,6,47,170,6,47,198,6,47,227,6,47,16,8,47,48,8,47,80,8,47,112,8,47,143,8,47,170,8,47,198,8,47,227,8,47,74,16,47,105,16,47,
|
||||
136,16,47,167,16,47,198,16,47,229,16,47,4,17,47,35,17,47,66,17,47,97,17,47,68,32,47,99,32,47,131,32,47,162,32,47,193,32,47,225,32,47,0,33,47,32,33,47,
|
||||
80,64,47,112,64,47,144,64,47,176,64,47,208,64,47,240,64,47,15,65,47,46,65,47,76,65,47,107,65,47,16,66,47,48,66,47,79,66,47,108,66,47,137,66,47,166,66,47,
|
||||
195,66,47,224,66,47,16,68,47,48,68,47,79,68,47,108,68,47,137,68,47,166,68,47,195,68,47,224,68,47,16,70,47,48,70,47,79,70,47,108,70,47,137,70,47,166,70,47,
|
||||
195,70,47,224,70,47,16,72,47,48,72,47,79,72,47,108,72,47,137,72,47,166,72,47,195,72,47,224,72,47,70,80,47,101,80,47,132,80,47,163,80,47,195,80,47,226,80,47,
|
||||
1,81,47,32,81,47,64,81,47,48,0,48,80,0,48,112,0,48,144,0,48,176,0,48,208,0,48,240,0,48,16,1,48,48,1,48,80,1,48,112,1,48,48,16,48,80,16,48,
|
||||
112,16,48,144,16,48,176,16,48,208,16,48,240,16,48,16,17,48,45,17,48,74,17,48,102,17,48,48,32,48,80,32,48,112,32,48,144,32,48,176,32,48,206,32,48,236,32,48,
|
||||
9,33,48,38,33,48,68,33,48,97,33,48,48,64,48,80,64,48,112,64,48,144,64,48,176,64,48,208,64,48,240,64,48,16,65,48,48,65,48,80,65,48,111,65,48,16,72,48,
|
||||
48,72,48,80,72,48,112,72,48,138,72,48,161,72,48,48,80,48,80,80,48,111,80,48,141,80,48,171,80,48,201,80,48,231,80,48,5,81,48,35,81,48,65,81,48,42,96,48,
|
||||
72,96,48,103,96,48,134,96,48,164,96,48,195,96,48,226,96,48,0,97,48,48,128,48,80,128,48,112,128,48,144,128,48,176,128,48,208,128,48,240,128,48,16,129,48,48,129,48,
|
||||
80,129,48,111,129,48,16,130,48,48,130,48,80,130,48,112,130,48,138,130,48,161,130,48,16,132,48,48,132,48,80,132,48,112,132,48,138,132,48,161,132,48,16,134,48,48,134,48,
|
||||
80,134,48,112,134,48,138,134,48,161,134,48,48,144,48,80,144,48,111,144,48,141,144,48,171,144,48,201,144,48,231,144,48,5,145,48,35,145,48,65,145,48,42,160,48,72,160,48,
|
||||
103,160,48,134,160,48,164,160,48,195,160,48,226,160,48,0,161,48,48,192,48,80,192,48,112,192,48,144,192,48,176,192,48,208,192,48,240,192,48,15,193,48,44,193,48,74,193,48,
|
||||
103,193,48,16,194,48,48,194,48,78,194,48,105,194,48,132,194,48,16,196,48,48,196,48,78,196,48,105,196,48,132,196,48,16,198,48,48,198,48,78,198,48,105,198,48,132,198,48,
|
||||
42,208,48,72,208,48,103,208,48,134,208,48,164,208,48,195,208,48,226,208,48,0,209,48,36,224,48,67,224,48,98,224,48,129,224,48,160,224,48,48,0,49,80,0,49,112,0,49,
|
||||
144,0,49,176,0,49,208,0,49,240,0,49,15,1,49,44,1,49,74,1,49,103,1,49,16,2,49,48,2,49,78,2,49,105,2,49,132,2,49,16,4,49,48,4,49,78,4,49,
|
||||
105,4,49,132,4,49,16,6,49,48,6,49,78,6,49,105,6,49,132,6,49,16,8,49,48,8,49,78,8,49,105,8,49,132,8,49,42,16,49,72,16,49,103,16,49,134,16,49,
|
||||
164,16,49,195,16,49,226,16,49,0,17,49,36,32,49,67,32,49,98,32,49,129,32,49,160,32,49,48,64,49,80,64,49,112,64,49,144,64,49,175,64,49,205,64,49,236,64,49,
|
||||
9,65,49,39,65,49,70,65,49,99,65,49,16,66,49,45,66,49,73,66,49,100,66,49,129,66,49,16,68,49,45,68,49,73,68,49,100,68,49,129,68,49,16,70,49,45,70,49,
|
||||
73,70,49,100,70,49,129,70,49,16,72,49,45,72,49,73,72,49,100,72,49,129,72,49,37,80,49,68,80,49,99,80,49,130,80,49,161,80,49,192,80,49,48,0,50,80,0,50,
|
||||
112,0,50,144,0,50,176,0,50,208,0,50,240,0,50,16,1,50,48,1,50,80,1,50,48,16,50,80,16,50,112,16,50,144,16,50,176,16,50,208,16,50,236,16,50,6,17,50,
|
||||
33,17,50,48,32,50,80,32,50,112,32,50,143,32,50,171,32,50,200,32,50,229,32,50,1,33,50,48,64,50,80,64,50,112,64,50,144,64,50,176,64,50,208,64,50,240,64,50,
|
||||
15,65,50,42,65,50,70,65,50,16,72,50,48,72,50,77,72,50,99,72,50,48,80,50,78,80,50,107,80,50,137,80,50,166,80,50,196,80,50,226,80,50,40,96,50,70,96,50,
|
||||
101,96,50,131,96,50,161,96,50,192,96,50,48,128,50,80,128,50,112,128,50,144,128,50,176,128,50,208,128,50,240,128,50,15,129,50,42,129,50,70,129,50,16,130,50,48,130,50,
|
||||
77,130,50,99,130,50,16,132,50,48,132,50,77,132,50,99,132,50,16,134,50,48,134,50,77,134,50,99,134,50,48,144,50,78,144,50,107,144,50,137,144,50,166,144,50,196,144,50,
|
||||
226,144,50,40,160,50,70,160,50,101,160,50,131,160,50,161,160,50,192,160,50,48,192,50,80,192,50,112,192,50,144,192,50,176,192,50,206,192,50,235,192,50,7,193,50,36,193,50,
|
||||
65,193,50,16,194,50,46,194,50,70,194,50,16,196,50,46,196,50,70,196,50,16,198,50,46,198,50,70,198,50,40,208,50,70,208,50,101,208,50,131,208,50,161,208,50,192,208,50,
|
||||
35,224,50,65,224,50,96,224,50,128,224,50,48,0,51,80,0,51,112,0,51,144,0,51,176,0,51,206,0,51,235,0,51,7,1,51,36,1,51,65,1,51,16,2,51,46,2,51,
|
||||
70,2,51,16,4,51,46,4,51,70,4,51,16,6,51,46,6,51,70,6,51,16,8,51,46,8,51,70,8,51,40,16,51,70,16,51,101,16,51,131,16,51,161,16,51,192,16,51,
|
||||
35,32,51,65,32,51,96,32,51,128,32,51,48,64,51,80,64,51,112,64,51,142,64,51,171,64,51,200,64,51,230,64,51,3,65,51,33,65,51,16,66,51,41,66,51,67,66,51,
|
||||
16,68,51,41,68,51,67,68,51,16,70,51,41,70,51,67,70,51,16,72,51,41,72,51,67,72,51,36,80,51,67,80,51,97,80,51,128,80,51,16,0,52,48,0,52,80,0,52,
|
||||
112,0,52,144,0,52,176,0,52,208,0,52,240,0,52,14,1,52,16,16,52,48,16,52,80,16,52,112,16,52,144,16,52,172,16,52,198,16,52,225,16,52,16,32,52,48,32,52,
|
||||
80,32,52,109,32,52,138,32,52,165,32,52,193,32,52,16,64,52,48,64,52,80,64,52,112,64,52,144,64,52,176,64,52,207,64,52,234,64,52,3,65,52,16,72,52,48,72,52,
|
||||
65,72,52,16,80,52,46,80,52,75,80,52,104,80,52,133,80,52,162,80,52,10,96,52,39,96,52,68,96,52,98,96,52,129,96,52,16,128,52,48,128,52,80,128,52,112,128,52,
|
||||
144,128,52,176,128,52,207,128,52,234,128,52,3,129,52,16,130,52,48,130,52,65,130,52,16,132,52,48,132,52,65,132,52,16,134,52,48,134,52,65,134,52,16,144,52,46,144,52,
|
||||
75,144,52,104,144,52,133,144,52,162,144,52,10,160,52,39,160,52,68,160,52,98,160,52,129,160,52,16,192,52,48,192,52,80,192,52,112,192,52,144,192,52,171,192,52,199,192,52,
|
||||
228,192,52,16,194,52,40,194,52,16,196,52,40,196,52,16,198,52,40,198,52,10,208,52,39,208,52,68,208,52,98,208,52,129,208,52,4,224,52,34,224,52,64,224,52,16,0,53,
|
||||
48,0,53,80,0,53,112,0,53,144,0,53,171,0,53,199,0,53,228,0,53,16,2,53,40,2,53,16,4,53,40,4,53,16,6,53,40,6,53,16,8,53,40,8,53,10,16,53,
|
||||
39,16,53,68,16,53,98,16,53,129,16,53,4,32,53,34,32,53,64,32,53,16,64,53,48,64,53,79,64,53,108,64,53,138,64,53,166,64,53,195,64,53,225,64,53,15,66,53,
|
||||
36,66,53,15,68,53,36,68,53,15,70,53,36,70,53,15,72,53,36,72,53,6,80,53,35,80,53,65,80,53,96,80,53,16,0,54,48,0,54,80,0,54,112,0,54,144,0,54,
|
||||
176,0,54,208,0,54,16,16,54,48,16,54,80,16,54,112,16,54,139,16,54,163,16,54,16,32,54,48,32,54,77,32,54,104,32,54,133,32,54,16,64,54,48,64,54,80,64,54,
|
||||
112,64,54,144,64,54,172,64,54,196,64,54,16,72,54,38,72,54,16,80,54,44,80,54,72,80,54,100,80,54,129,80,54,9,96,54,37,96,54,66,96,54,96,96,54,16,128,54,
|
||||
48,128,54,80,128,54,112,128,54,144,128,54,172,128,54,196,128,54,16,130,54,38,130,54,16,132,54,38,132,54,16,134,54,38,134,54,16,144,54,44,144,54,72,144,54,100,144,54,
|
||||
129,144,54,9,160,54,37,160,54,66,160,54,96,160,54,16,192,54,48,192,54,80,192,54,110,192,54,139,192,54,165,192,54,192,192,54,16,194,54,33,194,54,16,196,54,33,196,54,
|
||||
16,198,54,33,198,54,9,208,54,37,208,54,66,208,54,96,208,54,3,224,54,33,224,54,16,0,55,48,0,55,80,0,55,110,0,55,139,0,55,165,0,55,192,0,55,16,2,55,
|
||||
33,2,55,16,4,55,33,4,55,16,6,55,33,6,55,16,8,55,33,8,55,9,16,55,37,16,55,66,16,55,96,16,55,3,32,55,33,32,55,16,64,55,48,64,55,76,64,55,
|
||||
105,64,55,134,64,55,162,64,55,12,66,55,12,68,55,12,70,55,12,72,55,5,80,55,34,80,55,64,80,55,16,0,56,48,0,56,80,0,56,112,0,56,144,0,56,174,0,56,
|
||||
16,16,56,48,16,56,80,16,56,106,16,56,131,16,56,16,32,56,47,32,56,73,32,56,100,32,56,16,64,56,48,64,56,80,64,56,112,64,56,140,64,56,163,64,56,16,72,56,
|
||||
16,80,56,41,80,56,69,80,56,97,80,56,8,96,56,35,96,56,64,96,56,16,128,56,48,128,56,80,128,56,112,128,56,140,128,56,163,128,56,16,130,56,16,132,56,16,134,56,
|
||||
16,144,56,41,144,56,69,144,56,97,144,56,8,160,56,35,160,56,64,160,56,16,192,56,48,192,56,79,192,56,106,192,56,133,192,56,14,194,56,14,196,56,14,198,56,8,208,56,
|
||||
35,208,56,64,208,56,3,224,56,32,224,56,16,0,57,48,0,57,79,0,57,106,0,57,133,0,57,14,2,57,14,4,57,14,6,57,14,8,57,8,16,57,35,16,57,64,16,57,
|
||||
3,32,57,32,32,57,16,64,57,46,64,57,73,64,57,101,64,57,130,64,57,9,66,57,9,68,57,9,70,57,9,72,57,4,80,57,32,80,57,16,0,58,48,0,58,80,0,58,
|
||||
112,0,58,144,0,58,16,16,58,48,16,58,76,16,58,99,16,58,16,32,58,44,32,58,69,32,58,16,64,58,48,64,58,80,64,58,108,64,58,132,64,58,15,80,58,39,80,58,
|
||||
66,80,58,7,96,58,34,96,58,16,128,58,48,128,58,80,128,58,108,128,58,132,128,58,15,144,58,39,144,58,66,144,58,7,160,58,34,160,58,16,192,58,48,192,58,75,192,58,
|
||||
101,192,58,128,192,58,7,208,58,34,208,58,2,224,58,16,0,59,48,0,59,75,0,59,101,0,59,128,0,59,7,16,59,34,16,59,2,32,59,16,64,59,44,64,59,70,64,59,
|
||||
98,64,59,3,80,59,16,0,60,48,0,60,80,0,60,112,0,60,16,16,60,48,16,60,70,16,60,16,32,60,41,32,60,65,32,60,16,64,60,48,64,60,79,64,60,100,64,60,
|
||||
14,80,60,37,80,60,6,96,60,32,96,60,16,128,60,48,128,60,79,128,60,100,128,60,14,144,60,37,144,60,6,160,60,32,160,60,16,192,60,47,192,60,71,192,60,96,192,60,
|
||||
6,208,60,32,208,60,1,224,60,16,0,61,47,0,61,71,0,61,96,0,61,6,16,61,32,16,61,1,32,61,16,64,61,41,64,61,67,64,61,3,80,61,16,0,62,48,0,62,
|
||||
80,0,62,16,16,62,45,16,62,64,16,62,16,32,62,38,32,62,16,64,62,48,64,62,73,64,62,12,80,62,34,80,62,5,96,62,16,128,62,48,128,62,73,128,62,12,144,62,
|
||||
34,144,62,5,160,62,16,192,62,44,192,62,67,192,62,5,208,62,1,224,62,16,0,63,44,0,63,67,0,63,5,16,63,1,32,63,16,64,63,39,64,63,64,64,63,2,80,63,
|
||||
16,0,64,48,0,64,78,0,64,16,16,64,40,16,64,16,32,64,35,32,64,16,64,64,48,64,64,67,64,64,11,80,64,32,80,64,4,96,64,16,128,64,48,128,64,67,128,64,
|
||||
11,144,64,32,144,64,4,160,64,16,192,64,41,192,64,4,208,64,0,224,64,16,0,65,41,0,65,4,16,65,0,32,65,15,64,65,36,64,65,1,80,65,112,0,66,144,0,66,
|
||||
176,0,66,208,0,66,240,0,66,16,1,66,48,1,66,80,1,66,112,1,66,112,16,66,144,16,66,176,16,66,208,16,66,240,16,66,16,17,66,48,17,66,80,17,66,112,17,66,
|
||||
112,32,66,144,32,66,176,32,66,208,32,66,240,32,66,16,33,66,48,33,66,80,33,66,112,33,66,112,64,66,144,64,66,176,64,66,208,64,66,240,64,66,16,65,66,48,65,66,
|
||||
80,65,66,112,65,66,48,72,66,80,72,66,112,72,66,144,72,66,176,72,66,208,72,66,240,72,66,13,73,66,40,73,66,68,73,66,112,80,66,144,80,66,176,80,66,208,80,66,
|
||||
239,80,66,14,81,66,44,81,66,76,81,66,106,81,66,106,96,66,138,96,66,169,96,66,200,96,66,231,96,66,6,97,66,37,97,66,69,97,66,100,97,66,112,128,66,144,128,66,
|
||||
176,128,66,208,128,66,240,128,66,16,129,66,48,129,66,80,129,66,112,129,66,48,130,66,80,130,66,112,130,66,144,130,66,176,130,66,208,130,66,240,130,66,13,131,66,40,131,66,
|
||||
68,131,66,48,132,66,80,132,66,112,132,66,144,132,66,176,132,66,208,132,66,240,132,66,13,133,66,40,133,66,68,133,66,48,134,66,80,134,66,112,134,66,144,134,66,176,134,66,
|
||||
208,134,66,240,134,66,13,135,66,40,135,66,68,135,66,112,144,66,144,144,66,176,144,66,208,144,66,239,144,66,14,145,66,44,145,66,76,145,66,106,145,66,106,160,66,138,160,66,
|
||||
169,160,66,200,160,66,231,160,66,6,161,66,37,161,66,69,161,66,100,161,66,112,192,66,144,192,66,176,192,66,208,192,66,240,192,66,16,193,66,48,193,66,80,193,66,112,193,66,
|
||||
48,194,66,80,194,66,112,194,66,144,194,66,176,194,66,205,194,66,234,194,66,6,195,66,35,195,66,64,195,66,48,196,66,80,196,66,112,196,66,144,196,66,176,196,66,205,196,66,
|
||||
234,196,66,6,197,66,35,197,66,64,197,66,48,198,66,80,198,66,112,198,66,144,198,66,176,198,66,205,198,66,234,198,66,6,199,66,35,199,66,64,199,66,106,208,66,138,208,66,
|
||||
169,208,66,200,208,66,231,208,66,6,209,66,37,209,66,69,209,66,100,209,66,100,224,66,132,224,66,163,224,66,195,224,66,226,224,66,1,225,66,33,225,66,64,225,66,96,225,66,
|
||||
112,0,67,144,0,67,176,0,67,208,0,67,240,0,67,16,1,67,48,1,67,80,1,67,112,1,67,48,2,67,80,2,67,112,2,67,144,2,67,176,2,67,205,2,67,234,2,67,
|
||||
6,3,67,35,3,67,64,3,67,48,4,67,80,4,67,112,4,67,144,4,67,176,4,67,205,4,67,234,4,67,6,5,67,35,5,67,64,5,67,48,6,67,80,6,67,112,6,67,
|
||||
144,6,67,176,6,67,205,6,67,234,6,67,6,7,67,35,7,67,64,7,67,48,8,67,80,8,67,112,8,67,144,8,67,176,8,67,205,8,67,234,8,67,6,9,67,35,9,67,
|
||||
64,9,67,106,16,67,138,16,67,169,16,67,200,16,67,231,16,67,6,17,67,37,17,67,69,17,67,100,17,67,100,32,67,132,32,67,163,32,67,195,32,67,226,32,67,1,33,67,
|
||||
33,33,67,64,33,67,96,33,67,112,64,67,144,64,67,176,64,67,208,64,67,240,64,67,16,65,67,48,65,67,80,65,67,111,65,67,48,66,67,80,66,67,111,66,67,141,66,67,
|
||||
170,66,67,199,66,67,230,66,67,3,67,67,32,67,67,48,68,67,80,68,67,111,68,67,141,68,67,170,68,67,199,68,67,230,68,67,3,69,67,32,69,67,48,70,67,80,70,67,
|
||||
111,70,67,141,70,67,170,70,67,199,70,67,230,70,67,3,71,67,32,71,67,48,72,67,80,72,67,111,72,67,141,72,67,170,72,67,199,72,67,230,72,67,3,73,67,32,73,67,
|
||||
102,80,67,133,80,67,164,80,67,196,80,67,227,80,67,3,81,67,34,81,67,65,81,67,97,81,67,48,0,68,80,0,68,112,0,68,144,0,68,176,0,68,208,0,68,240,0,68,
|
||||
16,1,68,48,1,68,80,1,68,112,1,68,48,16,68,80,16,68,112,16,68,144,16,68,176,16,68,208,16,68,240,16,68,16,17,68,48,17,68,78,17,68,106,17,68,48,32,68,
|
||||
80,32,68,112,32,68,144,32,68,176,32,68,208,32,68,238,32,68,11,33,68,41,33,68,71,33,68,100,33,68,48,64,68,80,64,68,112,64,68,144,64,68,176,64,68,208,64,68,
|
||||
240,64,68,16,65,68,48,65,68,80,65,68,112,65,68,16,72,68,48,72,68,80,72,68,112,72,68,143,72,68,166,72,68,48,80,68,80,80,68,112,80,68,142,80,68,172,80,68,
|
||||
202,80,68,233,80,68,6,81,68,36,81,68,67,81,68,97,81,68,42,96,68,73,96,68,104,96,68,135,96,68,165,96,68,196,96,68,227,96,68,1,97,68,32,97,68,48,128,68,
|
||||
80,128,68,112,128,68,144,128,68,176,128,68,208,128,68,240,128,68,16,129,68,48,129,68,80,129,68,112,129,68,16,130,68,48,130,68,80,130,68,112,130,68,143,130,68,166,130,68,
|
||||
16,132,68,48,132,68,80,132,68,112,132,68,143,132,68,166,132,68,16,134,68,48,134,68,80,134,68,112,134,68,143,134,68,166,134,68,48,144,68,80,144,68,112,144,68,142,144,68,
|
||||
172,144,68,202,144,68,233,144,68,6,145,68,36,145,68,67,145,68,97,145,68,42,160,68,73,160,68,104,160,68,135,160,68,165,160,68,196,160,68,227,160,68,1,161,68,32,161,68,
|
||||
48,192,68,80,192,68,112,192,68,144,192,68,176,192,68,208,192,68,240,192,68,16,193,68,47,193,68,77,193,68,106,193,68,16,194,68,48,194,68,80,194,68,107,194,68,135,194,68,
|
||||
161,194,68,16,196,68,48,196,68,80,196,68,107,196,68,135,196,68,161,196,68,16,198,68,48,198,68,80,198,68,107,198,68,135,198,68,161,198,68,42,208,68,73,208,68,104,208,68,
|
||||
135,208,68,165,208,68,196,208,68,227,208,68,1,209,68,32,209,68,36,224,68,67,224,68,98,224,68,130,224,68,161,224,68,192,224,68,48,0,69,80,0,69,112,0,69,144,0,69,
|
||||
176,0,69,208,0,69,240,0,69,16,1,69,47,1,69,77,1,69,106,1,69,16,2,69,48,2,69,80,2,69,107,2,69,135,2,69,161,2,69,16,4,69,48,4,69,80,4,69,
|
||||
107,4,69,135,4,69,161,4,69,16,6,69,48,6,69,80,6,69,107,6,69,135,6,69,161,6,69,16,8,69,48,8,69,80,8,69,107,8,69,135,8,69,161,8,69,42,16,69,
|
||||
73,16,69,104,16,69,135,16,69,165,16,69,196,16,69,227,16,69,1,17,69,32,17,69,36,32,69,67,32,69,98,32,69,130,32,69,161,32,69,192,32,69,48,64,69,80,64,69,
|
||||
112,64,69,144,64,69,176,64,69,207,64,69,237,64,69,11,65,69,41,65,69,71,65,69,101,65,69,16,66,69,47,66,69,74,66,69,102,66,69,131,66,69,16,68,69,47,68,69,
|
||||
74,68,69,102,68,69,131,68,69,16,70,69,47,70,69,74,70,69,102,70,69,131,70,69,16,72,69,47,72,69,74,72,69,102,72,69,131,72,69,38,80,69,68,80,69,100,80,69,
|
||||
131,80,69,162,80,69,193,80,69,224,80,69,48,0,70,80,0,70,112,0,70,144,0,70,176,0,70,208,0,70,240,0,70,16,1,70,48,1,70,80,1,70,48,16,70,80,16,70,
|
||||
112,16,70,144,16,70,176,16,70,208,16,70,236,16,70,6,17,70,33,17,70,48,32,70,80,32,70,112,32,70,143,32,70,171,32,70,200,32,70,229,32,70,1,33,70,48,64,70,
|
||||
80,64,70,112,64,70,144,64,70,176,64,70,208,64,70,240,64,70,15,65,70,42,65,70,70,65,70,16,72,70,48,72,70,77,72,70,99,72,70,48,80,70,78,80,70,107,80,70,
|
||||
137,80,70,166,80,70,196,80,70,226,80,70,40,96,70,70,96,70,101,96,70,131,96,70,161,96,70,192,96,70,48,128,70,80,128,70,112,128,70,144,128,70,176,128,70,208,128,70,
|
||||
240,128,70,15,129,70,42,129,70,70,129,70,16,130,70,48,130,70,77,130,70,99,130,70,16,132,70,48,132,70,77,132,70,99,132,70,16,134,70,48,134,70,77,134,70,99,134,70,
|
||||
48,144,70,78,144,70,107,144,70,137,144,70,166,144,70,196,144,70,226,144,70,40,160,70,70,160,70,101,160,70,131,160,70,161,160,70,192,160,70,48,192,70,80,192,70,112,192,70,
|
||||
144,192,70,176,192,70,206,192,70,235,192,70,7,193,70,36,193,70,65,193,70,16,194,70,46,194,70,70,194,70,16,196,70,46,196,70,70,196,70,16,198,70,46,198,70,70,198,70,
|
||||
40,208,70,70,208,70,101,208,70,131,208,70,161,208,70,192,208,70,35,224,70,65,224,70,96,224,70,128,224,70,48,0,71,80,0,71,112,0,71,144,0,71,176,0,71,206,0,71,
|
||||
235,0,71,7,1,71,36,1,71,65,1,71,16,2,71,46,2,71,70,2,71,16,4,71,46,4,71,70,4,71,16,6,71,46,6,71,70,6,71,16,8,71,46,8,71,70,8,71,
|
||||
40,16,71,70,16,71,101,16,71,131,16,71,161,16,71,192,16,71,35,32,71,65,32,71,96,32,71,128,32,71,48,64,71,80,64,71,112,64,71,142,64,71,171,64,71,200,64,71,
|
||||
230,64,71,3,65,71,33,65,71,16,66,71,41,66,71,67,66,71,16,68,71,41,68,71,67,68,71,16,70,71,41,70,71,67,70,71,16,72,71,41,72,71,67,72,71,36,80,71,
|
||||
67,80,71,97,80,71,128,80,71,16,0,72,48,0,72,80,0,72,112,0,72,144,0,72,176,0,72,208,0,72,240,0,72,16,16,72,48,16,72,80,16,72,112,16,72,144,16,72,
|
||||
170,16,72,195,16,72,16,32,72,48,32,72,80,32,72,108,32,72,137,32,72,164,32,72,16,64,72,48,64,72,80,64,72,112,64,72,144,64,72,176,64,72,204,64,72,231,64,72,
|
||||
16,72,72,45,72,72,16,80,72,46,80,72,74,80,72,103,80,72,132,80,72,161,80,72,10,96,72,38,96,72,68,96,72,98,96,72,128,96,72,16,128,72,48,128,72,80,128,72,
|
||||
112,128,72,144,128,72,176,128,72,204,128,72,231,128,72,16,130,72,45,130,72,16,132,72,45,132,72,16,134,72,45,134,72,16,144,72,46,144,72,74,144,72,103,144,72,132,144,72,
|
||||
161,144,72,10,160,72,38,160,72,68,160,72,98,160,72,128,160,72,16,192,72,48,192,72,80,192,72,112,192,72,143,192,72,170,192,72,197,192,72,226,192,72,16,194,72,38,194,72,
|
||||
16,196,72,38,196,72,16,198,72,38,198,72,10,208,72,38,208,72,68,208,72,98,208,72,128,208,72,4,224,72,33,224,72,64,224,72,16,0,73,48,0,73,80,0,73,112,0,73,
|
||||
143,0,73,170,0,73,197,0,73,226,0,73,16,2,73,38,2,73,16,4,73,38,4,73,16,6,73,38,6,73,16,8,73,38,8,73,10,16,73,38,16,73,68,16,73,98,16,73,
|
||||
128,16,73,4,32,73,33,32,73,64,32,73,16,64,73,48,64,73,79,64,73,107,64,73,137,64,73,165,64,73,194,64,73,224,64,73,14,66,73,35,66,73,14,68,73,35,68,73,
|
||||
14,70,73,35,70,73,14,72,73,35,72,73,6,80,73,35,80,73,65,80,73,16,0,74,48,0,74,80,0,74,112,0,74,144,0,74,176,0,74,16,16,74,48,16,74,80,16,74,
|
||||
109,16,74,135,16,74,16,32,74,48,32,74,75,32,74,102,32,74,130,32,74,16,64,74,48,64,74,80,64,74,112,64,74,144,64,74,167,64,74,16,72,74,33,72,74,16,80,74,
|
||||
43,80,74,70,80,74,99,80,74,128,80,74,9,96,74,36,96,74,65,96,74,16,128,74,48,128,74,80,128,74,112,128,74,144,128,74,167,128,74,16,130,74,33,130,74,16,132,74,
|
||||
33,132,74,16,134,74,33,134,74,16,144,74,43,144,74,70,144,74,99,144,74,128,144,74,9,160,74,36,160,74,65,160,74,16,192,74,48,192,74,80,192,74,108,192,74,136,192,74,
|
||||
162,192,74,16,194,74,16,196,74,16,198,74,9,208,74,36,208,74,65,208,74,3,224,74,32,224,74,16,0,75,48,0,75,80,0,75,108,0,75,136,0,75,162,0,75,16,2,75,
|
||||
16,4,75,16,6,75,16,8,75,9,16,75,36,16,75,65,16,75,3,32,75,32,32,75,16,64,75,47,64,75,75,64,75,103,64,75,132,64,75,160,64,75,10,66,75,10,68,75,
|
||||
10,70,75,10,72,75,4,80,75,33,80,75,16,0,76,48,0,76,80,0,76,112,0,76,144,0,76,16,16,76,48,16,76,77,16,76,100,16,76,16,32,76,45,32,76,70,32,76,
|
||||
96,32,76,16,64,76,48,64,76,80,64,76,109,64,76,135,64,76,16,80,76,40,80,76,67,80,76,8,96,76,34,96,76,16,128,76,48,128,76,80,128,76,109,128,76,135,128,76,
|
||||
16,144,76,40,144,76,67,144,76,8,160,76,34,160,76,16,192,76,48,192,76,76,192,76,102,192,76,130,192,76,8,208,76,34,208,76,2,224,76,16,0,77,48,0,77,76,0,77,
|
||||
102,0,77,130,0,77,8,16,77,34,16,77,2,32,77,16,64,77,44,64,77,71,64,77,99,64,77,4,80,77,32,80,77,16,0,78,48,0,78,80,0,78,112,0,78,16,16,78,
|
||||
48,16,78,70,16,78,16,32,78,41,32,78,65,32,78,16,64,78,48,64,78,79,64,78,100,64,78,14,80,78,37,80,78,6,96,78,32,96,78,16,128,78,48,128,78,79,128,78,
|
||||
100,128,78,14,144,78,37,144,78,6,160,78,32,160,78,16,192,78,47,192,78,71,192,78,96,192,78,6,208,78,32,208,78,1,224,78,16,0,79,47,0,79,71,0,79,96,0,79,
|
||||
6,16,79,32,16,79,1,32,79,16,64,79,41,64,79,67,64,79,3,80,79,16,0,80,48,0,80,80,0,80,16,16,80,44,16,80,16,32,80,37,32,80,16,64,80,48,64,80,
|
||||
71,64,80,12,80,80,34,80,80,5,96,80,16,128,80,48,128,80,71,128,80,12,144,80,34,144,80,5,160,80,16,192,80,43,192,80,66,192,80,5,208,80,1,224,80,16,0,81,
|
||||
43,0,81,66,0,81,5,16,81,1,32,81,16,64,81,38,64,81,64,64,81,2,80,81,16,0,82,48,0,82,16,16,82,38,16,82,16,32,82,33,32,82,16,64,82,47,64,82,
|
||||
10,80,82,4,96,82,16,128,82,47,128,82,10,144,82,4,160,82,16,192,82,39,192,82,4,208,82,0,224,82,16,0,83,39,0,83,4,16,83,0,32,83,15,64,83,35,64,83,
|
||||
1,80,83,16,0,84,48,0,84,16,16,84,32,16,84,14,32,84,16,64,84,41,64,84,8,80,84,3,96,84,16,128,84,41,128,84,8,144,84,3,160,84,16,192,84,35,192,84,
|
||||
3,208,84,16,0,85,35,0,85,3,16,85,13,64,85,32,64,85,0,80,85,16,0,86,46,0,86,16,16,86,11,32,86,16,64,86,35,64,86,6,80,86,1,96,86,16,128,86,
|
||||
35,128,86,6,144,86,1,160,86,16,192,86,1,208,86,16,0,87,1,16,87,11,64,87,80,0,88,112,0,88,144,0,88,176,0,88,208,0,88,240,0,88,16,1,88,48,1,88,
|
||||
80,1,88,112,1,88,80,16,88,112,16,88,144,16,88,176,16,88,208,16,88,240,16,88,16,17,88,48,17,88,80,17,88,112,17,88,80,32,88,112,32,88,144,32,88,176,32,88,
|
||||
208,32,88,240,32,88,16,33,88,47,33,88,77,33,88,107,33,88,80,64,88,112,64,88,144,64,88,176,64,88,208,64,88,240,64,88,16,65,88,48,65,88,80,65,88,112,65,88,
|
||||
16,72,88,48,72,88,80,72,88,112,72,88,144,72,88,176,72,88,205,72,88,232,72,88,1,73,88,80,80,88,112,80,88,144,80,88,175,80,88,206,80,88,236,80,88,11,81,88,
|
||||
41,81,88,72,81,88,102,81,88,74,96,88,105,96,88,136,96,88,167,96,88,198,96,88,229,96,88,4,97,88,35,97,88,66,97,88,97,97,88,80,128,88,112,128,88,144,128,88,
|
||||
176,128,88,208,128,88,240,128,88,16,129,88,48,129,88,80,129,88,112,129,88,16,130,88,48,130,88,80,130,88,112,130,88,144,130,88,176,130,88,205,130,88,232,130,88,1,131,88,
|
||||
16,132,88,48,132,88,80,132,88,112,132,88,144,132,88,176,132,88,205,132,88,232,132,88,1,133,88,16,134,88,48,134,88,80,134,88,112,134,88,144,134,88,176,134,88,205,134,88,
|
||||
232,134,88,1,135,88,80,144,88,112,144,88,144,144,88,175,144,88,206,144,88,236,144,88,11,145,88,41,145,88,72,145,88,102,145,88,74,160,88,105,160,88,136,160,88,167,160,88,
|
||||
198,160,88,229,160,88,4,161,88,35,161,88,66,161,88,97,161,88,80,192,88,112,192,88,144,192,88,176,192,88,208,192,88,240,192,88,16,193,88,48,193,88,80,193,88,112,193,88,
|
||||
16,194,88,48,194,88,80,194,88,112,194,88,143,194,88,170,194,88,198,194,88,227,194,88,16,196,88,48,196,88,80,196,88,112,196,88,143,196,88,170,196,88,198,196,88,227,196,88,
|
||||
16,198,88,48,198,88,80,198,88,112,198,88,143,198,88,170,198,88,198,198,88,227,198,88,74,208,88,105,208,88,136,208,88,167,208,88,198,208,88,229,208,88,4,209,88,35,209,88,
|
||||
66,209,88,97,209,88,68,224,88,99,224,88,131,224,88,162,224,88,193,224,88,225,224,88,0,225,88,32,225,88,80,0,89,112,0,89,144,0,89,176,0,89,208,0,89,240,0,89,
|
||||
16,1,89,48,1,89,80,1,89,112,1,89,16,2,89,48,2,89,80,2,89,112,2,89,143,2,89,170,2,89,198,2,89,227,2,89,16,4,89,48,4,89,80,4,89,112,4,89,
|
||||
143,4,89,170,4,89,198,4,89,227,4,89,16,6,89,48,6,89,80,6,89,112,6,89,143,6,89,170,6,89,198,6,89,227,6,89,16,8,89,48,8,89,80,8,89,112,8,89,
|
||||
143,8,89,170,8,89,198,8,89,227,8,89,74,16,89,105,16,89,136,16,89,167,16,89,198,16,89,229,16,89,4,17,89,35,17,89,66,17,89,97,17,89,68,32,89,99,32,89,
|
||||
131,32,89,162,32,89,193,32,89,225,32,89,0,33,89,32,33,89,80,64,89,112,64,89,144,64,89,176,64,89,208,64,89,240,64,89,15,65,89,46,65,89,76,65,89,107,65,89,
|
||||
16,66,89,48,66,89,79,66,89,108,66,89,137,66,89,166,66,89,195,66,89,224,66,89,16,68,89,48,68,89,79,68,89,108,68,89,137,68,89,166,68,89,195,68,89,224,68,89,
|
||||
16,70,89,48,70,89,79,70,89,108,70,89,137,70,89,166,70,89,195,70,89,224,70,89,16,72,89,48,72,89,79,72,89,108,72,89,137,72,89,166,72,89,195,72,89,224,72,89,
|
||||
70,80,89,101,80,89,132,80,89,163,80,89,195,80,89,226,80,89,1,81,89,32,81,89,64,81,89,48,0,90,80,0,90,112,0,90,144,0,90,176,0,90,208,0,90,240,0,90,
|
||||
16,1,90,48,1,90,80,1,90,112,1,90,48,16,90,80,16,90,112,16,90,144,16,90,176,16,90,208,16,90,240,16,90,12,17,90,39,17,90,68,17,90,48,32,90,80,32,90,
|
||||
112,32,90,144,32,90,174,32,90,203,32,90,233,32,90,5,33,90,34,33,90,64,33,90,48,64,90,80,64,90,112,64,90,144,64,90,176,64,90,208,64,90,240,64,90,16,65,90,
|
||||
48,65,90,77,65,90,103,65,90,16,72,90,48,72,90,80,72,90,106,72,90,131,72,90,48,80,90,79,80,90,109,80,90,139,80,90,169,80,90,198,80,90,228,80,90,2,81,90,
|
||||
32,81,90,41,96,90,71,96,90,102,96,90,133,96,90,163,96,90,193,96,90,224,96,90,48,128,90,80,128,90,112,128,90,144,128,90,176,128,90,208,128,90,240,128,90,16,129,90,
|
||||
48,129,90,77,129,90,103,129,90,16,130,90,48,130,90,80,130,90,106,130,90,131,130,90,16,132,90,48,132,90,80,132,90,106,132,90,131,132,90,16,134,90,48,134,90,80,134,90,
|
||||
106,134,90,131,134,90,48,144,90,79,144,90,109,144,90,139,144,90,169,144,90,198,144,90,228,144,90,2,145,90,32,145,90,41,160,90,71,160,90,102,160,90,133,160,90,163,160,90,
|
||||
193,160,90,224,160,90,48,192,90,80,192,90,112,192,90,144,192,90,176,192,90,208,192,90,239,192,90,11,193,90,40,193,90,70,193,90,98,193,90,16,194,90,48,194,90,74,194,90,
|
||||
100,194,90,16,196,90,48,196,90,74,196,90,100,196,90,16,198,90,48,198,90,74,198,90,100,198,90,41,208,90,71,208,90,102,208,90,133,208,90,163,208,90,193,208,90,224,208,90,
|
||||
35,224,90,66,224,90,97,224,90,128,224,90,48,0,91,80,0,91,112,0,91,144,0,91,176,0,91,208,0,91,239,0,91,11,1,91,40,1,91,70,1,91,98,1,91,16,2,91,
|
||||
48,2,91,74,2,91,100,2,91,16,4,91,48,4,91,74,4,91,100,4,91,16,6,91,48,6,91,74,6,91,100,6,91,16,8,91,48,8,91,74,8,91,100,8,91,41,16,91,
|
||||
71,16,91,102,16,91,133,16,91,163,16,91,193,16,91,224,16,91,35,32,91,66,32,91,97,32,91,128,32,91,48,64,91,80,64,91,112,64,91,144,64,91,173,64,91,203,64,91,
|
||||
233,64,91,6,65,91,36,65,91,66,65,91,96,65,91,16,66,91,43,66,91,70,66,91,97,66,91,16,68,91,43,68,91,70,68,91,97,68,91,16,70,91,43,70,91,70,70,91,
|
||||
97,70,91,16,72,91,43,72,91,70,72,91,97,72,91,37,80,91,67,80,91,98,80,91,129,80,91,160,80,91,16,0,92,48,0,92,80,0,92,112,0,92,144,0,92,176,0,92,
|
||||
208,0,92,240,0,92,14,1,92,16,16,92,48,16,92,80,16,92,112,16,92,144,16,92,172,16,92,198,16,92,225,16,92,16,32,92,48,32,92,80,32,92,109,32,92,138,32,92,
|
||||
165,32,92,193,32,92,16,64,92,48,64,92,80,64,92,112,64,92,144,64,92,176,64,92,207,64,92,234,64,92,3,65,92,16,72,92,48,72,92,65,72,92,16,80,92,46,80,92,
|
||||
75,80,92,104,80,92,133,80,92,162,80,92,10,96,92,39,96,92,68,96,92,98,96,92,129,96,92,16,128,92,48,128,92,80,128,92,112,128,92,144,128,92,176,128,92,207,128,92,
|
||||
234,128,92,3,129,92,16,130,92,48,130,92,65,130,92,16,132,92,48,132,92,65,132,92,16,134,92,48,134,92,65,134,92,16,144,92,46,144,92,75,144,92,104,144,92,133,144,92,
|
||||
162,144,92,10,160,92,39,160,92,68,160,92,98,160,92,129,160,92,16,192,92,48,192,92,80,192,92,112,192,92,144,192,92,171,192,92,199,192,92,228,192,92,16,194,92,40,194,92,
|
||||
16,196,92,40,196,92,16,198,92,40,198,92,10,208,92,39,208,92,68,208,92,98,208,92,129,208,92,4,224,92,34,224,92,64,224,92,16,0,93,48,0,93,80,0,93,112,0,93,
|
||||
144,0,93,171,0,93,199,0,93,228,0,93,16,2,93,40,2,93,16,4,93,40,4,93,16,6,93,40,6,93,16,8,93,40,8,93,10,16,93,39,16,93,68,16,93,98,16,93,
|
||||
129,16,93,4,32,93,34,32,93,64,32,93,16,64,93,48,64,93,79,64,93,108,64,93,138,64,93,166,64,93,195,64,93,225,64,93,15,66,93,36,66,93,15,68,93,36,68,93,
|
||||
15,70,93,36,70,93,15,72,93,36,72,93,6,80,93,35,80,93,65,80,93,96,80,93,16,0,94,48,0,94,80,0,94,112,0,94,144,0,94,176,0,94,16,16,94,48,16,94,
|
||||
80,16,94,109,16,94,135,16,94,16,32,94,48,32,94,75,32,94,102,32,94,130,32,94,16,64,94,48,64,94,80,64,94,112,64,94,144,64,94,167,64,94,16,72,94,33,72,94,
|
||||
16,80,94,43,80,94,70,80,94,99,80,94,128,80,94,9,96,94,36,96,94,65,96,94,16,128,94,48,128,94,80,128,94,112,128,94,144,128,94,167,128,94,16,130,94,33,130,94,
|
||||
16,132,94,33,132,94,16,134,94,33,134,94,16,144,94,43,144,94,70,144,94,99,144,94,128,144,94,9,160,94,36,160,94,65,160,94,16,192,94,48,192,94,80,192,94,108,192,94,
|
||||
136,192,94,162,192,94,16,194,94,16,196,94,16,198,94,9,208,94,36,208,94,65,208,94,3,224,94,32,224,94,16,0,95,48,0,95,80,0,95,108,0,95,136,0,95,162,0,95,
|
||||
16,2,95,16,4,95,16,6,95,16,8,95,9,16,95,36,16,95,65,16,95,3,32,95,32,32,95,16,64,95,47,64,95,75,64,95,103,64,95,132,64,95,160,64,95,10,66,95,
|
||||
10,68,95,10,70,95,10,72,95,4,80,95,33,80,95,16,0,96,48,0,96,80,0,96,112,0,96,144,0,96,16,16,96,48,16,96,76,16,96,99,16,96,16,32,96,44,32,96,
|
||||
69,32,96,16,64,96,48,64,96,80,64,96,108,64,96,132,64,96,15,80,96,39,80,96,66,80,96,7,96,96,34,96,96,16,128,96,48,128,96,80,128,96,108,128,96,132,128,96,
|
||||
15,144,96,39,144,96,66,144,96,7,160,96,34,160,96,16,192,96,48,192,96,75,192,96,101,192,96,128,192,96,7,208,96,34,208,96,2,224,96,16,0,97,48,0,97,75,0,97,
|
||||
101,0,97,128,0,97,7,16,97,34,16,97,2,32,97,16,64,97,44,64,97,70,64,97,98,64,97,3,80,97,16,0,98,48,0,98,80,0,98,16,16,98,47,16,98,67,16,98,
|
||||
16,32,98,39,32,98,16,64,98,48,64,98,76,64,98,13,80,98,35,80,98,6,96,98,16,128,98,48,128,98,76,128,98,13,144,98,35,144,98,6,160,98,16,192,98,45,192,98,
|
||||
69,192,98,6,208,98,1,224,98,16,0,99,45,0,99,69,0,99,6,16,99,1,32,99,16,64,99,40,64,99,66,64,99,2,80,99,16,0,100,48,0,100,78,0,100,16,16,100,
|
||||
40,16,100,16,32,100,35,32,100,16,64,100,48,64,100,67,64,100,11,80,100,32,80,100,4,96,100,16,128,100,48,128,100,67,128,100,11,144,100,32,144,100,4,160,100,16,192,100,
|
||||
41,192,100,4,208,100,0,224,100,16,0,101,41,0,101,4,16,101,0,32,101,15,64,101,36,64,101,1,80,101,16,0,102,48,0,102,16,16,102,33,16,102,14,32,102,16,64,102,
|
||||
42,64,102,9,80,102,3,96,102,16,128,102,42,128,102,9,144,102,3,160,102,16,192,102,36,192,102,3,208,102,16,0,103,36,0,103,3,16,103,13,64,103,33,64,103,0,80,103,
|
||||
16,0,104,46,0,104,16,16,104,11,32,104,16,64,104,35,64,104,6,80,104,1,96,104,16,128,104,35,128,104,6,144,104,1,160,104,16,192,104,1,208,104,16,0,105,1,16,105,
|
||||
11,64,105,80,0,110,112,0,110,144,0,110,176,0,110,208,0,110,240,0,110,16,1,110,48,1,110,80,1,110,112,1,110,80,16,110,112,16,110,144,16,110,176,16,110,208,16,110,
|
||||
240,16,110,16,17,110,48,17,110,80,17,110,109,17,110,80,32,110,112,32,110,144,32,110,176,32,110,208,32,110,240,32,110,13,33,110,43,33,110,73,33,110,102,33,110,80,64,110,
|
||||
112,64,110,144,64,110,176,64,110,208,64,110,240,64,110,16,65,110,48,65,110,80,65,110,112,65,110,16,72,110,48,72,110,80,72,110,112,72,110,144,72,110,170,72,110,195,72,110,
|
||||
80,80,110,112,80,110,143,80,110,173,80,110,203,80,110,234,80,110,8,81,110,38,81,110,68,81,110,99,81,110,73,96,110,104,96,110,135,96,110,166,96,110,197,96,110,228,96,110,
|
||||
2,97,110,33,97,110,64,97,110,80,128,110,112,128,110,144,128,110,176,128,110,208,128,110,240,128,110,16,129,110,48,129,110,80,129,110,112,129,110,16,130,110,48,130,110,80,130,110,
|
||||
112,130,110,144,130,110,170,130,110,195,130,110,16,132,110,48,132,110,80,132,110,112,132,110,144,132,110,170,132,110,195,132,110,16,134,110,48,134,110,80,134,110,112,134,110,144,134,110,
|
||||
170,134,110,195,134,110,80,144,110,112,144,110,143,144,110,173,144,110,203,144,110,234,144,110,8,145,110,38,145,110,68,145,110,99,145,110,73,160,110,104,160,110,135,160,110,166,160,110,
|
||||
197,160,110,228,160,110,2,161,110,33,161,110,64,161,110,80,192,110,112,192,110,144,192,110,176,192,110,208,192,110,240,192,110,16,193,110,48,193,110,79,193,110,108,193,110,16,194,110,
|
||||
48,194,110,80,194,110,109,194,110,138,194,110,164,194,110,16,196,110,48,196,110,80,196,110,109,196,110,138,196,110,164,196,110,16,198,110,48,198,110,80,198,110,109,198,110,138,198,110,
|
||||
164,198,110,73,208,110,104,208,110,135,208,110,166,208,110,197,208,110,228,208,110,2,209,110,33,209,110,64,209,110,67,224,110,99,224,110,130,224,110,161,224,110,192,224,110,224,224,110,
|
||||
80,0,111,112,0,111,144,0,111,176,0,111,208,0,111,240,0,111,16,1,111,48,1,111,79,1,111,108,1,111,16,2,111,48,2,111,80,2,111,109,2,111,138,2,111,164,2,111,
|
||||
16,4,111,48,4,111,80,4,111,109,4,111,138,4,111,164,4,111,16,6,111,48,6,111,80,6,111,109,6,111,138,6,111,164,6,111,16,8,111,48,8,111,80,8,111,109,8,111,
|
||||
138,8,111,164,8,111,73,16,111,104,16,111,135,16,111,166,16,111,197,16,111,228,16,111,2,17,111,33,17,111,64,17,111,67,32,111,99,32,111,130,32,111,161,32,111,192,32,111,
|
||||
224,32,111,80,64,111,112,64,111,144,64,111,176,64,111,208,64,111,238,64,111,12,65,111,42,65,111,73,65,111,103,65,111,16,66,111,48,66,111,76,66,111,104,66,111,133,66,111,
|
||||
161,66,111,16,68,111,48,68,111,76,68,111,104,68,111,133,68,111,161,68,111,16,70,111,48,70,111,76,70,111,104,70,111,133,70,111,161,70,111,16,72,111,48,72,111,76,72,111,
|
||||
104,72,111,133,72,111,161,72,111,69,80,111,100,80,111,131,80,111,162,80,111,193,80,111,225,80,111,0,81,111,48,0,112,80,0,112,112,0,112,144,0,112,176,0,112,208,0,112,
|
||||
240,0,112,16,1,112,48,1,112,48,16,112,80,16,112,112,16,112,144,16,112,176,16,112,205,16,112,233,16,112,3,17,112,48,32,112,80,32,112,112,32,112,142,32,112,170,32,112,
|
||||
198,32,112,227,32,112,48,64,112,80,64,112,112,64,112,144,64,112,176,64,112,208,64,112,240,64,112,12,65,112,39,65,112,16,72,112,48,72,112,74,72,112,48,80,112,77,80,112,
|
||||
106,80,112,136,80,112,165,80,112,195,80,112,224,80,112,40,96,112,70,96,112,100,96,112,131,96,112,161,96,112,48,128,112,80,128,112,112,128,112,144,128,112,176,128,112,208,128,112,
|
||||
240,128,112,12,129,112,39,129,112,16,130,112,48,130,112,74,130,112,16,132,112,48,132,112,74,132,112,16,134,112,48,134,112,74,134,112,48,144,112,77,144,112,106,144,112,136,144,112,
|
||||
165,144,112,195,144,112,224,144,112,40,160,112,70,160,112,100,160,112,131,160,112,161,160,112,48,192,112,80,192,112,112,192,112,144,192,112,176,192,112,204,192,112,233,192,112,5,193,112,
|
||||
34,193,112,16,194,112,44,194,112,68,194,112,16,196,112,44,196,112,68,196,112,16,198,112,44,198,112,68,198,112,40,208,112,70,208,112,100,208,112,131,208,112,161,208,112,35,224,112,
|
||||
65,224,112,96,224,112,48,0,113,80,0,113,112,0,113,144,0,113,176,0,113,204,0,113,233,0,113,5,1,113,34,1,113,16,2,113,44,2,113,68,2,113,16,4,113,44,4,113,
|
||||
68,4,113,16,6,113,44,6,113,68,6,113,16,8,113,44,8,113,68,8,113,40,16,113,70,16,113,100,16,113,131,16,113,161,16,113,35,32,113,65,32,113,96,32,113,48,64,113,
|
||||
80,64,113,111,64,113,141,64,113,170,64,113,199,64,113,229,64,113,2,65,113,16,66,113,39,66,113,65,66,113,16,68,113,39,68,113,65,68,113,16,70,113,39,70,113,65,70,113,
|
||||
16,72,113,39,72,113,65,72,113,36,80,113,66,80,113,97,80,113,128,80,113,16,0,114,48,0,114,80,0,114,112,0,114,144,0,114,176,0,114,208,0,114,16,16,114,48,16,114,
|
||||
80,16,114,112,16,114,139,16,114,163,16,114,16,32,114,48,32,114,77,32,114,104,32,114,133,32,114,16,64,114,48,64,114,80,64,114,112,64,114,144,64,114,172,64,114,196,64,114,
|
||||
16,72,114,38,72,114,16,80,114,44,80,114,72,80,114,100,80,114,129,80,114,9,96,114,37,96,114,66,96,114,96,96,114,16,128,114,48,128,114,80,128,114,112,128,114,144,128,114,
|
||||
172,128,114,196,128,114,16,130,114,38,130,114,16,132,114,38,132,114,16,134,114,38,134,114,16,144,114,44,144,114,72,144,114,100,144,114,129,144,114,9,160,114,37,160,114,66,160,114,
|
||||
96,160,114,16,192,114,48,192,114,80,192,114,110,192,114,139,192,114,165,192,114,192,192,114,16,194,114,33,194,114,16,196,114,33,196,114,16,198,114,33,198,114,9,208,114,37,208,114,
|
||||
66,208,114,96,208,114,3,224,114,33,224,114,16,0,115,48,0,115,80,0,115,110,0,115,139,0,115,165,0,115,192,0,115,16,2,115,33,2,115,16,4,115,33,4,115,16,6,115,
|
||||
33,6,115,16,8,115,33,8,115,9,16,115,37,16,115,66,16,115,96,16,115,3,32,115,33,32,115,16,64,115,48,64,115,76,64,115,105,64,115,134,64,115,162,64,115,12,66,115,
|
||||
12,68,115,12,70,115,12,72,115,5,80,115,34,80,115,64,80,115,16,0,116,48,0,116,80,0,116,112,0,116,144,0,116,16,16,116,48,16,116,77,16,116,100,16,116,16,32,116,
|
||||
45,32,116,70,32,116,96,32,116,16,64,116,48,64,116,80,64,116,109,64,116,135,64,116,16,80,116,40,80,116,67,80,116,8,96,116,34,96,116,16,128,116,48,128,116,80,128,116,
|
||||
109,128,116,135,128,116,16,144,116,40,144,116,67,144,116,8,160,116,34,160,116,16,192,116,48,192,116,76,192,116,102,192,116,130,192,116,8,208,116,34,208,116,2,224,116,16,0,117,
|
||||
48,0,117,76,0,117,102,0,117,130,0,117,8,16,117,34,16,117,2,32,117,16,64,117,44,64,117,71,64,117,99,64,117,4,80,117,32,80,117,16,0,118,48,0,118,80,0,118,
|
||||
16,16,118,47,16,118,67,16,118,16,32,118,39,32,118,16,64,118,48,64,118,76,64,118,13,80,118,35,80,118,6,96,118,16,128,118,48,128,118,76,128,118,13,144,118,35,144,118,
|
||||
6,160,118,16,192,118,45,192,118,69,192,118,6,208,118,1,224,118,16,0,119,45,0,119,69,0,119,6,16,119,1,32,119,16,64,119,40,64,119,66,64,119,2,80,119,16,0,120,
|
||||
48,0,120,16,16,120,39,16,120,16,32,120,34,32,120,16,64,120,48,64,120,10,80,120,4,96,120,16,128,120,48,128,120,10,144,120,4,160,120,16,192,120,40,192,120,4,208,120,
|
||||
0,224,120,16,0,121,40,0,121,4,16,121,0,32,121,15,64,121,36,64,121,1,80,121,16,0,122,48,0,122,16,16,122,13,32,122,16,64,122,39,64,122,8,80,122,2,96,122,
|
||||
16,128,122,39,128,122,8,144,122,2,160,122,16,192,122,34,192,122,2,208,122,16,0,123,34,0,123,2,16,123,12,64,123,32,64,123,0,80,123,16,0,124,16,16,124,10,32,124,
|
||||
16,64,124,5,80,124,1,96,124,16,128,124,5,144,124,1,160,124,16,192,124,1,208,124,16,0,125,1,16,125,10,64,125,48,0,132,80,0,132,112,0,132,144,0,132,176,0,132,
|
||||
208,0,132,240,0,132,16,1,132,48,1,132,80,1,132,112,1,132,48,16,132,80,16,132,112,16,132,144,16,132,176,16,132,208,16,132,240,16,132,16,17,132,45,17,132,74,17,132,
|
||||
102,17,132,48,32,132,80,32,132,112,32,132,144,32,132,176,32,132,206,32,132,236,32,132,9,33,132,38,33,132,68,33,132,97,33,132,48,64,132,80,64,132,112,64,132,144,64,132,
|
||||
176,64,132,208,64,132,240,64,132,16,65,132,48,65,132,80,65,132,111,65,132,16,72,132,48,72,132,80,72,132,112,72,132,138,72,132,161,72,132,48,80,132,80,80,132,111,80,132,
|
||||
141,80,132,171,80,132,201,80,132,231,80,132,5,81,132,35,81,132,65,81,132,42,96,132,72,96,132,103,96,132,134,96,132,164,96,132,195,96,132,226,96,132,0,97,132,48,128,132,
|
||||
80,128,132,112,128,132,144,128,132,176,128,132,208,128,132,240,128,132,16,129,132,48,129,132,80,129,132,111,129,132,16,130,132,48,130,132,80,130,132,112,130,132,138,130,132,161,130,132,
|
||||
16,132,132,48,132,132,80,132,132,112,132,132,138,132,132,161,132,132,16,134,132,48,134,132,80,134,132,112,134,132,138,134,132,161,134,132,48,144,132,80,144,132,111,144,132,141,144,132,
|
||||
171,144,132,201,144,132,231,144,132,5,145,132,35,145,132,65,145,132,42,160,132,72,160,132,103,160,132,134,160,132,164,160,132,195,160,132,226,160,132,0,161,132,48,192,132,80,192,132,
|
||||
112,192,132,144,192,132,176,192,132,208,192,132,240,192,132,15,193,132,44,193,132,74,193,132,103,193,132,16,194,132,48,194,132,78,194,132,105,194,132,132,194,132,16,196,132,48,196,132,
|
||||
78,196,132,105,196,132,132,196,132,16,198,132,48,198,132,78,198,132,105,198,132,132,198,132,42,208,132,72,208,132,103,208,132,134,208,132,164,208,132,195,208,132,226,208,132,0,209,132,
|
||||
36,224,132,67,224,132,98,224,132,129,224,132,160,224,132,48,0,133,80,0,133,112,0,133,144,0,133,176,0,133,208,0,133,240,0,133,15,1,133,44,1,133,74,1,133,103,1,133,
|
||||
16,2,133,48,2,133,78,2,133,105,2,133,132,2,133,16,4,133,48,4,133,78,4,133,105,4,133,132,4,133,16,6,133,48,6,133,78,6,133,105,6,133,132,6,133,16,8,133,
|
||||
48,8,133,78,8,133,105,8,133,132,8,133,42,16,133,72,16,133,103,16,133,134,16,133,164,16,133,195,16,133,226,16,133,0,17,133,36,32,133,67,32,133,98,32,133,129,32,133,
|
||||
160,32,133,48,64,133,80,64,133,112,64,133,144,64,133,175,64,133,205,64,133,236,64,133,9,65,133,39,65,133,70,65,133,99,65,133,16,66,133,45,66,133,73,66,133,100,66,133,
|
||||
129,66,133,16,68,133,45,68,133,73,68,133,100,68,133,129,68,133,16,70,133,45,70,133,73,70,133,100,70,133,129,70,133,16,72,133,45,72,133,73,72,133,100,72,133,129,72,133,
|
||||
37,80,133,68,80,133,99,80,133,130,80,133,161,80,133,192,80,133,16,0,134,48,0,134,80,0,134,112,0,134,144,0,134,176,0,134,208,0,134,240,0,134,14,1,134,16,16,134,
|
||||
48,16,134,80,16,134,112,16,134,144,16,134,172,16,134,198,16,134,225,16,134,16,32,134,48,32,134,80,32,134,109,32,134,138,32,134,165,32,134,193,32,134,16,64,134,48,64,134,
|
||||
80,64,134,112,64,134,144,64,134,176,64,134,207,64,134,234,64,134,3,65,134,16,72,134,48,72,134,65,72,134,16,80,134,46,80,134,75,80,134,104,80,134,133,80,134,162,80,134,
|
||||
10,96,134,39,96,134,68,96,134,98,96,134,129,96,134,16,128,134,48,128,134,80,128,134,112,128,134,144,128,134,176,128,134,207,128,134,234,128,134,3,129,134,16,130,134,48,130,134,
|
||||
65,130,134,16,132,134,48,132,134,65,132,134,16,134,134,48,134,134,65,134,134,16,144,134,46,144,134,75,144,134,104,144,134,133,144,134,162,144,134,10,160,134,39,160,134,68,160,134,
|
||||
98,160,134,129,160,134,16,192,134,48,192,134,80,192,134,112,192,134,144,192,134,171,192,134,199,192,134,228,192,134,16,194,134,40,194,134,16,196,134,40,196,134,16,198,134,40,198,134,
|
||||
10,208,134,39,208,134,68,208,134,98,208,134,129,208,134,4,224,134,34,224,134,64,224,134,16,0,135,48,0,135,80,0,135,112,0,135,144,0,135,171,0,135,199,0,135,228,0,135,
|
||||
16,2,135,40,2,135,16,4,135,40,4,135,16,6,135,40,6,135,16,8,135,40,8,135,10,16,135,39,16,135,68,16,135,98,16,135,129,16,135,4,32,135,34,32,135,64,32,135,
|
||||
16,64,135,48,64,135,79,64,135,108,64,135,138,64,135,166,64,135,195,64,135,225,64,135,15,66,135,36,66,135,15,68,135,36,68,135,15,70,135,36,70,135,15,72,135,36,72,135,
|
||||
6,80,135,35,80,135,65,80,135,96,80,135,16,0,136,48,0,136,80,0,136,112,0,136,144,0,136,174,0,136,16,16,136,48,16,136,80,16,136,106,16,136,131,16,136,16,32,136,
|
||||
47,32,136,73,32,136,100,32,136,16,64,136,48,64,136,80,64,136,112,64,136,140,64,136,163,64,136,16,72,136,16,80,136,41,80,136,69,80,136,97,80,136,8,96,136,35,96,136,
|
||||
64,96,136,16,128,136,48,128,136,80,128,136,112,128,136,140,128,136,163,128,136,16,130,136,16,132,136,16,134,136,16,144,136,41,144,136,69,144,136,97,144,136,8,160,136,35,160,136,
|
||||
64,160,136,16,192,136,48,192,136,79,192,136,106,192,136,133,192,136,14,194,136,14,196,136,14,198,136,8,208,136,35,208,136,64,208,136,3,224,136,32,224,136,16,0,137,48,0,137,
|
||||
79,0,137,106,0,137,133,0,137,14,2,137,14,4,137,14,6,137,14,8,137,8,16,137,35,16,137,64,16,137,3,32,137,32,32,137,16,64,137,46,64,137,73,64,137,101,64,137,
|
||||
130,64,137,9,66,137,9,68,137,9,70,137,9,72,137,4,80,137,32,80,137,16,0,138,48,0,138,80,0,138,112,0,138,16,16,138,48,16,138,70,16,138,16,32,138,41,32,138,
|
||||
65,32,138,16,64,138,48,64,138,79,64,138,100,64,138,14,80,138,37,80,138,6,96,138,32,96,138,16,128,138,48,128,138,79,128,138,100,128,138,14,144,138,37,144,138,6,160,138,
|
||||
32,160,138,16,192,138,47,192,138,71,192,138,96,192,138,6,208,138,32,208,138,1,224,138,16,0,139,47,0,139,71,0,139,96,0,139,6,16,139,32,16,139,1,32,139,16,64,139,
|
||||
41,64,139,67,64,139,3,80,139,16,0,140,48,0,140,78,0,140,16,16,140,40,16,140,16,32,140,35,32,140,16,64,140,48,64,140,67,64,140,11,80,140,32,80,140,4,96,140,
|
||||
16,128,140,48,128,140,67,128,140,11,144,140,32,144,140,4,160,140,16,192,140,41,192,140,4,208,140,0,224,140,16,0,141,41,0,141,4,16,141,0,32,141,15,64,141,36,64,141,
|
||||
1,80,141,16,0,142,48,0,142,16,16,142,13,32,142,16,64,142,39,64,142,8,80,142,2,96,142,16,128,142,39,128,142,8,144,142,2,160,142,16,192,142,34,192,142,2,208,142,
|
||||
16,0,143,34,0,143,2,16,143,12,64,143,32,64,143,0,80,143,16,0,144,16,16,144,9,32,144,16,64,144,5,80,144,0,96,144,16,128,144,5,144,144,0,160,144,15,192,144,
|
||||
0,208,144,15,0,145,0,16,145,9,64,145,48,0,154,80,0,154,112,0,154,144,0,154,176,0,154,208,0,154,240,0,154,16,1,154,48,1,154,80,1,154,112,1,154,48,16,154,
|
||||
80,16,154,112,16,154,144,16,154,176,16,154,208,16,154,240,16,154,12,17,154,39,17,154,68,17,154,48,32,154,80,32,154,112,32,154,144,32,154,174,32,154,203,32,154,233,32,154,
|
||||
5,33,154,34,33,154,64,33,154,48,64,154,80,64,154,112,64,154,144,64,154,176,64,154,208,64,154,240,64,154,16,65,154,48,65,154,77,65,154,103,65,154,16,72,154,48,72,154,
|
||||
80,72,154,106,72,154,131,72,154,48,80,154,79,80,154,109,80,154,139,80,154,169,80,154,198,80,154,228,80,154,2,81,154,32,81,154,41,96,154,71,96,154,102,96,154,133,96,154,
|
||||
163,96,154,193,96,154,224,96,154,48,128,154,80,128,154,112,128,154,144,128,154,176,128,154,208,128,154,240,128,154,16,129,154,48,129,154,77,129,154,103,129,154,16,130,154,48,130,154,
|
||||
80,130,154,106,130,154,131,130,154,16,132,154,48,132,154,80,132,154,106,132,154,131,132,154,16,134,154,48,134,154,80,134,154,106,134,154,131,134,154,48,144,154,79,144,154,109,144,154,
|
||||
139,144,154,169,144,154,198,144,154,228,144,154,2,145,154,32,145,154,41,160,154,71,160,154,102,160,154,133,160,154,163,160,154,193,160,154,224,160,154,48,192,154,80,192,154,112,192,154,
|
||||
144,192,154,176,192,154,208,192,154,239,192,154,11,193,154,40,193,154,70,193,154,98,193,154,16,194,154,48,194,154,74,194,154,100,194,154,16,196,154,48,196,154,74,196,154,100,196,154,
|
||||
16,198,154,48,198,154,74,198,154,100,198,154,41,208,154,71,208,154,102,208,154,133,208,154,163,208,154,193,208,154,224,208,154,35,224,154,66,224,154,97,224,154,128,224,154,48,0,155,
|
||||
80,0,155,112,0,155,144,0,155,176,0,155,208,0,155,239,0,155,11,1,155,40,1,155,70,1,155,98,1,155,16,2,155,48,2,155,74,2,155,100,2,155,16,4,155,48,4,155,
|
||||
74,4,155,100,4,155,16,6,155,48,6,155,74,6,155,100,6,155,16,8,155,48,8,155,74,8,155,100,8,155,41,16,155,71,16,155,102,16,155,133,16,155,163,16,155,193,16,155,
|
||||
224,16,155,35,32,155,66,32,155,97,32,155,128,32,155,48,64,155,80,64,155,112,64,155,144,64,155,173,64,155,203,64,155,233,64,155,6,65,155,36,65,155,66,65,155,96,65,155,
|
||||
16,66,155,43,66,155,70,66,155,97,66,155,16,68,155,43,68,155,70,68,155,97,68,155,16,70,155,43,70,155,70,70,155,97,70,155,16,72,155,43,72,155,70,72,155,97,72,155,
|
||||
37,80,155,67,80,155,98,80,155,129,80,155,160,80,155,16,0,156,48,0,156,80,0,156,112,0,156,144,0,156,176,0,156,208,0,156,16,16,156,48,16,156,80,16,156,112,16,156,
|
||||
141,16,156,165,16,156,16,32,156,48,32,156,78,32,156,106,32,156,134,32,156,161,32,156,16,64,156,48,64,156,80,64,156,112,64,156,144,64,156,174,64,156,199,64,156,16,72,156,
|
||||
40,72,156,16,80,156,44,80,156,73,80,156,101,80,156,130,80,156,10,96,156,37,96,156,67,96,156,97,96,156,16,128,156,48,128,156,80,128,156,112,128,156,144,128,156,174,128,156,
|
||||
199,128,156,16,130,156,40,130,156,16,132,156,40,132,156,16,134,156,40,134,156,16,144,156,44,144,156,73,144,156,101,144,156,130,144,156,10,160,156,37,160,156,67,160,156,97,160,156,
|
||||
16,192,156,48,192,156,80,192,156,112,192,156,140,192,156,167,192,156,194,192,156,16,194,156,35,194,156,16,196,156,35,196,156,16,198,156,35,198,156,10,208,156,37,208,156,67,208,156,
|
||||
97,208,156,4,224,156,33,224,156,16,0,157,48,0,157,80,0,157,112,0,157,140,0,157,167,0,157,194,0,157,16,2,157,35,2,157,16,4,157,35,4,157,16,6,157,35,6,157,
|
||||
16,8,157,35,8,157,10,16,157,37,16,157,67,16,157,97,16,157,4,32,157,33,32,157,16,64,157,48,64,157,77,64,157,106,64,157,135,64,157,163,64,157,192,64,157,12,66,157,
|
||||
32,66,157,12,68,157,32,68,157,12,70,157,32,70,157,12,72,157,32,72,157,5,80,157,34,80,157,64,80,157,16,0,158,48,0,158,80,0,158,112,0,158,144,0,158,16,16,158,
|
||||
48,16,158,76,16,158,99,16,158,16,32,158,44,32,158,69,32,158,16,64,158,48,64,158,80,64,158,108,64,158,132,64,158,15,80,158,39,80,158,66,80,158,7,96,158,34,96,158,
|
||||
16,128,158,48,128,158,80,128,158,108,128,158,132,128,158,15,144,158,39,144,158,66,144,158,7,160,158,34,160,158,16,192,158,48,192,158,75,192,158,101,192,158,128,192,158,7,208,158,
|
||||
34,208,158,2,224,158,16,0,159,48,0,159,75,0,159,101,0,159,128,0,159,7,16,159,34,16,159,2,32,159,16,64,159,44,64,159,70,64,159,98,64,159,3,80,159,16,0,160,
|
||||
48,0,160,80,0,160,16,16,160,44,16,160,16,32,160,37,32,160,16,64,160,48,64,160,71,64,160,12,80,160,34,80,160,5,96,160,16,128,160,48,128,160,71,128,160,12,144,160,
|
||||
34,144,160,5,160,160,16,192,160,43,192,160,66,192,160,5,208,160,1,224,160,16,0,161,43,0,161,66,0,161,5,16,161,1,32,161,16,64,161,38,64,161,64,64,161,2,80,161,
|
||||
16,0,162,48,0,162,16,16,162,33,16,162,14,32,162,16,64,162,42,64,162,9,80,162,3,96,162,16,128,162,42,128,162,9,144,162,3,160,162,16,192,162,36,192,162,3,208,162,
|
||||
16,0,163,36,0,163,3,16,163,13,64,163,33,64,163,0,80,163,16,0,164,16,16,164,10,32,164,16,64,164,5,80,164,1,96,164,16,128,164,5,144,164,1,160,164,16,192,164,
|
||||
1,208,164,16,0,165,1,16,165,10,64,165,48,0,176,80,0,176,112,0,176,144,0,176,176,0,176,208,0,176,240,0,176,16,1,176,48,1,176,80,1,176,48,16,176,80,16,176,
|
||||
112,16,176,144,16,176,176,16,176,208,16,176,236,16,176,6,17,176,33,17,176,48,32,176,80,32,176,112,32,176,143,32,176,171,32,176,200,32,176,229,32,176,1,33,176,48,64,176,
|
||||
80,64,176,112,64,176,144,64,176,176,64,176,208,64,176,240,64,176,15,65,176,42,65,176,70,65,176,16,72,176,48,72,176,77,72,176,99,72,176,48,80,176,78,80,176,107,80,176,
|
||||
137,80,176,166,80,176,196,80,176,226,80,176,40,96,176,70,96,176,101,96,176,131,96,176,161,96,176,192,96,176,48,128,176,80,128,176,112,128,176,144,128,176,176,128,176,208,128,176,
|
||||
240,128,176,15,129,176,42,129,176,70,129,176,16,130,176,48,130,176,77,130,176,99,130,176,16,132,176,48,132,176,77,132,176,99,132,176,16,134,176,48,134,176,77,134,176,99,134,176,
|
||||
48,144,176,78,144,176,107,144,176,137,144,176,166,144,176,196,144,176,226,144,176,40,160,176,70,160,176,101,160,176,131,160,176,161,160,176,192,160,176,48,192,176,80,192,176,112,192,176,
|
||||
144,192,176,176,192,176,206,192,176,235,192,176,7,193,176,36,193,176,65,193,176,16,194,176,46,194,176,70,194,176,16,196,176,46,196,176,70,196,176,16,198,176,46,198,176,70,198,176,
|
||||
40,208,176,70,208,176,101,208,176,131,208,176,161,208,176,192,208,176,35,224,176,65,224,176,96,224,176,128,224,176,48,0,177,80,0,177,112,0,177,144,0,177,176,0,177,206,0,177,
|
||||
235,0,177,7,1,177,36,1,177,65,1,177,16,2,177,46,2,177,70,2,177,16,4,177,46,4,177,70,4,177,16,6,177,46,6,177,70,6,177,16,8,177,46,8,177,70,8,177,
|
||||
40,16,177,70,16,177,101,16,177,131,16,177,161,16,177,192,16,177,35,32,177,65,32,177,96,32,177,128,32,177,48,64,177,80,64,177,112,64,177,142,64,177,171,64,177,200,64,177,
|
||||
230,64,177,3,65,177,33,65,177,16,66,177,41,66,177,67,66,177,16,68,177,41,68,177,67,68,177,16,70,177,41,70,177,67,70,177,16,72,177,41,72,177,67,72,177,36,80,177,
|
||||
67,80,177,97,80,177,128,80,177,16,0,178,48,0,178,80,0,178,112,0,178,144,0,178,176,0,178,16,16,178,48,16,178,80,16,178,109,16,178,135,16,178,16,32,178,48,32,178,
|
||||
75,32,178,102,32,178,130,32,178,16,64,178,48,64,178,80,64,178,112,64,178,144,64,178,167,64,178,16,72,178,33,72,178,16,80,178,43,80,178,70,80,178,99,80,178,128,80,178,
|
||||
9,96,178,36,96,178,65,96,178,16,128,178,48,128,178,80,128,178,112,128,178,144,128,178,167,128,178,16,130,178,33,130,178,16,132,178,33,132,178,16,134,178,33,134,178,16,144,178,
|
||||
43,144,178,70,144,178,99,144,178,128,144,178,9,160,178,36,160,178,65,160,178,16,192,178,48,192,178,80,192,178,108,192,178,136,192,178,162,192,178,16,194,178,16,196,178,16,198,178,
|
||||
9,208,178,36,208,178,65,208,178,3,224,178,32,224,178,16,0,179,48,0,179,80,0,179,108,0,179,136,0,179,162,0,179,16,2,179,16,4,179,16,6,179,16,8,179,9,16,179,
|
||||
36,16,179,65,16,179,3,32,179,32,32,179,16,64,179,47,64,179,75,64,179,103,64,179,132,64,179,160,64,179,10,66,179,10,68,179,10,70,179,10,72,179,4,80,179,33,80,179,
|
||||
16,0,180,48,0,180,80,0,180,112,0,180,16,16,180,48,16,180,70,16,180,16,32,180,41,32,180,65,32,180,16,64,180,48,64,180,79,64,180,100,64,180,14,80,180,37,80,180,
|
||||
6,96,180,32,96,180,16,128,180,48,128,180,79,128,180,100,128,180,14,144,180,37,144,180,6,160,180,32,160,180,16,192,180,47,192,180,71,192,180,96,192,180,6,208,180,32,208,180,
|
||||
1,224,180,16,0,181,47,0,181,71,0,181,96,0,181,6,16,181,32,16,181,1,32,181,16,64,181,41,64,181,67,64,181,3,80,181,16,0,182,48,0,182,16,16,182,38,16,182,
|
||||
16,32,182,33,32,182,16,64,182,47,64,182,10,80,182,4,96,182,16,128,182,47,128,182,10,144,182,4,160,182,16,192,182,39,192,182,4,208,182,0,224,182,16,0,183,39,0,183,
|
||||
4,16,183,0,32,183,15,64,183,35,64,183,1,80,183,16,0,184,46,0,184,16,16,184,11,32,184,16,64,184,35,64,184,6,80,184,1,96,184,16,128,184,35,128,184,6,144,184,
|
||||
1,160,184,16,192,184,1,208,184,16,0,185,1,16,185,11,64,185,48,0,198,80,0,198,112,0,198,144,0,198,176,0,198,208,0,198,240,0,198,16,1,198,46,1,198,48,16,198,
|
||||
80,16,198,112,16,198,144,16,198,176,16,198,202,16,198,230,16,198,0,17,198,48,32,198,80,32,198,111,32,198,140,32,198,168,32,198,196,32,198,225,32,198,48,64,198,80,64,198,
|
||||
112,64,198,144,64,198,176,64,198,208,64,198,239,64,198,9,65,198,35,65,198,16,72,198,48,72,198,71,72,198,47,80,198,76,80,198,105,80,198,135,80,198,164,80,198,193,80,198,
|
||||
39,96,198,69,96,198,99,96,198,130,96,198,160,96,198,48,128,198,80,128,198,112,128,198,144,128,198,176,128,198,208,128,198,239,128,198,9,129,198,35,129,198,16,130,198,48,130,198,
|
||||
71,130,198,16,132,198,48,132,198,71,132,198,16,134,198,48,134,198,71,134,198,47,144,198,76,144,198,105,144,198,135,144,198,164,144,198,193,144,198,39,160,198,69,160,198,99,160,198,
|
||||
130,160,198,160,160,198,48,192,198,80,192,198,112,192,198,144,192,198,174,192,198,202,192,198,231,192,198,3,193,198,16,194,198,43,194,198,66,194,198,16,196,198,43,196,198,66,196,198,
|
||||
16,198,198,43,198,198,66,198,198,39,208,198,69,208,198,99,208,198,130,208,198,160,208,198,34,224,198,65,224,198,96,224,198,48,0,199,80,0,199,112,0,199,144,0,199,174,0,199,
|
||||
202,0,199,231,0,199,3,1,199,16,2,199,43,2,199,66,2,199,16,4,199,43,4,199,66,4,199,16,6,199,43,6,199,66,6,199,16,8,199,43,8,199,66,8,199,39,16,199,
|
||||
69,16,199,99,16,199,130,16,199,160,16,199,34,32,199,65,32,199,96,32,199,48,64,199,80,64,199,110,64,199,140,64,199,169,64,199,198,64,199,227,64,199,0,65,199,16,66,199,
|
||||
38,66,199,64,66,199,16,68,199,38,68,199,64,68,199,16,70,199,38,70,199,64,70,199,16,72,199,38,72,199,64,72,199,35,80,199,66,80,199,96,80,199,16,0,200,48,0,200,
|
||||
80,0,200,112,0,200,144,0,200,16,16,200,48,16,200,80,16,200,104,16,200,129,16,200,16,32,200,47,32,200,72,32,200,99,32,200,16,64,200,48,64,200,80,64,200,112,64,200,
|
||||
138,64,200,16,80,200,41,80,200,68,80,200,96,80,200,8,96,200,35,96,200,64,96,200,16,128,200,48,128,200,80,128,200,112,128,200,138,128,200,16,144,200,41,144,200,68,144,200,
|
||||
96,144,200,8,160,200,35,160,200,64,160,200,16,192,200,48,192,200,78,192,200,105,192,200,132,192,200,8,208,200,35,208,200,64,208,200,3,224,200,16,0,201,48,0,201,78,0,201,
|
||||
105,0,201,132,0,201,8,16,201,35,16,201,64,16,201,3,32,201,16,64,201,45,64,201,73,64,201,100,64,201,129,64,201,4,80,201,32,80,201,16,0,202,48,0,202,80,0,202,
|
||||
16,16,202,45,16,202,64,16,202,16,32,202,38,32,202,16,64,202,48,64,202,73,64,202,12,80,202,34,80,202,5,96,202,16,128,202,48,128,202,73,128,202,12,144,202,34,144,202,
|
||||
5,160,202,16,192,202,44,192,202,67,192,202,5,208,202,1,224,202,16,0,203,44,0,203,67,0,203,5,16,203,1,32,203,16,64,203,39,64,203,64,64,203,2,80,203,16,0,204,
|
||||
48,0,204,16,16,204,32,16,204,14,32,204,16,64,204,41,64,204,8,80,204,3,96,204,16,128,204,41,128,204,8,144,204,3,160,204,16,192,204,35,192,204,3,208,204,16,0,205,
|
||||
35,0,205,3,16,205,13,64,205,32,64,205,0,80,205,16,0,220,48,0,220,80,0,220,112,0,220,144,0,220,176,0,220,208,0,220,240,0,220,14,1,220,16,16,220,48,16,220,
|
||||
80,16,220,112,16,220,144,16,220,172,16,220,198,16,220,225,16,220,16,32,220,48,32,220,80,32,220,109,32,220,138,32,220,165,32,220,193,32,220,16,64,220,48,64,220,80,64,220,
|
||||
112,64,220,144,64,220,176,64,220,207,64,220,234,64,220,3,65,220,16,72,220,48,72,220,65,72,220,16,80,220,46,80,220,75,80,220,104,80,220,133,80,220,162,80,220,10,96,220,
|
||||
39,96,220,68,96,220,98,96,220,129,96,220,16,128,220,48,128,220,80,128,220,112,128,220,144,128,220,176,128,220,207,128,220,234,128,220,3,129,220,16,130,220,48,130,220,65,130,220,
|
||||
16,132,220,48,132,220,65,132,220,16,134,220,48,134,220,65,134,220,16,144,220,46,144,220,75,144,220,104,144,220,133,144,220,162,144,220,10,160,220,39,160,220,68,160,220,98,160,220,
|
||||
129,160,220,16,192,220,48,192,220,80,192,220,112,192,220,144,192,220,171,192,220,199,192,220,228,192,220,16,194,220,40,194,220,16,196,220,40,196,220,16,198,220,40,198,220,10,208,220,
|
||||
39,208,220,68,208,220,98,208,220,129,208,220,4,224,220,34,224,220,64,224,220,16,0,221,48,0,221,80,0,221,112,0,221,144,0,221,171,0,221,199,0,221,228,0,221,16,2,221,
|
||||
40,2,221,16,4,221,40,4,221,16,6,221,40,6,221,16,8,221,40,8,221,10,16,221,39,16,221,68,16,221,98,16,221,129,16,221,4,32,221,34,32,221,64,32,221,16,64,221,
|
||||
48,64,221,79,64,221,108,64,221,138,64,221,166,64,221,195,64,221,225,64,221,15,66,221,36,66,221,15,68,221,36,68,221,15,70,221,36,70,221,15,72,221,36,72,221,6,80,221,
|
||||
35,80,221,65,80,221,96,80,221,16,0,222,48,0,222,80,0,222,112,0,222,144,0,222,16,16,222,48,16,222,76,16,222,99,16,222,16,32,222,44,32,222,69,32,222,16,64,222,
|
||||
48,64,222,80,64,222,108,64,222,132,64,222,15,80,222,39,80,222,66,80,222,7,96,222,34,96,222,16,128,222,48,128,222,80,128,222,108,128,222,132,128,222,15,144,222,39,144,222,
|
||||
66,144,222,7,160,222,34,160,222,16,192,222,48,192,222,75,192,222,101,192,222,128,192,222,7,208,222,34,208,222,2,224,222,16,0,223,48,0,223,75,0,223,101,0,223,128,0,223,
|
||||
7,16,223,34,16,223,2,32,223,16,64,223,44,64,223,70,64,223,98,64,223,3,80,223,16,0,224,48,0,224,78,0,224,16,16,224,40,16,224,16,32,224,35,32,224,16,64,224,
|
||||
48,64,224,67,64,224,11,80,224,32,80,224,4,96,224,16,128,224,48,128,224,67,128,224,11,144,224,32,144,224,4,160,224,16,192,224,41,192,224,4,208,224,0,224,224,16,0,225,
|
||||
41,0,225,4,16,225,0,32,225,15,64,225,36,64,225,1,80,225,16,0,226,46,0,226,16,16,226,11,32,226,16,64,226,35,64,226,6,80,226,1,96,226,16,128,226,35,128,226,
|
||||
6,144,226,1,160,226,16,192,226,1,208,226,16,0,227,1,16,227,11,64,227
|
||||
};
|
||||
257
transcoder/basisu_etc1_mods.inl
Normal file
257
transcoder/basisu_etc1_mods.inl
Normal file
@@ -0,0 +1,257 @@
|
||||
static const uint8_t g_etc1_mod_tabs[255][8] = {
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,1,1,},
|
||||
{0,0,0,0,0,0,0,1,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,0,},
|
||||
{0,0,0,0,0,0,0,1,},
|
||||
{0,0,0,0,0,0,1,1,},
|
||||
{0,0,0,0,0,1,1,1,},
|
||||
{0,0,0,0,0,1,1,1,},
|
||||
{0,0,0,0,1,1,1,1,},
|
||||
{0,0,0,0,1,1,1,1,},
|
||||
{0,0,0,0,1,1,1,1,},
|
||||
{0,0,0,0,1,1,1,1,},
|
||||
{0,0,0,1,1,1,1,1,},
|
||||
{0,0,0,1,1,1,1,1,},
|
||||
{0,0,0,1,1,1,1,1,},
|
||||
{0,0,0,1,1,1,1,2,},
|
||||
{0,0,0,1,1,1,2,2,},
|
||||
{0,0,0,1,1,1,2,2,},
|
||||
{0,0,0,1,1,2,2,2,},
|
||||
{0,0,1,1,1,2,2,2,},
|
||||
{0,0,1,1,1,2,2,2,},
|
||||
{0,0,1,1,1,2,2,2,},
|
||||
{0,0,1,1,1,2,2,2,},
|
||||
{0,0,1,1,2,2,2,2,},
|
||||
{0,0,1,1,2,2,2,2,},
|
||||
{0,0,1,1,2,2,2,2,},
|
||||
{0,0,1,1,2,2,2,2,},
|
||||
{0,0,1,1,2,2,2,2,},
|
||||
{0,0,1,1,2,2,2,3,},
|
||||
{0,0,1,1,2,2,3,3,},
|
||||
{0,0,1,2,2,2,3,3,},
|
||||
{0,0,1,2,2,2,3,3,},
|
||||
{0,0,1,2,2,2,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,2,3,3,3,},
|
||||
{0,1,1,2,3,3,3,3,},
|
||||
{0,1,1,2,3,3,3,3,},
|
||||
{0,1,1,2,3,3,3,3,},
|
||||
{0,1,2,2,3,3,3,3,},
|
||||
{0,1,2,2,3,3,3,4,},
|
||||
{0,1,2,2,3,3,3,4,},
|
||||
{0,1,2,2,3,3,4,4,},
|
||||
{0,1,2,2,3,3,4,4,},
|
||||
{0,1,2,2,3,3,4,4,},
|
||||
{0,1,2,2,3,3,4,4,},
|
||||
{0,1,2,2,3,3,4,4,},
|
||||
{0,1,2,2,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,3,4,4,4,},
|
||||
{0,1,2,3,4,4,4,4,},
|
||||
{0,1,2,3,4,4,4,5,},
|
||||
{0,1,2,3,4,4,4,5,},
|
||||
{0,1,2,3,4,4,4,5,},
|
||||
{0,1,2,3,4,4,5,5,},
|
||||
{0,1,2,3,4,4,5,5,},
|
||||
{0,1,2,3,4,4,5,5,},
|
||||
{0,1,2,3,4,4,5,5,},
|
||||
{0,2,2,3,4,4,5,5,},
|
||||
{0,2,2,3,4,4,5,5,},
|
||||
{0,2,2,3,4,4,5,5,},
|
||||
{0,2,3,3,4,5,5,5,},
|
||||
{0,2,3,3,4,5,5,5,},
|
||||
{0,2,3,3,4,5,5,5,},
|
||||
{0,2,3,3,4,5,5,5,},
|
||||
{1,2,3,3,4,5,5,5,},
|
||||
{1,2,3,3,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,5,},
|
||||
{1,2,3,4,4,5,5,6,},
|
||||
{1,2,3,4,5,5,5,6,},
|
||||
{1,2,3,4,5,5,5,6,},
|
||||
{1,2,3,4,5,5,5,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,5,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,3,4,5,6,6,6,},
|
||||
{1,2,4,4,5,6,6,6,},
|
||||
{1,2,4,4,5,6,6,6,},
|
||||
{1,2,4,4,5,6,6,6,},
|
||||
{1,2,4,4,5,6,6,6,},
|
||||
{1,2,4,5,5,6,6,6,},
|
||||
{1,2,4,5,5,6,6,6,},
|
||||
{1,3,4,5,5,6,6,6,},
|
||||
{1,3,4,5,5,6,6,6,},
|
||||
{1,3,4,5,5,6,6,6,},
|
||||
{1,3,4,5,5,6,6,6,},
|
||||
{1,3,4,5,5,6,6,6,},
|
||||
{1,3,4,5,5,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,6,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,6,7,},
|
||||
{1,3,4,5,6,6,7,7,},
|
||||
{1,3,4,5,6,6,7,7,},
|
||||
{1,3,4,5,6,6,7,7,},
|
||||
{1,3,4,5,6,6,7,7,},
|
||||
{1,3,4,5,6,6,7,7,},
|
||||
{1,3,4,6,6,6,7,7,},
|
||||
{1,3,5,6,6,6,7,7,},
|
||||
{1,3,5,6,6,6,7,7,},
|
||||
{1,3,5,6,6,6,7,7,},
|
||||
{2,3,5,6,6,6,7,7,},
|
||||
{2,3,5,6,6,6,7,7,},
|
||||
{2,3,5,6,6,6,7,7,},
|
||||
{2,3,5,6,6,6,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,3,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,6,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,5,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,4,6,6,7,7,7,7,},
|
||||
{2,5,6,6,7,7,7,7,},
|
||||
{2,5,6,6,7,7,7,7,},
|
||||
{2,5,6,6,7,7,7,7,},
|
||||
{2,5,6,6,7,7,7,7,},
|
||||
{2,5,6,6,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,},
|
||||
{2,5,6,7,7,7,7,7,}
|
||||
};
|
||||
1446
transcoder/basisu_idct.h
Normal file
1446
transcoder/basisu_idct.h
Normal file
File diff suppressed because it is too large
Load Diff
26
webgl/encoder/build_notes.txt
Normal file
26
webgl/encoder/build_notes.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
# Prereq: activate emsdk first (so emcmake/em++ are on PATH)
|
||||
# Linux/macOS:
|
||||
source /path/to/emsdk/emsdk_env.sh
|
||||
# Windows PowerShell:
|
||||
# & "C:\path\to\emsdk\emsdk_env.ps1"
|
||||
|
||||
# ===== Release (fast; same behavior as your original file) =====
|
||||
emcmake cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build-release -j
|
||||
|
||||
# ===== Debug (symbols + assertions) =====
|
||||
emcmake cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build-debug -j
|
||||
|
||||
# ===== SAN (ASan + UBSan; great for catching bugs) =====
|
||||
emcmake cmake -S . -B build-san -DCMAKE_BUILD_TYPE=SAN
|
||||
cmake --build build-san -j
|
||||
|
||||
# Build a single target (optional) instead of all three:
|
||||
cmake --build build-release -j --target basis_encoder.js
|
||||
cmake --build build-release -j --target basis_encoder_threads.js
|
||||
cmake --build build-release -j --target basis_encoder_threads_wasm64.js
|
||||
|
||||
# Toggle Zstd (OFF = smaller binary, no KTX2 Zstd compression)
|
||||
emcmake cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release -DKTX2_ZSTANDARD=OFF
|
||||
cmake --build build-release -j
|
||||
BIN
webgl/texture_test/assets/base.basis
Normal file
BIN
webgl/texture_test/assets/base.basis
Normal file
Binary file not shown.
107
zstd/zstd_errors.h
Normal file
107
zstd/zstd_errors.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_ERRORS_H_398273423
|
||||
#define ZSTD_ERRORS_H_398273423
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
|
||||
#ifndef ZSTDERRORLIB_VISIBLE
|
||||
/* Backwards compatibility with old macro name */
|
||||
# ifdef ZSTDERRORLIB_VISIBILITY
|
||||
# define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define ZSTDERRORLIB_VISIBLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZSTDERRORLIB_HIDDEN
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define ZSTDERRORLIB_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE
|
||||
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE
|
||||
#endif
|
||||
|
||||
/*-*********************************************
|
||||
* Error codes list
|
||||
*-*********************************************
|
||||
* Error codes _values_ are pinned down since v1.3.1 only.
|
||||
* Therefore, don't rely on values if you may link to any version < v1.3.1.
|
||||
*
|
||||
* Only values < 100 are considered stable.
|
||||
*
|
||||
* note 1 : this API shall be used with static linking only.
|
||||
* dynamic linking is not yet officially supported.
|
||||
* note 2 : Prefer relying on the enum than on its value whenever possible
|
||||
* This is the only supported way to use the error list < v1.3.1
|
||||
* note 3 : ZSTD_isError() is always correct, whatever the library version.
|
||||
**********************************************/
|
||||
typedef enum {
|
||||
ZSTD_error_no_error = 0,
|
||||
ZSTD_error_GENERIC = 1,
|
||||
ZSTD_error_prefix_unknown = 10,
|
||||
ZSTD_error_version_unsupported = 12,
|
||||
ZSTD_error_frameParameter_unsupported = 14,
|
||||
ZSTD_error_frameParameter_windowTooLarge = 16,
|
||||
ZSTD_error_corruption_detected = 20,
|
||||
ZSTD_error_checksum_wrong = 22,
|
||||
ZSTD_error_literals_headerWrong = 24,
|
||||
ZSTD_error_dictionary_corrupted = 30,
|
||||
ZSTD_error_dictionary_wrong = 32,
|
||||
ZSTD_error_dictionaryCreation_failed = 34,
|
||||
ZSTD_error_parameter_unsupported = 40,
|
||||
ZSTD_error_parameter_combination_unsupported = 41,
|
||||
ZSTD_error_parameter_outOfBound = 42,
|
||||
ZSTD_error_tableLog_tooLarge = 44,
|
||||
ZSTD_error_maxSymbolValue_tooLarge = 46,
|
||||
ZSTD_error_maxSymbolValue_tooSmall = 48,
|
||||
ZSTD_error_cannotProduce_uncompressedBlock = 49,
|
||||
ZSTD_error_stabilityCondition_notRespected = 50,
|
||||
ZSTD_error_stage_wrong = 60,
|
||||
ZSTD_error_init_missing = 62,
|
||||
ZSTD_error_memory_allocation = 64,
|
||||
ZSTD_error_workSpace_tooSmall= 66,
|
||||
ZSTD_error_dstSize_tooSmall = 70,
|
||||
ZSTD_error_srcSize_wrong = 72,
|
||||
ZSTD_error_dstBuffer_null = 74,
|
||||
ZSTD_error_noForwardProgress_destFull = 80,
|
||||
ZSTD_error_noForwardProgress_inputEmpty = 82,
|
||||
/* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
|
||||
ZSTD_error_frameIndex_tooLarge = 100,
|
||||
ZSTD_error_seekableIO = 102,
|
||||
ZSTD_error_dstBuffer_wrong = 104,
|
||||
ZSTD_error_srcBuffer_wrong = 105,
|
||||
ZSTD_error_sequenceProducer_failed = 106,
|
||||
ZSTD_error_externalSequences_invalid = 107,
|
||||
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
||||
} ZSTD_ErrorCode;
|
||||
|
||||
ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZSTD_ERRORS_H_398273423 */
|
||||
Reference in New Issue
Block a user