static inline void _T_mode_color_read(const uint8_t *etc, uint32_t *paint_colors) { // 4 bit colors const int r1_4 = (BITS(etc[0], 3, 4) << 2) | BITS(etc[0], 0, 1); const int g1_4 = BITS(etc[1], 4, 7); const int b1_4 = BITS(etc[1], 0, 3); const int r2_4 = BITS(etc[2], 4, 7); const int g2_4 = BITS(etc[2], 0, 3); const int b2_4 = BITS(etc[3], 4, 7); // Distance index const int didx = (BITS(etc[3], 2, 3) << 1) | BIT(etc[3], 0); const int d = kDistances[didx]; // Write out paint colors for T mode paint_colors[0] = BGRA(_4to8(r1_4), _4to8(g1_4), _4to8(b1_4), 255); paint_colors[1] = BGRA(CLAMPDOWN(_4to8(r2_4) + d), CLAMPDOWN(_4to8(g2_4) + d), CLAMPDOWN(_4to8(b2_4) + d), 255); paint_colors[2] = BGRA(_4to8(r2_4), _4to8(g2_4), _4to8(b2_4), 255); paint_colors[3] = BGRA(CLAMPUP(_4to8(r2_4) - d), CLAMPUP(_4to8(g2_4) - d), CLAMPUP(_4to8(b2_4) - d), 255); }
void rg_etc2_rgba8_decode_block(const unsigned char *etc, unsigned int *bgra) { const uint8_t zeros[7] = {0}; uint32_t table_index; int base_codeword; int multiplier; base_codeword = etc[0]; // Fast path if alpha is the same for all pixels if (!memcmp(etc + 1, zeros, 7)) { if (!base_codeword) memset(bgra, 0, 64); else { rg_etc2_rgb8_decode_block(etc + 8, bgra); if (base_codeword != 255) for (int k = 0; k < 16; k++) { const uint32_t rgb = *bgra; const int R = MIN(R_VAL(&rgb), base_codeword); const int G = MIN(G_VAL(&rgb), base_codeword); const int B = MIN(B_VAL(&rgb), base_codeword); *bgra++ = BGRA(R, G, B, base_codeword); } } return; } rg_etc2_rgb8_decode_block(etc + 8, bgra); multiplier = BITS(etc[1], 4, 7); table_index = BITS(etc[1], 0, 3); for (int x = 0, k = 0; x < 4; x++) for (int y = 0; y < 4; y++, k += 3) { const uint32_t byte = (k >> 3); // = [k/8] const uint32_t bit = k - (byte << 3); // = k%8 const uint32_t rgb = bgra[(y << 2) + x]; uint32_t index, alpha, R, G, B; if (bit < 6) index = BITS(etc[byte + 2], 5 - bit, 7 - bit); else if (bit == 6) index = (BITS(etc[byte + 2], 0, 1) << 1) | BIT(etc[byte + 3], 7); else // bit == 7 index = (BIT(etc[byte + 2], 0) << 2) | BITS(etc[byte + 3], 6, 7); alpha = CLAMP(base_codeword + kAlphaModifiers[table_index][index] * multiplier); R = MIN(R_VAL(&rgb), alpha); G = MIN(G_VAL(&rgb), alpha); B = MIN(B_VAL(&rgb), alpha); bgra[(y << 2) + x] = BGRA(R, G, B, alpha); } }
static inline void _planar_mode_color_read(const uint8_t *etc, uint32_t *bgra) { // RO: Bits 57-62 const int RO = _6to8(BITS(etc[0], 1, 6)); // GO: Bits 49-54,56 const int GO = _7to8((BIT(etc[0], 0) << 6) | (BITS(etc[1], 1, 6))); // BO: Bits 39,40-41,43-44,48 const int BO = _6to8((BIT(etc[1], 0) << 5) | (BITS(etc[2], 3, 4) << 3) | (BITS(etc[2], 0, 1) << 1) | BIT(etc[3], 7)); // RH: Bits 32,34-38 const int RH = _6to8((BITS(etc[3], 2, 6) << 1) | BIT(etc[3], 0)); // GH: Bits 25-31 const int GH = _7to8(BITS(etc[4], 1, 7)); // BH: Bits 19-23,24 const int BH = _6to8((BIT(etc[4], 0) << 5) | (BITS(etc[5], 3, 7))); // RV: Bits 13-15,16-18 const int RV = _6to8((BITS(etc[5], 0, 2) << 3) | (BITS(etc[6], 5, 7))); // GV: Bits 6-7,8-12 const int GV = _7to8((BITS(etc[6], 0, 4) << 2) | (BITS(etc[7], 6, 7))); // BV: Bits 0-5 const int BV = _6to8(BITS(etc[7], 0, 5)); for (int y = 0; y < 4; y++) for (int x = 0; x < 4; x++) { // Formulas straight from the spec const int R = CLAMP(((x * (RH - RO)) + y * (RV - RO) + 4 * RO + 2) >> 2); const int G = CLAMP(((x * (GH - GO)) + y * (GV - GO) + 4 * GO + 2) >> 2); const int B = CLAMP(((x * (BH - BO)) + y * (BV - BO) + 4 * BO + 2) >> 2); *bgra++ = BGRA(R, G, B, 255); } }
static inline void _H_mode_color_read(const uint8_t *etc, uint32_t *paint_colors) { // 4 bit colors const int r1_4 = BITS(etc[0], 3, 6); const int g1_4 = (BITS(etc[0], 0, 2) << 1) | (BIT(etc[1], 4)); const int b1_4 = (BIT(etc[1], 3) << 3) | (BITS(etc[1], 0, 1) << 1) | (BIT(etc[2], 7)); const int r2_4 = BITS(etc[2], 3, 6); const int g2_4 = (BITS(etc[2], 0, 2) << 1) | (BIT(etc[3], 7)); const int b2_4 = BITS(etc[3], 3, 6); // Distance index const int basecol1 = (_4to8(r1_4) << 16) | (_4to8(g1_4) << 8) | _4to8(b1_4); const int basecol2 = (_4to8(r2_4) << 16) | (_4to8(g2_4) << 8) | _4to8(b2_4); const int didx = (BIT(etc[3], 2) << 2) | (BIT(etc[3], 0) << 1) | ((basecol1 >= basecol2) ? 1 : 0); const int d = kDistances[didx]; // Write out paint colors for H mode paint_colors[0] = BGRA(CLAMPDOWN(_4to8(r1_4) + d), CLAMPDOWN(_4to8(g1_4) + d), CLAMPDOWN(_4to8(b1_4) + d), 255); paint_colors[1] = BGRA(CLAMPUP(_4to8(r1_4) - d), CLAMPUP(_4to8(g1_4) - d), CLAMPUP(_4to8(b1_4) - d), 255); paint_colors[2] = BGRA(CLAMPDOWN(_4to8(r2_4) + d), CLAMPDOWN(_4to8(g2_4) + d), CLAMPDOWN(_4to8(b2_4) + d), 255); paint_colors[3] = BGRA(CLAMPUP(_4to8(r2_4) - d), CLAMPUP(_4to8(g2_4) - d), CLAMPUP(_4to8(b2_4) - d), 255); }
uint32_t EXPORT createBGRA(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t a) { return BGRA(r, g, b, a); }