123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- // basisu_global_selector_palette.h
- // Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
- //
- // TODO: NONE of this is used in .basis/.ktx2 files. It will be deleted soon.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #pragma once
- #include "basisu_transcoder_internal.h"
- #include <algorithm>
- namespace basist
- {
- class etc1_global_palette_entry_modifier
- {
- public:
- enum { cTotalBits = 15, cTotalValues = 1 << cTotalBits };
- etc1_global_palette_entry_modifier(uint32_t index = 0)
- {
- #ifdef _DEBUG
- static bool s_tested;
- if (!s_tested)
- {
- s_tested = true;
- for (uint32_t i = 0; i < cTotalValues; i++)
- {
- etc1_global_palette_entry_modifier m(i);
- etc1_global_palette_entry_modifier n = m;
- assert(n.get_index() == i);
- }
- }
- #endif
- set_index(index);
- }
- void set_index(uint32_t index)
- {
- assert(index < cTotalValues);
- m_rot = index & 3;
- m_flip = (index >> 2) & 1;
- m_inv = (index >> 3) & 1;
- m_contrast = (index >> 4) & 3;
- m_shift = (index >> 6) & 1;
- m_median = (index >> 7) & 1;
- m_div = (index >> 8) & 1;
- m_rand = (index >> 9) & 1;
- m_dilate = (index >> 10) & 1;
- m_shift_x = (index >> 11) & 1;
- m_shift_y = (index >> 12) & 1;
- m_erode = (index >> 13) & 1;
- m_high_pass = (index >> 14) & 1;
- }
- uint32_t get_index() const
- {
- return m_rot | (m_flip << 2) | (m_inv << 3) | (m_contrast << 4) | (m_shift << 6) | (m_median << 7) | (m_div << 8) | (m_rand << 9) | (m_dilate << 10) | (m_shift_x << 11) | (m_shift_y << 12) | (m_erode << 13) | (m_high_pass << 14);
- }
- void clear()
- {
- basisu::clear_obj(*this);
- }
- uint8_t m_contrast;
- bool m_rand;
- bool m_median;
- bool m_div;
- bool m_shift;
- bool m_inv;
- bool m_flip;
- bool m_dilate;
- bool m_shift_x;
- bool m_shift_y;
- bool m_erode;
- bool m_high_pass;
- uint8_t m_rot;
- };
- enum modifier_types
- {
- cModifierContrast,
- cModifierRand,
- cModifierMedian,
- cModifierDiv,
- cModifierShift,
- cModifierInv,
- cModifierFlippedAndRotated,
- cModifierDilate,
- cModifierShiftX,
- cModifierShiftY,
- cModifierErode,
- cModifierHighPass,
- cTotalModifiers
- };
- #define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_MOD_BITS (etc1_global_palette_entry_modifier::cTotalBits)
- struct etc1_selector_palette_entry
- {
- etc1_selector_palette_entry()
- {
- clear();
- }
- void clear()
- {
- basisu::clear_obj(*this);
- }
- uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; }
- uint8_t&operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; }
- void set_uint32(uint32_t v)
- {
- for (uint32_t byte_index = 0; byte_index < 4; byte_index++)
- {
- uint32_t b = (v >> (byte_index * 8)) & 0xFF;
- m_selectors[byte_index * 4 + 0] = b & 3;
- m_selectors[byte_index * 4 + 1] = (b >> 2) & 3;
- m_selectors[byte_index * 4 + 2] = (b >> 4) & 3;
- m_selectors[byte_index * 4 + 3] = (b >> 6) & 3;
- }
- }
- uint32_t get_uint32() const
- {
- return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24);
- }
- uint32_t get_byte(uint32_t byte_index) const
- {
- assert(byte_index < 4);
- return m_selectors[byte_index * 4 + 0] |
- (m_selectors[byte_index * 4 + 1] << 2) |
- (m_selectors[byte_index * 4 + 2] << 4) |
- (m_selectors[byte_index * 4 + 3] << 6);
- }
- uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
- uint8_t&operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
- uint32_t calc_distance(const etc1_selector_palette_entry &other) const
- {
- uint32_t dist = 0;
- for (uint32_t i = 0; i < 8; i++)
- {
- int delta = static_cast<int>(m_selectors[i]) - static_cast<int>(other.m_selectors[i]);
- dist += delta * delta;
- }
- return dist;
- }
- #if 0
- uint32_t calc_hamming_dist(const etc1_selector_palette_entry &other) const
- {
- uint32_t dist = 0;
- for (uint32_t i = 0; i < 4; i++)
- dist += g_hamming_dist[get_byte(i) ^ other.get_byte(i)];
- return dist;
- }
- #endif
- etc1_selector_palette_entry get_inverted() const
- {
- etc1_selector_palette_entry result;
- for (uint32_t i = 0; i < 16; i++)
- result.m_selectors[i] = 3 - m_selectors[i];
- return result;
- }
- etc1_selector_palette_entry get_divided() const
- {
- etc1_selector_palette_entry result;
- const uint8_t div_selector[4] = { 2, 0, 3, 1 };
- for (uint32_t i = 0; i < 16; i++)
- result.m_selectors[i] = div_selector[m_selectors[i]];
- return result;
- }
- etc1_selector_palette_entry get_shifted(int delta) const
- {
- etc1_selector_palette_entry result;
- for (uint32_t i = 0; i < 16; i++)
- result.m_selectors[i] = static_cast<uint8_t>(basisu::clamp<int>(m_selectors[i] + delta, 0, 3));
- return result;
- }
- etc1_selector_palette_entry get_randomized() const
- {
- uint32_t seed = get_uint32();
- etc1_selector_palette_entry result;
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- int s = (*this)(x, y);
- // between 0 and 10
- uint32_t i = basisd_urand(seed, 6) + basisd_urand(seed, 6);
- if (i == 0)
- s -= 2;
- else if (i == 10)
- s += 2;
- else if (i < 3)
- s -= 1;
- else if (i > 7)
- s += 1;
- result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(s, 0, 3));
- }
- }
- return result;
- }
- etc1_selector_palette_entry get_contrast(int table_index) const
- {
- assert(table_index < 4);
- etc1_selector_palette_entry result;
- static const uint8_t s_contrast_tables[4][4] =
- {
- { 0, 1, 2, 3 }, // not used
- { 0, 0, 3, 3 },
- { 1, 1, 2, 2 },
- { 1, 1, 3, 3 }
- };
- for (uint32_t i = 0; i < 16; i++)
- {
- result[i] = s_contrast_tables[table_index][(*this)[i]];
- }
- return result;
- }
- etc1_selector_palette_entry get_dilated() const
- {
- etc1_selector_palette_entry result;
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- uint32_t max_selector = 0;
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- if ((fy < 0) || (fy > 3))
- continue;
- for (int xd = -1; xd <= 1; xd++)
- {
- int fx = x + xd;
- if ((fx < 0) || (fx > 3))
- continue;
- max_selector = basisu::maximum<uint32_t>(max_selector, (*this)(fx, fy));
- }
- }
- result(x, y) = static_cast<uint8_t>(max_selector);
- }
- }
- return result;
- }
- etc1_selector_palette_entry get_eroded() const
- {
- etc1_selector_palette_entry result;
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- uint32_t min_selector = 99;
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- if ((fy < 0) || (fy > 3))
- continue;
- for (int xd = -1; xd <= 1; xd++)
- {
- int fx = x + xd;
- if ((fx < 0) || (fx > 3))
- continue;
- min_selector = basisu::minimum<uint32_t>(min_selector, (*this)(fx, fy));
- }
- }
- result(x, y) = static_cast<uint8_t>(min_selector);
- }
- }
- return result;
- }
- etc1_selector_palette_entry get_shift_x() const
- {
- etc1_selector_palette_entry result;
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- int sx = x - 1;
- if (sx < 0)
- sx = 0;
- result(x, y) = (*this)(sx, y);
- }
- }
- return result;
- }
- etc1_selector_palette_entry get_shift_y() const
- {
- etc1_selector_palette_entry result;
- for (uint32_t y = 0; y < 4; y++)
- {
- int sy = y - 1;
- if (sy < 0)
- sy = 3;
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = (*this)(x, sy);
- }
- return result;
- }
- etc1_selector_palette_entry get_median() const
- {
- etc1_selector_palette_entry result;
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- // ABC
- // D F
- // GHI
- uint8_t selectors[8];
- uint32_t n = 0;
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- if ((fy < 0) || (fy > 3))
- continue;
- for (int xd = -1; xd <= 1; xd++)
- {
- if ((xd | yd) == 0)
- continue;
- int fx = x + xd;
- if ((fx < 0) || (fx > 3))
- continue;
- selectors[n++] = (*this)(fx, fy);
- }
- }
- std::sort(selectors, selectors + n);
- result(x, y) = selectors[n / 2];
- }
- }
- return result;
- }
- etc1_selector_palette_entry get_high_pass() const
- {
- etc1_selector_palette_entry result;
- static const int kernel[3][3] =
- {
- { 0, -1, 0 },
- { -1, 8, -1 },
- { 0, -1, 0 }
- };
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- // ABC
- // D F
- // GHI
- int sum = 0;
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- fy = basisu::clamp<int>(fy, 0, 3);
- for (int xd = -1; xd <= 1; xd++)
- {
- int fx = x + xd;
- fx = basisu::clamp<int>(fx, 0, 3);
- int k = (*this)(fx, fy);
- sum += k * kernel[yd + 1][xd + 1];
- }
- }
- sum = sum / 4;
- result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(sum, 0, 3));
- }
- }
- return result;
- }
- etc1_selector_palette_entry get_flipped_and_rotated(bool flip, uint32_t rotation_index) const
- {
- etc1_selector_palette_entry temp;
- if (flip)
- {
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- temp(x, y) = (*this)(x, 3 - y);
- }
- else
- {
- temp = *this;
- }
- etc1_selector_palette_entry result;
- switch (rotation_index)
- {
- case 0:
- result = temp;
- break;
- case 1:
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = temp(y, 3 - x);
- break;
- case 2:
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = temp(3 - x, 3 - y);
- break;
- case 3:
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = temp(3 - y, x);
- break;
- default:
- assert(0);
- break;
- }
- return result;
- }
- etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier) const
- {
- etc1_selector_palette_entry r(*this);
- if (modifier.m_shift_x)
- r = r.get_shift_x();
- if (modifier.m_shift_y)
- r = r.get_shift_y();
- r = r.get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
- if (modifier.m_dilate)
- r = r.get_dilated();
- if (modifier.m_erode)
- r = r.get_eroded();
- if (modifier.m_high_pass)
- r = r.get_high_pass();
- if (modifier.m_rand)
- r = r.get_randomized();
- if (modifier.m_div)
- r = r.get_divided();
- if (modifier.m_shift)
- r = r.get_shifted(1);
- if (modifier.m_contrast)
- r = r.get_contrast(modifier.m_contrast);
- if (modifier.m_inv)
- r = r.get_inverted();
- if (modifier.m_median)
- r = r.get_median();
- return r;
- }
- etc1_selector_palette_entry apply_modifier(modifier_types mod_type, const etc1_global_palette_entry_modifier &modifier) const
- {
- switch (mod_type)
- {
- case cModifierContrast:
- return get_contrast(modifier.m_contrast);
- case cModifierRand:
- return get_randomized();
- case cModifierMedian:
- return get_median();
- case cModifierDiv:
- return get_divided();
- case cModifierShift:
- return get_shifted(1);
- case cModifierInv:
- return get_inverted();
- case cModifierFlippedAndRotated:
- return get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
- case cModifierDilate:
- return get_dilated();
- case cModifierShiftX:
- return get_shift_x();
- case cModifierShiftY:
- return get_shift_y();
- case cModifierErode:
- return get_eroded();
- case cModifierHighPass:
- return get_high_pass();
- default:
- assert(0);
- break;
- }
- return *this;
- }
- etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier, uint32_t num_order, const modifier_types *pOrder) const
- {
- etc1_selector_palette_entry r(*this);
- for (uint32_t i = 0; i < num_order; i++)
- {
- r = r.apply_modifier(pOrder[i], modifier);
- }
- return r;
- }
- bool operator< (const etc1_selector_palette_entry &other) const
- {
- for (uint32_t i = 0; i < 16; i++)
- {
- if (m_selectors[i] < other.m_selectors[i])
- return true;
- else if (m_selectors[i] != other.m_selectors[i])
- return false;
- }
- return false;
- }
- bool operator== (const etc1_selector_palette_entry &other) const
- {
- for (uint32_t i = 0; i < 16; i++)
- {
- if (m_selectors[i] != other.m_selectors[i])
- return false;
- }
- return true;
- }
- private:
- uint8_t m_selectors[16];
- };
- typedef basisu::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec;
- extern const uint32_t g_global_selector_cb[];
- extern const uint32_t g_global_selector_cb_size;
- #define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS (12)
- struct etc1_global_selector_codebook_entry_id
- {
- uint32_t m_palette_index;
- etc1_global_palette_entry_modifier m_modifier;
- etc1_global_selector_codebook_entry_id(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) : m_palette_index(palette_index), m_modifier(modifier) { }
- etc1_global_selector_codebook_entry_id() { }
- void set(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) { m_palette_index = palette_index; m_modifier = modifier; }
- };
- typedef basisu::vector<etc1_global_selector_codebook_entry_id> etc1_global_selector_codebook_entry_id_vec;
- class etc1_global_selector_codebook
- {
- public:
- etc1_global_selector_codebook() { }
- etc1_global_selector_codebook(uint32_t N, const uint32_t *pEntries) { init(N, pEntries); }
- void init(uint32_t N, const uint32_t* pEntries);
- void print_code(FILE *pFile);
- void clear()
- {
- m_palette.clear();
- }
- uint32_t size() const { return (uint32_t)m_palette.size(); }
- const etc1_selector_palette_entry_vec &get_palette() const
- {
- return m_palette;
- }
- etc1_selector_palette_entry get_entry(uint32_t palette_index) const
- {
- return m_palette[palette_index];
- }
- etc1_selector_palette_entry get_entry(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) const
- {
- return m_palette[palette_index].get_modified(modifier);
- }
- etc1_selector_palette_entry get_entry(const etc1_global_selector_codebook_entry_id &id) const
- {
- return m_palette[id.m_palette_index].get_modified(id.m_modifier);
- }
- etc1_selector_palette_entry_vec m_palette;
- };
- } // namespace basist
|