basisu_global_selector_palette.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. // basisu_global_selector_palette.h
  2. // Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
  3. //
  4. // TODO: NONE of this is used in .basis/.ktx2 files. It will be deleted soon.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License");
  7. // you may not use this file except in compliance with the License.
  8. // You may obtain a copy of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17. #pragma once
  18. #include "basisu_transcoder_internal.h"
  19. #include <algorithm>
  20. namespace basist
  21. {
  22. class etc1_global_palette_entry_modifier
  23. {
  24. public:
  25. enum { cTotalBits = 15, cTotalValues = 1 << cTotalBits };
  26. etc1_global_palette_entry_modifier(uint32_t index = 0)
  27. {
  28. #ifdef _DEBUG
  29. static bool s_tested;
  30. if (!s_tested)
  31. {
  32. s_tested = true;
  33. for (uint32_t i = 0; i < cTotalValues; i++)
  34. {
  35. etc1_global_palette_entry_modifier m(i);
  36. etc1_global_palette_entry_modifier n = m;
  37. assert(n.get_index() == i);
  38. }
  39. }
  40. #endif
  41. set_index(index);
  42. }
  43. void set_index(uint32_t index)
  44. {
  45. assert(index < cTotalValues);
  46. m_rot = index & 3;
  47. m_flip = (index >> 2) & 1;
  48. m_inv = (index >> 3) & 1;
  49. m_contrast = (index >> 4) & 3;
  50. m_shift = (index >> 6) & 1;
  51. m_median = (index >> 7) & 1;
  52. m_div = (index >> 8) & 1;
  53. m_rand = (index >> 9) & 1;
  54. m_dilate = (index >> 10) & 1;
  55. m_shift_x = (index >> 11) & 1;
  56. m_shift_y = (index >> 12) & 1;
  57. m_erode = (index >> 13) & 1;
  58. m_high_pass = (index >> 14) & 1;
  59. }
  60. uint32_t get_index() const
  61. {
  62. 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);
  63. }
  64. void clear()
  65. {
  66. basisu::clear_obj(*this);
  67. }
  68. uint8_t m_contrast;
  69. bool m_rand;
  70. bool m_median;
  71. bool m_div;
  72. bool m_shift;
  73. bool m_inv;
  74. bool m_flip;
  75. bool m_dilate;
  76. bool m_shift_x;
  77. bool m_shift_y;
  78. bool m_erode;
  79. bool m_high_pass;
  80. uint8_t m_rot;
  81. };
  82. enum modifier_types
  83. {
  84. cModifierContrast,
  85. cModifierRand,
  86. cModifierMedian,
  87. cModifierDiv,
  88. cModifierShift,
  89. cModifierInv,
  90. cModifierFlippedAndRotated,
  91. cModifierDilate,
  92. cModifierShiftX,
  93. cModifierShiftY,
  94. cModifierErode,
  95. cModifierHighPass,
  96. cTotalModifiers
  97. };
  98. #define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_MOD_BITS (etc1_global_palette_entry_modifier::cTotalBits)
  99. struct etc1_selector_palette_entry
  100. {
  101. etc1_selector_palette_entry()
  102. {
  103. clear();
  104. }
  105. void clear()
  106. {
  107. basisu::clear_obj(*this);
  108. }
  109. uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; }
  110. uint8_t&operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; }
  111. void set_uint32(uint32_t v)
  112. {
  113. for (uint32_t byte_index = 0; byte_index < 4; byte_index++)
  114. {
  115. uint32_t b = (v >> (byte_index * 8)) & 0xFF;
  116. m_selectors[byte_index * 4 + 0] = b & 3;
  117. m_selectors[byte_index * 4 + 1] = (b >> 2) & 3;
  118. m_selectors[byte_index * 4 + 2] = (b >> 4) & 3;
  119. m_selectors[byte_index * 4 + 3] = (b >> 6) & 3;
  120. }
  121. }
  122. uint32_t get_uint32() const
  123. {
  124. return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24);
  125. }
  126. uint32_t get_byte(uint32_t byte_index) const
  127. {
  128. assert(byte_index < 4);
  129. return m_selectors[byte_index * 4 + 0] |
  130. (m_selectors[byte_index * 4 + 1] << 2) |
  131. (m_selectors[byte_index * 4 + 2] << 4) |
  132. (m_selectors[byte_index * 4 + 3] << 6);
  133. }
  134. uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
  135. uint8_t&operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
  136. uint32_t calc_distance(const etc1_selector_palette_entry &other) const
  137. {
  138. uint32_t dist = 0;
  139. for (uint32_t i = 0; i < 8; i++)
  140. {
  141. int delta = static_cast<int>(m_selectors[i]) - static_cast<int>(other.m_selectors[i]);
  142. dist += delta * delta;
  143. }
  144. return dist;
  145. }
  146. #if 0
  147. uint32_t calc_hamming_dist(const etc1_selector_palette_entry &other) const
  148. {
  149. uint32_t dist = 0;
  150. for (uint32_t i = 0; i < 4; i++)
  151. dist += g_hamming_dist[get_byte(i) ^ other.get_byte(i)];
  152. return dist;
  153. }
  154. #endif
  155. etc1_selector_palette_entry get_inverted() const
  156. {
  157. etc1_selector_palette_entry result;
  158. for (uint32_t i = 0; i < 16; i++)
  159. result.m_selectors[i] = 3 - m_selectors[i];
  160. return result;
  161. }
  162. etc1_selector_palette_entry get_divided() const
  163. {
  164. etc1_selector_palette_entry result;
  165. const uint8_t div_selector[4] = { 2, 0, 3, 1 };
  166. for (uint32_t i = 0; i < 16; i++)
  167. result.m_selectors[i] = div_selector[m_selectors[i]];
  168. return result;
  169. }
  170. etc1_selector_palette_entry get_shifted(int delta) const
  171. {
  172. etc1_selector_palette_entry result;
  173. for (uint32_t i = 0; i < 16; i++)
  174. result.m_selectors[i] = static_cast<uint8_t>(basisu::clamp<int>(m_selectors[i] + delta, 0, 3));
  175. return result;
  176. }
  177. etc1_selector_palette_entry get_randomized() const
  178. {
  179. uint32_t seed = get_uint32();
  180. etc1_selector_palette_entry result;
  181. for (uint32_t y = 0; y < 4; y++)
  182. {
  183. for (uint32_t x = 0; x < 4; x++)
  184. {
  185. int s = (*this)(x, y);
  186. // between 0 and 10
  187. uint32_t i = basisd_urand(seed, 6) + basisd_urand(seed, 6);
  188. if (i == 0)
  189. s -= 2;
  190. else if (i == 10)
  191. s += 2;
  192. else if (i < 3)
  193. s -= 1;
  194. else if (i > 7)
  195. s += 1;
  196. result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(s, 0, 3));
  197. }
  198. }
  199. return result;
  200. }
  201. etc1_selector_palette_entry get_contrast(int table_index) const
  202. {
  203. assert(table_index < 4);
  204. etc1_selector_palette_entry result;
  205. static const uint8_t s_contrast_tables[4][4] =
  206. {
  207. { 0, 1, 2, 3 }, // not used
  208. { 0, 0, 3, 3 },
  209. { 1, 1, 2, 2 },
  210. { 1, 1, 3, 3 }
  211. };
  212. for (uint32_t i = 0; i < 16; i++)
  213. {
  214. result[i] = s_contrast_tables[table_index][(*this)[i]];
  215. }
  216. return result;
  217. }
  218. etc1_selector_palette_entry get_dilated() const
  219. {
  220. etc1_selector_palette_entry result;
  221. for (uint32_t y = 0; y < 4; y++)
  222. {
  223. for (uint32_t x = 0; x < 4; x++)
  224. {
  225. uint32_t max_selector = 0;
  226. for (int yd = -1; yd <= 1; yd++)
  227. {
  228. int fy = y + yd;
  229. if ((fy < 0) || (fy > 3))
  230. continue;
  231. for (int xd = -1; xd <= 1; xd++)
  232. {
  233. int fx = x + xd;
  234. if ((fx < 0) || (fx > 3))
  235. continue;
  236. max_selector = basisu::maximum<uint32_t>(max_selector, (*this)(fx, fy));
  237. }
  238. }
  239. result(x, y) = static_cast<uint8_t>(max_selector);
  240. }
  241. }
  242. return result;
  243. }
  244. etc1_selector_palette_entry get_eroded() const
  245. {
  246. etc1_selector_palette_entry result;
  247. for (uint32_t y = 0; y < 4; y++)
  248. {
  249. for (uint32_t x = 0; x < 4; x++)
  250. {
  251. uint32_t min_selector = 99;
  252. for (int yd = -1; yd <= 1; yd++)
  253. {
  254. int fy = y + yd;
  255. if ((fy < 0) || (fy > 3))
  256. continue;
  257. for (int xd = -1; xd <= 1; xd++)
  258. {
  259. int fx = x + xd;
  260. if ((fx < 0) || (fx > 3))
  261. continue;
  262. min_selector = basisu::minimum<uint32_t>(min_selector, (*this)(fx, fy));
  263. }
  264. }
  265. result(x, y) = static_cast<uint8_t>(min_selector);
  266. }
  267. }
  268. return result;
  269. }
  270. etc1_selector_palette_entry get_shift_x() const
  271. {
  272. etc1_selector_palette_entry result;
  273. for (uint32_t y = 0; y < 4; y++)
  274. {
  275. for (uint32_t x = 0; x < 4; x++)
  276. {
  277. int sx = x - 1;
  278. if (sx < 0)
  279. sx = 0;
  280. result(x, y) = (*this)(sx, y);
  281. }
  282. }
  283. return result;
  284. }
  285. etc1_selector_palette_entry get_shift_y() const
  286. {
  287. etc1_selector_palette_entry result;
  288. for (uint32_t y = 0; y < 4; y++)
  289. {
  290. int sy = y - 1;
  291. if (sy < 0)
  292. sy = 3;
  293. for (uint32_t x = 0; x < 4; x++)
  294. result(x, y) = (*this)(x, sy);
  295. }
  296. return result;
  297. }
  298. etc1_selector_palette_entry get_median() const
  299. {
  300. etc1_selector_palette_entry result;
  301. for (uint32_t y = 0; y < 4; y++)
  302. {
  303. for (uint32_t x = 0; x < 4; x++)
  304. {
  305. // ABC
  306. // D F
  307. // GHI
  308. uint8_t selectors[8];
  309. uint32_t n = 0;
  310. for (int yd = -1; yd <= 1; yd++)
  311. {
  312. int fy = y + yd;
  313. if ((fy < 0) || (fy > 3))
  314. continue;
  315. for (int xd = -1; xd <= 1; xd++)
  316. {
  317. if ((xd | yd) == 0)
  318. continue;
  319. int fx = x + xd;
  320. if ((fx < 0) || (fx > 3))
  321. continue;
  322. selectors[n++] = (*this)(fx, fy);
  323. }
  324. }
  325. std::sort(selectors, selectors + n);
  326. result(x, y) = selectors[n / 2];
  327. }
  328. }
  329. return result;
  330. }
  331. etc1_selector_palette_entry get_high_pass() const
  332. {
  333. etc1_selector_palette_entry result;
  334. static const int kernel[3][3] =
  335. {
  336. { 0, -1, 0 },
  337. { -1, 8, -1 },
  338. { 0, -1, 0 }
  339. };
  340. for (uint32_t y = 0; y < 4; y++)
  341. {
  342. for (uint32_t x = 0; x < 4; x++)
  343. {
  344. // ABC
  345. // D F
  346. // GHI
  347. int sum = 0;
  348. for (int yd = -1; yd <= 1; yd++)
  349. {
  350. int fy = y + yd;
  351. fy = basisu::clamp<int>(fy, 0, 3);
  352. for (int xd = -1; xd <= 1; xd++)
  353. {
  354. int fx = x + xd;
  355. fx = basisu::clamp<int>(fx, 0, 3);
  356. int k = (*this)(fx, fy);
  357. sum += k * kernel[yd + 1][xd + 1];
  358. }
  359. }
  360. sum = sum / 4;
  361. result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(sum, 0, 3));
  362. }
  363. }
  364. return result;
  365. }
  366. etc1_selector_palette_entry get_flipped_and_rotated(bool flip, uint32_t rotation_index) const
  367. {
  368. etc1_selector_palette_entry temp;
  369. if (flip)
  370. {
  371. for (uint32_t y = 0; y < 4; y++)
  372. for (uint32_t x = 0; x < 4; x++)
  373. temp(x, y) = (*this)(x, 3 - y);
  374. }
  375. else
  376. {
  377. temp = *this;
  378. }
  379. etc1_selector_palette_entry result;
  380. switch (rotation_index)
  381. {
  382. case 0:
  383. result = temp;
  384. break;
  385. case 1:
  386. for (uint32_t y = 0; y < 4; y++)
  387. for (uint32_t x = 0; x < 4; x++)
  388. result(x, y) = temp(y, 3 - x);
  389. break;
  390. case 2:
  391. for (uint32_t y = 0; y < 4; y++)
  392. for (uint32_t x = 0; x < 4; x++)
  393. result(x, y) = temp(3 - x, 3 - y);
  394. break;
  395. case 3:
  396. for (uint32_t y = 0; y < 4; y++)
  397. for (uint32_t x = 0; x < 4; x++)
  398. result(x, y) = temp(3 - y, x);
  399. break;
  400. default:
  401. assert(0);
  402. break;
  403. }
  404. return result;
  405. }
  406. etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier) const
  407. {
  408. etc1_selector_palette_entry r(*this);
  409. if (modifier.m_shift_x)
  410. r = r.get_shift_x();
  411. if (modifier.m_shift_y)
  412. r = r.get_shift_y();
  413. r = r.get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
  414. if (modifier.m_dilate)
  415. r = r.get_dilated();
  416. if (modifier.m_erode)
  417. r = r.get_eroded();
  418. if (modifier.m_high_pass)
  419. r = r.get_high_pass();
  420. if (modifier.m_rand)
  421. r = r.get_randomized();
  422. if (modifier.m_div)
  423. r = r.get_divided();
  424. if (modifier.m_shift)
  425. r = r.get_shifted(1);
  426. if (modifier.m_contrast)
  427. r = r.get_contrast(modifier.m_contrast);
  428. if (modifier.m_inv)
  429. r = r.get_inverted();
  430. if (modifier.m_median)
  431. r = r.get_median();
  432. return r;
  433. }
  434. etc1_selector_palette_entry apply_modifier(modifier_types mod_type, const etc1_global_palette_entry_modifier &modifier) const
  435. {
  436. switch (mod_type)
  437. {
  438. case cModifierContrast:
  439. return get_contrast(modifier.m_contrast);
  440. case cModifierRand:
  441. return get_randomized();
  442. case cModifierMedian:
  443. return get_median();
  444. case cModifierDiv:
  445. return get_divided();
  446. case cModifierShift:
  447. return get_shifted(1);
  448. case cModifierInv:
  449. return get_inverted();
  450. case cModifierFlippedAndRotated:
  451. return get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
  452. case cModifierDilate:
  453. return get_dilated();
  454. case cModifierShiftX:
  455. return get_shift_x();
  456. case cModifierShiftY:
  457. return get_shift_y();
  458. case cModifierErode:
  459. return get_eroded();
  460. case cModifierHighPass:
  461. return get_high_pass();
  462. default:
  463. assert(0);
  464. break;
  465. }
  466. return *this;
  467. }
  468. etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier, uint32_t num_order, const modifier_types *pOrder) const
  469. {
  470. etc1_selector_palette_entry r(*this);
  471. for (uint32_t i = 0; i < num_order; i++)
  472. {
  473. r = r.apply_modifier(pOrder[i], modifier);
  474. }
  475. return r;
  476. }
  477. bool operator< (const etc1_selector_palette_entry &other) const
  478. {
  479. for (uint32_t i = 0; i < 16; i++)
  480. {
  481. if (m_selectors[i] < other.m_selectors[i])
  482. return true;
  483. else if (m_selectors[i] != other.m_selectors[i])
  484. return false;
  485. }
  486. return false;
  487. }
  488. bool operator== (const etc1_selector_palette_entry &other) const
  489. {
  490. for (uint32_t i = 0; i < 16; i++)
  491. {
  492. if (m_selectors[i] != other.m_selectors[i])
  493. return false;
  494. }
  495. return true;
  496. }
  497. private:
  498. uint8_t m_selectors[16];
  499. };
  500. typedef basisu::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec;
  501. extern const uint32_t g_global_selector_cb[];
  502. extern const uint32_t g_global_selector_cb_size;
  503. #define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS (12)
  504. struct etc1_global_selector_codebook_entry_id
  505. {
  506. uint32_t m_palette_index;
  507. etc1_global_palette_entry_modifier m_modifier;
  508. 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) { }
  509. etc1_global_selector_codebook_entry_id() { }
  510. void set(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) { m_palette_index = palette_index; m_modifier = modifier; }
  511. };
  512. typedef basisu::vector<etc1_global_selector_codebook_entry_id> etc1_global_selector_codebook_entry_id_vec;
  513. class etc1_global_selector_codebook
  514. {
  515. public:
  516. etc1_global_selector_codebook() { }
  517. etc1_global_selector_codebook(uint32_t N, const uint32_t *pEntries) { init(N, pEntries); }
  518. void init(uint32_t N, const uint32_t* pEntries);
  519. void print_code(FILE *pFile);
  520. void clear()
  521. {
  522. m_palette.clear();
  523. }
  524. uint32_t size() const { return (uint32_t)m_palette.size(); }
  525. const etc1_selector_palette_entry_vec &get_palette() const
  526. {
  527. return m_palette;
  528. }
  529. etc1_selector_palette_entry get_entry(uint32_t palette_index) const
  530. {
  531. return m_palette[palette_index];
  532. }
  533. etc1_selector_palette_entry get_entry(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) const
  534. {
  535. return m_palette[palette_index].get_modified(modifier);
  536. }
  537. etc1_selector_palette_entry get_entry(const etc1_global_selector_codebook_entry_id &id) const
  538. {
  539. return m_palette[id.m_palette_index].get_modified(id.m_modifier);
  540. }
  541. etc1_selector_palette_entry_vec m_palette;
  542. };
  543. } // namespace basist