Use left nearest block for endpoint index prediction
This change improves compression ratio. Explanation: In the original algorithm the relative position of the block, used for prediction of the endpoint index for the currently decoded block, depends on the chunk encoding type. It can be a horizontal neighbour, a vertical neighbour, a diagonal neighbour, or in some rare cases even a block at relative position (-2, 0) or (-3, 0). Using left nearest neighbour for endpoint index prediction for each block (except the blocks at the image borders) minimizes the average distance to the prediction block and therefore usually improves the endpoint index prediction. Note: This modification alters the output file format and makes it incompatible with the previous revisions. 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.838 sec Modified: 1570534 bytes / 28.629 sec Improvement: 0.74% (compression ratio) / 0.72% (compression time) [Compressing Kodak set with mipmaps] Original: 2065243 bytes / 36.977 sec Modified: 2051509 bytes / 36.568 sec Improvement: 0.67% (compression ratio) / 1.11% (compression time)
This commit is contained in:
Binary file not shown.
+68
-40
@@ -727,8 +727,7 @@ bool crn_comp::pack_chunks(
|
||||
}
|
||||
}
|
||||
|
||||
uint prev_endpoint_index[cNumComps];
|
||||
utils::zero_object(prev_endpoint_index);
|
||||
uint endpoint_index[cNumComps][2][2] = {};
|
||||
|
||||
uint prev_selector_index[cNumComps];
|
||||
utils::zero_object(prev_selector_index);
|
||||
@@ -763,42 +762,52 @@ bool crn_comp::pack_chunks(
|
||||
// endpoints
|
||||
if (comp_index == cColor) {
|
||||
if (pColor_endpoint_remap) {
|
||||
for (uint i = 0; i < encoding.m_num_tiles; i++) {
|
||||
uint cur_endpoint_index = (*pColor_endpoint_remap)[m_endpoint_indices[cColor][details.m_first_endpoint_index + i]];
|
||||
int endpoint_delta = cur_endpoint_index - prev_endpoint_index[cColor];
|
||||
for (uint y = 0; y < 2; y++) {
|
||||
for (uint x = 0; x < 2; x++) {
|
||||
uint8 endpoint_reference = details.m_endpoint_references[comp_index][y][x];
|
||||
if (!endpoint_reference) {
|
||||
endpoint_index[comp_index][y][x] = (*pColor_endpoint_remap)[details.m_endpoint_indices[comp_index][y][x]];
|
||||
int endpoint_delta = endpoint_index[comp_index][y][x] - endpoint_index[comp_index][y][x ^ 1];
|
||||
|
||||
int sym = endpoint_delta;
|
||||
if (sym < 0)
|
||||
sym += pColor_endpoint_remap->size();
|
||||
int sym = endpoint_delta;
|
||||
if (sym < 0)
|
||||
sym += pColor_endpoint_remap->size();
|
||||
|
||||
CRNLIB_ASSERT(sym >= 0 && sym < (int)pColor_endpoint_remap->size());
|
||||
CRNLIB_ASSERT(sym >= 0 && sym < (int)pColor_endpoint_remap->size());
|
||||
|
||||
if (!pCodec)
|
||||
m_endpoint_index_hist[cColor].inc_freq(sym);
|
||||
else
|
||||
pCodec->encode(sym, m_endpoint_index_dm[0]);
|
||||
|
||||
prev_endpoint_index[cColor] = cur_endpoint_index;
|
||||
if (!pCodec)
|
||||
m_endpoint_index_hist[0].inc_freq(sym);
|
||||
else
|
||||
pCodec->encode(sym, m_endpoint_index_dm[0]);
|
||||
} else {
|
||||
endpoint_index[comp_index][y][x] = endpoint_reference == 1 ? endpoint_index[comp_index][y][x ^ 1] : endpoint_index[comp_index][y ^ 1][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pAlpha_endpoint_remap) {
|
||||
for (uint i = 0; i < encoding.m_num_tiles; i++) {
|
||||
uint cur_endpoint_index = (*pAlpha_endpoint_remap)[m_endpoint_indices[comp_index][details.m_first_endpoint_index + i]];
|
||||
int endpoint_delta = cur_endpoint_index - prev_endpoint_index[comp_index];
|
||||
for (uint y = 0; y < 2; y++) {
|
||||
for (uint x = 0; x < 2; x++) {
|
||||
uint8 endpoint_reference = details.m_endpoint_references[comp_index][y][x];
|
||||
if (!endpoint_reference) {
|
||||
endpoint_index[comp_index][y][x] = (*pAlpha_endpoint_remap)[details.m_endpoint_indices[comp_index][y][x]];
|
||||
int endpoint_delta = endpoint_index[comp_index][y][x] - endpoint_index[comp_index][y][x ^ 1];
|
||||
|
||||
int sym = endpoint_delta;
|
||||
if (sym < 0)
|
||||
sym += pAlpha_endpoint_remap->size();
|
||||
int sym = endpoint_delta;
|
||||
if (sym < 0)
|
||||
sym += pAlpha_endpoint_remap->size();
|
||||
|
||||
CRNLIB_ASSERT(sym >= 0 && sym < (int)pAlpha_endpoint_remap->size());
|
||||
CRNLIB_ASSERT(sym >= 0 && sym < (int)pAlpha_endpoint_remap->size());
|
||||
|
||||
if (!pCodec)
|
||||
m_endpoint_index_hist[1].inc_freq(sym);
|
||||
else
|
||||
pCodec->encode(sym, m_endpoint_index_dm[1]);
|
||||
|
||||
prev_endpoint_index[comp_index] = cur_endpoint_index;
|
||||
if (!pCodec)
|
||||
m_endpoint_index_hist[1].inc_freq(sym);
|
||||
else
|
||||
pCodec->encode(sym, m_endpoint_index_dm[1]);
|
||||
} else {
|
||||
endpoint_index[comp_index][y][x] = endpoint_reference == 1 ? endpoint_index[comp_index][y][x ^ 1] : endpoint_index[comp_index][y ^ 1][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -814,7 +823,7 @@ bool crn_comp::pack_chunks(
|
||||
|
||||
if (comp_index == cColor) {
|
||||
if (pColor_selector_remap) {
|
||||
uint cur_selector_index = (*pColor_selector_remap)[m_selector_indices[cColor][details.m_first_selector_index + x + y * 2]];
|
||||
uint cur_selector_index = (*pColor_selector_remap)[details.m_selector_indices[cColor][y][x]];
|
||||
int selector_delta = cur_selector_index - prev_selector_index[cColor];
|
||||
|
||||
int sym = selector_delta;
|
||||
@@ -831,7 +840,7 @@ bool crn_comp::pack_chunks(
|
||||
prev_selector_index[cColor] = cur_selector_index;
|
||||
}
|
||||
} else if (pAlpha_selector_remap) {
|
||||
uint cur_selector_index = (*pAlpha_selector_remap)[m_selector_indices[comp_index][details.m_first_selector_index + x + y * 2]];
|
||||
uint cur_selector_index = (*pAlpha_selector_remap)[details.m_selector_indices[comp_index][y][x]];
|
||||
int selector_delta = cur_selector_index - prev_selector_index[comp_index];
|
||||
|
||||
int sym = selector_delta;
|
||||
@@ -1251,6 +1260,28 @@ bool crn_comp::quantize_chunks() {
|
||||
}
|
||||
|
||||
void crn_comp::create_chunk_indices() {
|
||||
uint8 endpoint_index_map[8][4] = {
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 1, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 2 },
|
||||
{ 1, 2, 0, 0 },
|
||||
{ 0, 1, 0, 2 },
|
||||
{ 1, 0, 2, 0 },
|
||||
{ 0, 1, 2, 3 },
|
||||
};
|
||||
|
||||
uint8 endpoint_references[8][4] = {
|
||||
{ 0, 1, 2, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 2, 2 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 1 },
|
||||
{ 0, 0, 2, 0 },
|
||||
{ 0, 0, 0, 2 },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
m_chunk_details.resize(m_total_chunks);
|
||||
|
||||
for (uint i = 0; i < cNumComps; i++) {
|
||||
@@ -1261,14 +1292,6 @@ void crn_comp::create_chunk_indices() {
|
||||
for (uint chunk_index = 0; chunk_index < m_total_chunks; chunk_index++) {
|
||||
const dxt_hc::chunk_encoding& chunk_encoding = m_hvq.get_chunk_encoding(chunk_index);
|
||||
|
||||
for (uint i = 0; i < cNumComps; i++) {
|
||||
if (m_has_comp[i]) {
|
||||
m_chunk_details[chunk_index].m_first_endpoint_index = m_endpoint_indices[i].size();
|
||||
m_chunk_details[chunk_index].m_first_selector_index = m_selector_indices[i].size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < cNumComps; i++) {
|
||||
if (!m_has_comp[i])
|
||||
continue;
|
||||
@@ -1276,9 +1299,14 @@ void crn_comp::create_chunk_indices() {
|
||||
for (uint tile_index = 0; tile_index < chunk_encoding.m_num_tiles; tile_index++)
|
||||
m_endpoint_indices[i].push_back(chunk_encoding.m_endpoint_indices[i][tile_index]);
|
||||
|
||||
for (uint y = 0; y < cChunkBlockHeight; y++)
|
||||
for (uint x = 0; x < cChunkBlockWidth; x++)
|
||||
for (uint t = 0, y = 0; y < cChunkBlockHeight; y++) {
|
||||
for (uint x = 0; x < cChunkBlockWidth; x++, t++) {
|
||||
m_selector_indices[i].push_back(chunk_encoding.m_selector_indices[i][y][x]);
|
||||
m_chunk_details[chunk_index].m_selector_indices[i][y][x] = chunk_encoding.m_selector_indices[i][y][x];
|
||||
m_chunk_details[chunk_index].m_endpoint_indices[i][y][x] = chunk_encoding.m_endpoint_indices[i][endpoint_index_map[chunk_encoding.m_encoding_index][t]];
|
||||
m_chunk_details[chunk_index].m_endpoint_references[i][y][x] = endpoint_references[chunk_encoding.m_encoding_index][t];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -66,9 +66,9 @@ class crn_comp : public itexture_comp {
|
||||
|
||||
struct chunk_detail {
|
||||
chunk_detail() { utils::zero_object(*this); }
|
||||
|
||||
uint m_first_endpoint_index;
|
||||
uint m_first_selector_index;
|
||||
uint8 m_endpoint_references[cNumComps][2][2];
|
||||
uint16 m_endpoint_indices[cNumComps][2][2];
|
||||
uint16 m_selector_indices[cNumComps][2][2];
|
||||
};
|
||||
typedef crnlib::vector<chunk_detail> chunk_detail_vec;
|
||||
chunk_detail_vec m_chunk_details;
|
||||
|
||||
+101
-132
@@ -3036,59 +3036,17 @@ uint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h) {
|
||||
// File: crnd_decode.cpp
|
||||
|
||||
namespace crnd {
|
||||
|
||||
struct crnd_chunk_tile_desc {
|
||||
// These values are in blocks
|
||||
uint8 m_x_ofs;
|
||||
uint8 m_y_ofs;
|
||||
uint8 m_width;
|
||||
uint8 m_height;
|
||||
static uint8 g_crnd_endpoint_references[8][2][2] = {
|
||||
{{0, 1}, {2, 1}},
|
||||
{{0, 1}, {0, 1}},
|
||||
{{0, 0}, {2, 2}},
|
||||
{{0, 1}, {0, 0}},
|
||||
{{0, 0}, {0, 1}},
|
||||
{{0, 0}, {2, 0}},
|
||||
{{0, 0}, {0, 2}},
|
||||
{{0, 0}, {0, 0}},
|
||||
};
|
||||
|
||||
struct crnd_chunk_encoding_desc {
|
||||
uint32 m_num_tiles;
|
||||
chunk_tile_desc m_tiles[4];
|
||||
};
|
||||
|
||||
#if 0
|
||||
static crnd_chunk_encoding_desc g_crnd_chunk_encodings[cNumChunkEncodings] =
|
||||
{
|
||||
{ 1, { { 0, 0, 2, 2 } } },
|
||||
|
||||
{ 2, { { 0, 0, 2, 1 }, { 0, 1, 2, 1 } } },
|
||||
{ 2, { { 0, 0, 1, 2 }, { 1, 0, 1, 2 } } },
|
||||
|
||||
{ 3, { { 0, 0, 2, 1 }, { 0, 1, 1, 1 }, { 1, 1, 1, 1 } } },
|
||||
{ 3, { { 0, 1, 2, 1 }, { 0, 0, 1, 1 }, { 1, 0, 1, 1 } } },
|
||||
|
||||
{ 3, { { 0, 0, 1, 2 }, { 1, 0, 1, 1 }, { 1, 1, 1, 1 } } },
|
||||
{ 3, { { 1, 0, 1, 2 }, { 0, 0, 1, 1 }, { 0, 1, 1, 1 } } },
|
||||
|
||||
{ 1, { { 0, 0, 1, 1 }, { 1, 0, 1, 1 }, { 0, 1, 1, 1 }, { 1, 1, 1, 1 } } }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct crnd_encoding_tile_indices {
|
||||
uint8 m_tiles[4];
|
||||
};
|
||||
|
||||
static crnd_encoding_tile_indices g_crnd_chunk_encoding_tiles[cNumChunkEncodings] =
|
||||
{
|
||||
{{0, 0, 0, 0}},
|
||||
|
||||
{{0, 0, 1, 1}},
|
||||
{{0, 1, 0, 1}},
|
||||
|
||||
{{0, 0, 1, 2}},
|
||||
{{1, 2, 0, 0}},
|
||||
|
||||
{{0, 1, 0, 2}},
|
||||
{{1, 0, 2, 0}},
|
||||
|
||||
{{0, 1, 2, 3}}};
|
||||
|
||||
static uint8 g_crnd_chunk_encoding_num_tiles[cNumChunkEncodings] = {1, 2, 2, 3, 3, 3, 3, 4};
|
||||
|
||||
class crn_unpacker {
|
||||
public:
|
||||
inline crn_unpacker()
|
||||
@@ -3523,7 +3481,7 @@ class crn_unpacker {
|
||||
const uint32 num_color_endpoints = m_color_endpoints.size();
|
||||
const uint32 num_color_selectors = m_color_selectors.size();
|
||||
|
||||
uint32 prev_color_endpoint_index = 0;
|
||||
uint32 color_endpoint_index[2][2] = {};
|
||||
uint32 prev_color_selector_index = 0;
|
||||
|
||||
const uint32 num_faces = m_pHeader->m_faces;
|
||||
@@ -3543,7 +3501,6 @@ class crn_unpacker {
|
||||
const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);
|
||||
|
||||
for (uint32 x = 0; x < chunks_x; x++) {
|
||||
uint32 color_endpoints[4];
|
||||
|
||||
if (chunk_encoding_bits == 1) {
|
||||
CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);
|
||||
@@ -3553,18 +3510,21 @@ class crn_unpacker {
|
||||
const uint32 chunk_encoding_index = chunk_encoding_bits & 7;
|
||||
chunk_encoding_bits >>= 3;
|
||||
|
||||
const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];
|
||||
|
||||
for (uint32 i = 0; i < num_tiles; i++) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta);
|
||||
prev_color_endpoint_index += delta;
|
||||
limit(prev_color_endpoint_index, num_color_endpoints);
|
||||
color_endpoints[i] = m_color_endpoints[prev_color_endpoint_index];
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++) {
|
||||
uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx];
|
||||
if (!endpoint_reference) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta);
|
||||
color_endpoint_index[by][bx] = color_endpoint_index[by][bx ^ 1] + delta;
|
||||
if (color_endpoint_index[by][bx] >= num_color_endpoints)
|
||||
color_endpoint_index[by][bx] -= num_color_endpoints;
|
||||
} else {
|
||||
color_endpoint_index[by][bx] = endpoint_reference == 1 ? color_endpoint_index[by][bx ^ 1] : color_endpoint_index[by ^ 1][bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;
|
||||
|
||||
const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));
|
||||
|
||||
uint32* CRND_RESTRICT pD = (uint32*)pBlock;
|
||||
@@ -3578,7 +3538,7 @@ class crn_unpacker {
|
||||
limit(prev_color_selector_index, num_color_selectors);
|
||||
|
||||
if (!((bx && skip_right_col) || (by && skip_bottom_row))) {
|
||||
pD[0] = color_endpoints[pTile_indices[bx + by * 2]];
|
||||
pD[0] = m_color_endpoints[color_endpoint_index[by][bx]];
|
||||
pD[1] = m_color_selectors[prev_color_selector_index];
|
||||
}
|
||||
}
|
||||
@@ -3609,9 +3569,9 @@ class crn_unpacker {
|
||||
const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
|
||||
const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;
|
||||
|
||||
uint32 prev_color_endpoint_index = 0;
|
||||
uint32 color_endpoint_index[2][2] = {};
|
||||
uint32 prev_color_selector_index = 0;
|
||||
uint32 prev_alpha_endpoint_index = 0;
|
||||
uint32 alpha_endpoint_index[2][2] = {};
|
||||
uint32 prev_alpha_selector_index = 0;
|
||||
|
||||
const uint32 num_faces = m_pHeader->m_faces;
|
||||
@@ -3631,8 +3591,8 @@ class crn_unpacker {
|
||||
const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);
|
||||
|
||||
for (uint32 x = 0; x < chunks_x; x++) {
|
||||
uint32 color_endpoints[4];
|
||||
uint32 alpha_endpoints[4];
|
||||
uint32 color_endpoints[2][2];
|
||||
uint32 alpha_endpoints[2][2];
|
||||
|
||||
if (chunk_encoding_bits == 1) {
|
||||
CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);
|
||||
@@ -3642,31 +3602,40 @@ class crn_unpacker {
|
||||
const uint32 chunk_encoding_index = chunk_encoding_bits & 7;
|
||||
chunk_encoding_bits >>= 3;
|
||||
|
||||
const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];
|
||||
|
||||
const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;
|
||||
|
||||
const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));
|
||||
|
||||
uint32* CRND_RESTRICT pD = (uint32*)pBlock;
|
||||
|
||||
for (uint32 i = 0; i < num_tiles; i++) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
prev_alpha_endpoint_index += delta;
|
||||
limit(prev_alpha_endpoint_index, num_alpha_endpoints);
|
||||
alpha_endpoints[i] = m_alpha_endpoints[prev_alpha_endpoint_index];
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++) {
|
||||
uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx];
|
||||
if (!endpoint_reference) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
alpha_endpoint_index[by][bx] = alpha_endpoint_index[by][bx ^ 1] + delta;
|
||||
if (alpha_endpoint_index[by][bx] >= num_alpha_endpoints)
|
||||
alpha_endpoint_index[by][bx] -= num_alpha_endpoints;
|
||||
} else {
|
||||
alpha_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha_endpoint_index[by][bx ^ 1] : alpha_endpoint_index[by ^ 1][bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < num_tiles; i++) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta);
|
||||
prev_color_endpoint_index += delta;
|
||||
limit(prev_color_endpoint_index, num_color_endpoints);
|
||||
color_endpoints[i] = m_color_endpoints[prev_color_endpoint_index];
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++) {
|
||||
uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx];
|
||||
if (!endpoint_reference) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta);
|
||||
color_endpoint_index[by][bx] = color_endpoint_index[by][bx ^ 1] + delta;
|
||||
if (color_endpoint_index[by][bx] >= num_color_endpoints)
|
||||
color_endpoint_index[by][bx] -= num_color_endpoints;
|
||||
} else {
|
||||
color_endpoint_index[by][bx] = endpoint_reference == 1 ? color_endpoint_index[by][bx ^ 1] : color_endpoint_index[by ^ 1][bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pD = (uint32*)pBlock;
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++, pD += 4) {
|
||||
uint32 delta0;
|
||||
@@ -3680,12 +3649,10 @@ class crn_unpacker {
|
||||
limit(prev_color_selector_index, num_color_selectors);
|
||||
|
||||
if (!((bx && skip_right_col) || (by && skip_bottom_row))) {
|
||||
const uint32 tile_index = pTile_indices[bx + by * 2];
|
||||
const uint16* pAlpha_selectors = &m_alpha_selectors[prev_alpha_selector_index * 3];
|
||||
|
||||
pD[0] = alpha_endpoints[tile_index] | (pAlpha_selectors[0] << 16);
|
||||
pD[0] = m_alpha_endpoints[alpha_endpoint_index[by][bx]] | (pAlpha_selectors[0] << 16);
|
||||
pD[1] = pAlpha_selectors[1] | (pAlpha_selectors[2] << 16);
|
||||
pD[2] = color_endpoints[tile_index];
|
||||
pD[2] = m_color_endpoints[color_endpoint_index[by][bx]];
|
||||
pD[3] = m_color_selectors[prev_color_selector_index];
|
||||
}
|
||||
}
|
||||
@@ -3716,9 +3683,9 @@ class crn_unpacker {
|
||||
const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
|
||||
const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;
|
||||
|
||||
uint32 prev_alpha0_endpoint_index = 0;
|
||||
uint32 alpha0_endpoint_index[2][2] = {};
|
||||
uint32 prev_alpha0_selector_index = 0;
|
||||
uint32 prev_alpha1_endpoint_index = 0;
|
||||
uint32 alpha1_endpoint_index[2][2] = {};
|
||||
uint32 prev_alpha1_selector_index = 0;
|
||||
|
||||
const uint32 num_faces = m_pHeader->m_faces;
|
||||
@@ -3738,9 +3705,6 @@ class crn_unpacker {
|
||||
const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);
|
||||
|
||||
for (uint32 x = 0; x < chunks_x; x++) {
|
||||
uint32 alpha0_endpoints[4];
|
||||
uint32 alpha1_endpoints[4];
|
||||
|
||||
if (chunk_encoding_bits == 1) {
|
||||
CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);
|
||||
chunk_encoding_bits |= 512;
|
||||
@@ -3749,31 +3713,40 @@ class crn_unpacker {
|
||||
const uint32 chunk_encoding_index = chunk_encoding_bits & 7;
|
||||
chunk_encoding_bits >>= 3;
|
||||
|
||||
const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];
|
||||
|
||||
const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;
|
||||
|
||||
const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));
|
||||
|
||||
uint32* CRND_RESTRICT pD = (uint32*)pBlock;
|
||||
|
||||
for (uint32 i = 0; i < num_tiles; i++) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
prev_alpha0_endpoint_index += delta;
|
||||
limit(prev_alpha0_endpoint_index, num_alpha_endpoints);
|
||||
alpha0_endpoints[i] = m_alpha_endpoints[prev_alpha0_endpoint_index];
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++) {
|
||||
uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx];
|
||||
if (!endpoint_reference) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
alpha0_endpoint_index[by][bx] = alpha0_endpoint_index[by][bx ^ 1] + delta;
|
||||
if (alpha0_endpoint_index[by][bx] >= num_alpha_endpoints)
|
||||
alpha0_endpoint_index[by][bx] -= num_alpha_endpoints;
|
||||
} else {
|
||||
alpha0_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha0_endpoint_index[by][bx ^ 1] : alpha0_endpoint_index[by ^ 1][bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < num_tiles; i++) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
prev_alpha1_endpoint_index += delta;
|
||||
limit(prev_alpha1_endpoint_index, num_alpha_endpoints);
|
||||
alpha1_endpoints[i] = m_alpha_endpoints[prev_alpha1_endpoint_index];
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++) {
|
||||
uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx];
|
||||
if (!endpoint_reference) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
alpha1_endpoint_index[by][bx] = alpha1_endpoint_index[by][bx ^ 1] + delta;
|
||||
if (alpha1_endpoint_index[by][bx] >= num_alpha_endpoints)
|
||||
alpha1_endpoint_index[by][bx] -= num_alpha_endpoints;
|
||||
} else {
|
||||
alpha1_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha1_endpoint_index[by][bx ^ 1] : alpha1_endpoint_index[by ^ 1][bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pD = (uint32*)pBlock;
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++, pD += 4) {
|
||||
uint32 delta0;
|
||||
@@ -3787,13 +3760,11 @@ class crn_unpacker {
|
||||
limit(prev_alpha1_selector_index, num_alpha_selectors);
|
||||
|
||||
if (!((bx && skip_right_col) || (by && skip_bottom_row))) {
|
||||
const uint32 tile_index = pTile_indices[bx + by * 2];
|
||||
const uint16* pAlpha0_selectors = &m_alpha_selectors[prev_alpha0_selector_index * 3];
|
||||
const uint16* pAlpha1_selectors = &m_alpha_selectors[prev_alpha1_selector_index * 3];
|
||||
|
||||
pD[0] = alpha0_endpoints[tile_index] | (pAlpha0_selectors[0] << 16);
|
||||
pD[0] = m_alpha_endpoints[alpha0_endpoint_index[by][bx]] | (pAlpha0_selectors[0] << 16);
|
||||
pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);
|
||||
pD[2] = alpha1_endpoints[tile_index] | (pAlpha1_selectors[0] << 16);
|
||||
pD[2] = m_alpha_endpoints[alpha1_endpoint_index[by][bx]] | (pAlpha1_selectors[0] << 16);
|
||||
pD[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16);
|
||||
}
|
||||
}
|
||||
@@ -3824,7 +3795,7 @@ class crn_unpacker {
|
||||
const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
|
||||
const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num;
|
||||
|
||||
uint32 prev_alpha0_endpoint_index = 0;
|
||||
uint32 alpha0_endpoint_index[2][2] = {};
|
||||
uint32 prev_alpha0_selector_index = 0;
|
||||
|
||||
const uint32 num_faces = m_pHeader->m_faces;
|
||||
@@ -3842,8 +3813,6 @@ class crn_unpacker {
|
||||
const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1);
|
||||
|
||||
for (uint32 x = 0; x < chunks_x; x++) {
|
||||
uint32 alpha0_endpoints[4];
|
||||
|
||||
if (chunk_encoding_bits == 1) {
|
||||
CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits);
|
||||
chunk_encoding_bits |= 512;
|
||||
@@ -3852,23 +3821,25 @@ class crn_unpacker {
|
||||
const uint32 chunk_encoding_index = chunk_encoding_bits & 7;
|
||||
chunk_encoding_bits >>= 3;
|
||||
|
||||
const uint32 num_tiles = g_crnd_chunk_encoding_num_tiles[chunk_encoding_index];
|
||||
|
||||
const uint8* pTile_indices = g_crnd_chunk_encoding_tiles[chunk_encoding_index].m_tiles;
|
||||
|
||||
const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1));
|
||||
|
||||
uint32* CRND_RESTRICT pD = (uint32*)pBlock;
|
||||
|
||||
for (uint32 i = 0; i < num_tiles; i++) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
prev_alpha0_endpoint_index += delta;
|
||||
limit(prev_alpha0_endpoint_index, num_alpha_endpoints);
|
||||
alpha0_endpoints[i] = m_alpha_endpoints[prev_alpha0_endpoint_index];
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++) {
|
||||
uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx];
|
||||
if (!endpoint_reference) {
|
||||
uint32 delta;
|
||||
CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta);
|
||||
alpha0_endpoint_index[by][bx] = alpha0_endpoint_index[by][bx ^ 1] + delta;
|
||||
if (alpha0_endpoint_index[by][bx] >= num_alpha_endpoints)
|
||||
alpha0_endpoint_index[by][bx] -= num_alpha_endpoints;
|
||||
} else {
|
||||
alpha0_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha0_endpoint_index[by][bx ^ 1] : alpha0_endpoint_index[by ^ 1][bx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pD = (uint32*)pBlock;
|
||||
for (uint32 by = 0; by < 2; by++) {
|
||||
for (uint32 bx = 0; bx < 2; bx++, pD += 2) {
|
||||
uint32 delta;
|
||||
@@ -3877,10 +3848,8 @@ class crn_unpacker {
|
||||
limit(prev_alpha0_selector_index, num_alpha_selectors);
|
||||
|
||||
if (!((bx && skip_right_col) || (by && skip_bottom_row))) {
|
||||
const uint32 tile_index = pTile_indices[bx + by * 2];
|
||||
const uint16* pAlpha0_selectors = &m_alpha_selectors[prev_alpha0_selector_index * 3];
|
||||
|
||||
pD[0] = alpha0_endpoints[tile_index] | (pAlpha0_selectors[0] << 16);
|
||||
pD[0] = m_alpha_endpoints[alpha0_endpoint_index[by][bx]] | (pAlpha0_selectors[0] << 16);
|
||||
pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user