blob: 4eac0ed7e6f59d6be6aa8b1b287167183c793b72 [file]
// File: basisu_astc_hdr_6x6_enc.h
#pragma once
#include "basisu_enc.h"
#include "../transcoder/basisu_astc_hdr_core.h"
namespace astc_6x6_hdr
{
const uint32_t ASTC_HDR_6X6_DEF_USER_COMP_LEVEL = 2;
const uint32_t ASTC_HDR_6X6_MAX_USER_COMP_LEVEL = 12;
const uint32_t ASTC_HDR_6X6_MAX_COMP_LEVEL = 4;
const float LDR_BLACK_BIAS = 0.0f;// .49f;
// Note: This struct is copied several times, so do not place any heavyweight objects in here.
struct astc_hdr_6x6_global_config
{
// Important: The Delta ITP colorspace error metric we use internally makes several assumptions about the nature of the HDR RGB inputs supplied to the encoder.
// This encoder computes colorspace error in the ICtCp (or more accurately the delta E ITP, where CT is scaled by .5 vs. ICtCp to become T) colorspace, so getting this correct is important.
// By default the encoder assumes the input is in absolute luminance (in nits or candela per square meter, cd/m^2), specified as positive-only linear light RGB, using the REC 709 colorspace gamut (but NOT the sRGB transfer function, i.e. linear light).
// If the m_rec2020_bt2100_color_gamut flag is true, the input colorspace is treated as REC 2020/BT.2100 (which is wider than 709).
// For SDR/LDR->HDR upconversion, the REC 709 sRGB input should be converted to linear light (sRGB->linear) and the resulting normalized linear RGB values scaled by either 80 or 100 nits (the luminance of a typical SDR monitor).
// SDR upconversion to normalized [0,1] (i.e. non-absolute) luminances may work but is not supported because ITP errors will not be predicted correctly.
// 11/3/2025: This flag is always copied straight into the output KTX2 DFD colorspace, even for non-HDR formats.
// TODO: Move this parameter to reflect this.
bool m_rec2020_bt2100_color_gamut = false;
// levels 0-3 normal levels, 4=exhaustive
uint32_t m_master_comp_level = 0;
uint32_t m_highest_comp_level = 1;
float m_lambda = 0.0f;
bool m_extra_patterns_flag = false; // def to false, works in comp levels [1,4]
bool m_brute_force_partition_matching = false; // def to false
bool m_jnd_optimization = false; // defaults to false for HDR inputs, on SDR upconverted images this can default to enabled
float m_jnd_delta_itp_thresh = .75f;
bool m_force_one_strip = false;
bool m_gaussian1_fallback = true; // def to true, if this is disabled m_gaussian2_fallback should be disabled too
float m_gaussian1_strength = 1.45f;
bool m_gaussian2_fallback = true; // def to true, hopefully rarely kicks in
float m_gaussian2_strength = 1.83f;
// m_disable_delta_endpoint_usage may give a slight increase in RDO ASTC encoding efficiency. It's also faster.
bool m_disable_delta_endpoint_usage = false;
// Scale up Delta ITP errors for very dark pixels, assuming they will be brightly exposed > 1.0x.
// We don't know if the output will be exposed, or not. If heavily exposed, our JND calculations will not be conservative enough.
bool m_delta_itp_dark_adjustment = true;
bool m_debug_images = false;
std::string m_debug_image_prefix = "dbg_astc_hdr_6x6_devel_";
bool m_output_images = false;
std::string m_output_image_prefix = "dbg_astc_hdr_6x6_output_";
bool m_debug_output = false;
bool m_image_stats = false;
bool m_status_output = false;
//-------------------------------------------------------------------------------------
// Very low level/devel parameters - intended for development. Best not to change them.
//-------------------------------------------------------------------------------------
bool m_deblocking_flag = true;
float m_deblock_penalty_weight = .03f;
bool m_disable_twothree_subsets = false; // def to false
bool m_use_solid_blocks = true; // def to true
bool m_use_runs = true; // def to true
bool m_block_stat_optimizations_flag = true; // def to true
bool m_rdo_candidate_diversity_boost = true; // def to true
float m_rdo_candidate_diversity_boost_bit_window_weight = 1.2f;
bool m_favor_higher_compression = true; // utilize all modes
uint32_t m_num_reuse_xy_deltas = basist::astc_6x6_hdr::NUM_REUSE_XY_DELTAS;
// By default, for compatibility with KTX-Software (which uses v1.60), we write v1.6 compatible UASTC HDR 6x6i files.
// The transcoder is compatible with both variants. This setting impacts how 2x2 blocks are upsampled and the initial marker version.
// Eventually once KTX-Software upgrades to the latest version of basisu this will be defaulted to false.
// If this is false a v2.0 or later transcoder is required for UASTC HDR 6x6i.
bool m_write_basisu_1_6_compatible_files = true;
void print() const
{
basisu::fmt_debug_printf(" m_master_comp_level: {}, m_highest_comp_level: {}\n", m_master_comp_level, m_highest_comp_level);
basisu::fmt_debug_printf(" m_lambda: {}\n", m_lambda);
basisu::fmt_debug_printf(" m_rec2020_bt2100_color_gamut: {}\n", m_rec2020_bt2100_color_gamut);
basisu::fmt_debug_printf(" m_extra_patterns_flag: {}, m_brute_force_partition_matching: {}\n", m_extra_patterns_flag, m_brute_force_partition_matching);
basisu::fmt_debug_printf(" m_jnd_optimization: {}, m_jnd_delta_itp_thresh: {}\n", m_jnd_optimization, m_jnd_delta_itp_thresh);
basisu::fmt_debug_printf(" m_force_one_strip: {}\n", m_force_one_strip);
basisu::fmt_debug_printf(" m_gaussian1_fallback: {}, m_gaussian1_strength: {}\n", m_gaussian1_fallback, m_gaussian1_strength);
basisu::fmt_debug_printf(" m_gaussian2_fallback: {}, m_gaussian2_strength: {}\n", m_gaussian2_fallback, m_gaussian2_strength);
basisu::fmt_debug_printf(" m_disable_delta_endpoint_usage: {}\n", m_disable_delta_endpoint_usage);
basisu::fmt_debug_printf(" m_delta_itp_dark_adjustment: {}\n", m_delta_itp_dark_adjustment);
basisu::fmt_debug_printf(" m_debug_images: {}, m_debug_image_prefix: {}\n", m_debug_images, m_debug_image_prefix);
basisu::fmt_debug_printf(" m_output_images: {}, m_output_image_prefix: {}\n", m_output_images, m_output_image_prefix);
basisu::fmt_debug_printf(" m_image_stats: {}, m_status_output: {}\n", m_image_stats, m_status_output);
basisu::fmt_debug_printf(" m_deblocking_flag: {}, m_deblock_penalty_weight: {}\n", m_deblocking_flag, m_deblock_penalty_weight);
basisu::fmt_debug_printf(" m_disable_twothree_subsets: {}, m_use_solid_blocks: {}\n", m_disable_twothree_subsets, m_use_solid_blocks);
basisu::fmt_debug_printf(" m_use_runs: {}, m_block_stat_optimizations_flag: {}\n", m_use_runs, m_block_stat_optimizations_flag);
basisu::fmt_debug_printf(" m_rdo_candidate_diversity_boost: {}, m_rdo_candidate_diversity_boost_bit_window_weight: {}\n", m_rdo_candidate_diversity_boost, m_rdo_candidate_diversity_boost_bit_window_weight);
basisu::fmt_debug_printf(" m_favor_higher_compression: {}, m_num_reuse_xy_deltas: {}\n", m_favor_higher_compression, m_num_reuse_xy_deltas);
basisu::fmt_debug_printf(" m_write_basisu_1_6_compatible_files: {}\n", m_write_basisu_1_6_compatible_files);
}
astc_hdr_6x6_global_config()
{
}
void clear()
{
astc_hdr_6x6_global_config def;
std::swap(*this, def);
}
// Max level is ASTC_HDR_6X6_MAX_USER_COMP_LEVEL
void set_user_level(int level);
};
void global_init();
struct result_metrics
{
basisu::image_metrics m_im_astc_log2;
basisu::image_metrics m_im_astc_half;
basisu::image_metrics m_im_bc6h_log2;
basisu::image_metrics m_im_bc6h_half;
};
// The input image should be unpadded to 6x6 boundaries, i.e. the original unexpanded image.
bool compress_photo(const basisu::imagef& orig_src_img, const astc_hdr_6x6_global_config& global_cfg, basisu::job_pool* pJob_pool,
basisu::uint8_vec& intermediate_tex_data, basisu::uint8_vec& astc_tex_data, result_metrics& metrics);
} // namespace uastc_6x6_hdr