c9fd4dca75
This change improves compression speed. Explanation: While trying different remappings for the endpoint indices, there is no need to perform full pack simulation when using Huffman coding. Once the delta index histogram is generated, it is sufficient to simply multiply the code sizes by the corresponding frequences in order to get the total size of the compressed endpoint indices stream. There is also no need to compute the rest of the compressed stream, as its size does not depend on the endpoint remapping and therefore is always constant, so it will not affect the size comparison during endpoint optimization. Testing: The modified algorithm has been tested on the Kodak test set using 64-bit build with default settings (running on Windows 10, i7-4790, 3.6GHz). All the decompressed test images are identical to the images being compressed and decompressed using original version of Crunch. [Compressing Kodak set without mipmaps] Original: 1582222 bytes / 28.864 sec Modified: 1494501 bytes / 25.317 sec Improvement: 5.54% (compression ratio) / 12.29% (compression time) [Compressing Kodak set with mipmaps] Original: 2065243 bytes / 36.927 sec Modified: 1945365 bytes / 33.151 sec Improvement: 5.80% (compression ratio) / 10.23% (compression time)
155 lines
5.2 KiB
C++
155 lines
5.2 KiB
C++
// File: crn_comp.h
|
|
// See Copyright Notice and license at the end of inc/crnlib.h
|
|
#pragma once
|
|
|
|
#include "../inc/crn_defs.h"
|
|
|
|
#include "../inc/crnlib.h"
|
|
#include "crn_symbol_codec.h"
|
|
#include "crn_dxt_hc.h"
|
|
#include "crn_image.h"
|
|
#include "crn_image_utils.h"
|
|
#include "crn_texture_comp.h"
|
|
|
|
namespace crnlib {
|
|
class crn_comp : public itexture_comp {
|
|
CRNLIB_NO_COPY_OR_ASSIGNMENT_OP(crn_comp);
|
|
|
|
public:
|
|
crn_comp();
|
|
virtual ~crn_comp();
|
|
|
|
virtual const char* get_ext() const { return "CRN"; }
|
|
|
|
virtual bool compress_init(const crn_comp_params& params);
|
|
virtual bool compress_pass(const crn_comp_params& params, float* pEffective_bitrate);
|
|
virtual void compress_deinit();
|
|
|
|
virtual const crnlib::vector<uint8>& get_comp_data() const { return m_comp_data; }
|
|
virtual crnlib::vector<uint8>& get_comp_data() { return m_comp_data; }
|
|
|
|
uint get_comp_data_size() const { return m_comp_data.size(); }
|
|
const uint8* get_comp_data_ptr() const { return m_comp_data.size() ? &m_comp_data[0] : NULL; }
|
|
|
|
private:
|
|
task_pool m_task_pool;
|
|
const crn_comp_params* m_pParams;
|
|
|
|
image_u8 m_images[cCRNMaxFaces][cCRNMaxLevels];
|
|
|
|
struct level_tag {
|
|
uint m_width, m_height;
|
|
uint m_chunk_width, m_chunk_height;
|
|
uint m_group_index;
|
|
uint m_num_chunks;
|
|
uint m_first_chunk;
|
|
uint m_group_first_chunk;
|
|
} m_levels[cCRNMaxLevels];
|
|
|
|
struct mip_group {
|
|
mip_group()
|
|
: m_first_chunk(0), m_num_chunks(0) {}
|
|
|
|
uint m_first_chunk;
|
|
uint m_num_chunks;
|
|
uint m_chunk_width;
|
|
};
|
|
crnlib::vector<mip_group> m_mip_groups;
|
|
|
|
enum comp {
|
|
cColor,
|
|
cAlpha0,
|
|
cAlpha1,
|
|
cNumComps
|
|
};
|
|
|
|
bool m_has_comp[cNumComps];
|
|
|
|
crnlib::vector<dxt_hc::endpoint_indices_details> m_endpoint_indices;
|
|
crnlib::vector<dxt_hc::selector_indices_details> m_selector_indices;
|
|
|
|
uint m_total_chunks;
|
|
dxt_hc::pixel_chunk_vec m_chunks;
|
|
|
|
crnd::crn_header m_crn_header;
|
|
crnlib::vector<uint8> m_comp_data;
|
|
|
|
dxt_hc m_hvq;
|
|
|
|
symbol_histogram m_chunk_encoding_hist;
|
|
static_huffman_data_model m_reference_encoding_dm;
|
|
|
|
symbol_histogram m_endpoint_index_hist[2];
|
|
static_huffman_data_model m_endpoint_index_dm[2]; // color, alpha
|
|
|
|
symbol_histogram m_selector_index_hist[2];
|
|
static_huffman_data_model m_selector_index_dm[2]; // color, alpha
|
|
|
|
crnlib::vector<uint8> m_packed_chunks[cCRNMaxLevels];
|
|
crnlib::vector<uint8> m_packed_data_models;
|
|
crnlib::vector<uint8> m_packed_color_endpoints;
|
|
crnlib::vector<uint8> m_packed_color_selectors;
|
|
crnlib::vector<uint8> m_packed_alpha_endpoints;
|
|
crnlib::vector<uint8> m_packed_alpha_selectors;
|
|
|
|
void clear();
|
|
|
|
void append_chunks(const image_u8& img, uint num_chunks_x, uint num_chunks_y, dxt_hc::pixel_chunk_vec& chunks, float weight);
|
|
|
|
static float color_endpoint_similarity_func(uint index_a, uint index_b, void* pContext);
|
|
static float alpha_endpoint_similarity_func(uint index_a, uint index_b, void* pContext);
|
|
void sort_color_endpoint_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<uint>& endpoints);
|
|
void sort_alpha_endpoint_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<uint>& endpoints);
|
|
|
|
bool pack_color_endpoints(crnlib::vector<uint8>& data, const crnlib::vector<uint>& remapping, uint trial_index);
|
|
bool pack_alpha_endpoints(crnlib::vector<uint8>& data, const crnlib::vector<uint>& remapping, uint trial_index);
|
|
|
|
static float color_selector_similarity_func(uint index_a, uint index_b, void* pContext);
|
|
static float alpha_selector_similarity_func(uint index_a, uint index_b, void* pContext);
|
|
void sort_selector_codebook(crnlib::vector<uint>& remapping, const crnlib::vector<dxt_hc::selectors>& selectors, const uint8* pTo_linear);
|
|
|
|
bool pack_selectors(
|
|
crnlib::vector<uint8>& packed_data,
|
|
const crnlib::vector<dxt_hc::selectors>& selectors,
|
|
const crnlib::vector<uint>& remapping,
|
|
uint max_selector_value,
|
|
const uint8* pTo_linear,
|
|
uint trial_index);
|
|
|
|
bool alias_images();
|
|
void create_chunks();
|
|
bool quantize_chunks();
|
|
|
|
bool pack_chunks(
|
|
uint group,
|
|
bool clear_histograms,
|
|
symbol_codec* pCodec,
|
|
const crnlib::vector<uint>* pColor_endpoint_remap,
|
|
const crnlib::vector<uint>* pColor_selector_remap,
|
|
const crnlib::vector<uint>* pAlpha_endpoint_remap,
|
|
const crnlib::vector<uint>* pAlpha_selector_remap);
|
|
|
|
void optimize_color_endpoint_codebook_task(uint64 data, void* pData_ptr);
|
|
bool optimize_color_endpoint_codebook(crnlib::vector<uint>& remapping);
|
|
|
|
bool optimize_color_selector_codebook(crnlib::vector<uint>& remapping);
|
|
|
|
void optimize_alpha_endpoint_codebook_task(uint64 data, void* pData_ptr);
|
|
bool optimize_alpha_endpoint_codebook(crnlib::vector<uint>& remapping);
|
|
|
|
bool optimize_alpha_selector_codebook(crnlib::vector<uint>& remapping);
|
|
|
|
bool create_comp_data();
|
|
|
|
bool pack_data_models();
|
|
|
|
bool update_progress(uint phase_index, uint subphase_index, uint subphase_total);
|
|
|
|
bool compress_internal();
|
|
|
|
static void append_vec(crnlib::vector<uint8>& a, const void* p, uint size);
|
|
static void append_vec(crnlib::vector<uint8>& a, const crnlib::vector<uint8>& b);
|
|
};
|
|
|
|
} // namespace crnlib
|