Decompress.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Resource/Decompress.h"
  24. #include <cstdint>
  25. // ETC2 decompress
  26. typedef unsigned char uint8;
  27. typedef unsigned short uint16;
  28. typedef short int16;
  29. // Implemented by ETCPACK
  30. extern void decompressBlockAlphaC(uint8* data, uint8* img, int width, int height, int ix, int iy, int channels);
  31. extern void decompressBlockETC2c(unsigned int block_part1, unsigned int block_part2, uint8 *img, int width, int height, int startx, int starty, int channels);
  32. extern void setupAlphaTable();
  33. // DXT decompression based on the Squish library, modified for Urho3D
  34. namespace Urho3D
  35. {
  36. /* -----------------------------------------------------------------------------
  37. Copyright (c) 2006 Simon Brown [email protected]
  38. Permission is hereby granted, free of charge, to any person obtaining
  39. a copy of this software and associated documentation files (the
  40. "Software"), to deal in the Software without restriction, including
  41. without limitation the rights to use, copy, modify, merge, publish,
  42. distribute, sublicense, and/or sell copies of the Software, and to
  43. permit persons to whom the Software is furnished to do so, subject to
  44. the following conditions:
  45. The above copyright notice and this permission notice shall be included
  46. in all copies or substantial portions of the Software.
  47. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  48. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  49. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  50. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  51. CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  52. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  53. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  54. -------------------------------------------------------------------------- */
  55. static int Unpack565(unsigned char const* packed, unsigned char* colour)
  56. {
  57. // build the packed value
  58. int value = (int)packed[0] | ((int)packed[1] << 8);
  59. // get the components in the stored range
  60. auto red = (unsigned char)((value >> 11) & 0x1f);
  61. auto green = (unsigned char)((value >> 5) & 0x3f);
  62. auto blue = (unsigned char)(value & 0x1f);
  63. // scale up to 8 bits
  64. colour[0] = (red << 3) | (red >> 2);
  65. colour[1] = (green << 2) | (green >> 4);
  66. colour[2] = (blue << 3) | (blue >> 2);
  67. colour[3] = 255;
  68. // return the value
  69. return value;
  70. }
  71. static void DecompressColourDXT(unsigned char* rgba, void const* block, bool isDxt1)
  72. {
  73. // get the block bytes
  74. auto const* bytes = reinterpret_cast< unsigned char const* >( block );
  75. // unpack the endpoints
  76. unsigned char codes[16];
  77. int a = Unpack565(bytes, codes);
  78. int b = Unpack565(bytes + 2, codes + 4);
  79. // generate the midpoints
  80. for (int i = 0; i < 3; ++i)
  81. {
  82. int c = codes[i];
  83. int d = codes[4 + i];
  84. if (isDxt1 && a <= b)
  85. {
  86. codes[8 + i] = (unsigned char)((c + d) / 2);
  87. codes[12 + i] = 0;
  88. }
  89. else
  90. {
  91. codes[8 + i] = (unsigned char)((2 * c + d) / 3);
  92. codes[12 + i] = (unsigned char)((c + 2 * d) / 3);
  93. }
  94. }
  95. // fill in alpha for the intermediate values
  96. codes[8 + 3] = 255;
  97. codes[12 + 3] = (unsigned char)((isDxt1 && a <= b) ? 0 : 255);
  98. // unpack the indices
  99. unsigned char indices[16];
  100. for (int i = 0; i < 4; ++i)
  101. {
  102. unsigned char* ind = indices + 4 * i;
  103. unsigned char packed = bytes[4 + i];
  104. ind[0] = (unsigned char)(packed & 0x3);
  105. ind[1] = (unsigned char)((packed >> 2) & 0x3);
  106. ind[2] = (unsigned char)((packed >> 4) & 0x3);
  107. ind[3] = (unsigned char)((packed >> 6) & 0x3);
  108. }
  109. // store out the colours
  110. for (int i = 0; i < 16; ++i)
  111. {
  112. auto offset = (unsigned char)(4 * indices[i]);
  113. for (int j = 0; j < 4; ++j)
  114. rgba[4 * i + j] = codes[offset + j];
  115. }
  116. }
  117. static void DecompressAlphaDXT3(unsigned char* rgba, void const* block)
  118. {
  119. auto const* bytes = reinterpret_cast< unsigned char const* >( block );
  120. // unpack the alpha values pairwise
  121. for (int i = 0; i < 8; ++i)
  122. {
  123. // quantise down to 4 bits
  124. unsigned char quant = bytes[i];
  125. // unpack the values
  126. auto lo = (unsigned char)(quant & 0x0f);
  127. auto hi = (unsigned char)(quant & 0xf0);
  128. // convert back up to bytes
  129. rgba[8 * i + 3] = lo | (lo << 4);
  130. rgba[8 * i + 7] = hi | (hi >> 4);
  131. }
  132. }
  133. static void DecompressAlphaDXT5(unsigned char* rgba, void const* block)
  134. {
  135. // get the two alpha values
  136. auto const* bytes = reinterpret_cast< unsigned char const* >( block );
  137. int alpha0 = bytes[0];
  138. int alpha1 = bytes[1];
  139. // compare the values to build the codebook
  140. unsigned char codes[8];
  141. codes[0] = (unsigned char)alpha0;
  142. codes[1] = (unsigned char)alpha1;
  143. if (alpha0 <= alpha1)
  144. {
  145. // use 5-alpha codebook
  146. for (int i = 1; i < 5; ++i)
  147. codes[1 + i] = (unsigned char)(((5 - i) * alpha0 + i * alpha1) / 5);
  148. codes[6] = 0;
  149. codes[7] = 255;
  150. }
  151. else
  152. {
  153. // use 7-alpha codebook
  154. for (int i = 1; i < 7; ++i)
  155. codes[1 + i] = (unsigned char)(((7 - i) * alpha0 + i * alpha1) / 7);
  156. }
  157. // decode the indices
  158. unsigned char indices[16];
  159. unsigned char const* src = bytes + 2;
  160. unsigned char* dest = indices;
  161. for (int i = 0; i < 2; ++i)
  162. {
  163. // grab 3 bytes
  164. int value = 0;
  165. for (int j = 0; j < 3; ++j)
  166. {
  167. int byte = *src++;
  168. value |= (byte << 8 * j);
  169. }
  170. // unpack 8 3-bit values from it
  171. for (int j = 0; j < 8; ++j)
  172. {
  173. int index = (value >> 3 * j) & 0x7;
  174. *dest++ = (unsigned char)index;
  175. }
  176. }
  177. // write out the indexed codebook values
  178. for (int i = 0; i < 16; ++i)
  179. rgba[4 * i + 3] = codes[indices[i]];
  180. }
  181. static void DecompressDXT(unsigned char* rgba, const void* block, CompressedFormat format)
  182. {
  183. // get the block locations
  184. void const* colourBlock = block;
  185. void const* alphaBock = block;
  186. if (format == CF_DXT3 || format == CF_DXT5)
  187. colourBlock = reinterpret_cast< unsigned char const* >( block ) + 8;
  188. // decompress colour
  189. DecompressColourDXT(rgba, colourBlock, format == CF_DXT1);
  190. // decompress alpha separately if necessary
  191. if (format == CF_DXT3)
  192. DecompressAlphaDXT3(rgba, alphaBock);
  193. else if (format == CF_DXT5)
  194. DecompressAlphaDXT5(rgba, alphaBock);
  195. }
  196. void DecompressImageDXT(unsigned char* rgba, const void* blocks, int width, int height, int depth, CompressedFormat format)
  197. {
  198. // initialise the block input
  199. auto const* sourceBlock = reinterpret_cast< unsigned char const* >( blocks );
  200. int bytesPerBlock = format == CF_DXT1 ? 8 : 16;
  201. // loop over blocks
  202. for (int z = 0; z < depth; ++z)
  203. {
  204. int sz = width * height * 4 * z;
  205. for (int y = 0; y < height; y += 4)
  206. {
  207. for (int x = 0; x < width; x += 4)
  208. {
  209. // decompress the block
  210. unsigned char targetRgba[4 * 16];
  211. DecompressDXT(targetRgba, sourceBlock, format);
  212. // write the decompressed pixels to the correct image locations
  213. unsigned char const* sourcePixel = targetRgba;
  214. for (int py = 0; py < 4; ++py)
  215. {
  216. for (int px = 0; px < 4; ++px)
  217. {
  218. // get the target location
  219. int sx = x + px;
  220. int sy = y + py;
  221. if (sx < width && sy < height)
  222. {
  223. unsigned char* targetPixel = rgba + sz + 4 * (width * sy + sx);
  224. // copy the rgba value
  225. for (int i = 0; i < 4; ++i)
  226. *targetPixel++ = *sourcePixel++;
  227. }
  228. else
  229. {
  230. // skip this pixel as its outside the image
  231. sourcePixel += 4;
  232. }
  233. }
  234. }
  235. // advance
  236. sourceBlock += bytesPerBlock;
  237. }
  238. }
  239. }
  240. }
  241. // PVRTC decompression based on the Oolong Engine, modified for Urho3D
  242. #define PT_INDEX (2) /*The Punch-through index*/
  243. #define BLK_Y_SIZE (4) /*always 4 for all 2D block types*/
  244. #define BLK_X_MAX (8) /*Max X dimension for blocks*/
  245. #define BLK_X_2BPP (8) /*dimensions for the two formats*/
  246. #define BLK_X_4BPP (4)
  247. #define _MIN(X, Y) (((X)<(Y))? (X):(Y))
  248. #define _MAX(X, Y) (((X)>(Y))? (X):(Y))
  249. #define WRAP_COORD(Val, Size) ((Val) & ((Size)-1))
  250. #define CLAMP(X, lower, upper) (_MIN(_MAX((X),(lower)), (upper)))
  251. #define LIMIT_COORD(Val, Size, AssumeImageTiles) ((AssumeImageTiles)? WRAP_COORD((Val), (Size)): CLAMP((Val), 0, (Size)-1))
  252. using AMTC_BLOCK_STRUCT = struct
  253. {
  254. // Uses 64 bits pre block
  255. unsigned PackedData[2];
  256. };
  257. static void Unpack5554Colour(const AMTC_BLOCK_STRUCT* pBlock, int ABColours[2][4])
  258. {
  259. unsigned RawBits[2];
  260. int i;
  261. // Extract A and B
  262. RawBits[0] = pBlock->PackedData[1] & (0xFFFE); /*15 bits (shifted up by one)*/
  263. RawBits[1] = pBlock->PackedData[1] >> 16; /*16 bits*/
  264. // Step through both colours
  265. for (i = 0; i < 2; i++)
  266. {
  267. // If completely opaque
  268. if (RawBits[i] & (1 << 15))
  269. {
  270. // Extract R and G (both 5 bit)
  271. ABColours[i][0] = (RawBits[i] >> 10) & 0x1F;
  272. ABColours[i][1] = (RawBits[i] >> 5) & 0x1F;
  273. // The precision of Blue depends on A or B. If A then we need to
  274. // replicate the top bit to get 5 bits in total
  275. ABColours[i][2] = RawBits[i] & 0x1F;
  276. if (i == 0)
  277. {
  278. ABColours[0][2] |= ABColours[0][2] >> 4;
  279. }
  280. // Set 4bit alpha fully on...
  281. ABColours[i][3] = 0xF;
  282. }
  283. // Else if colour has variable translucency
  284. else
  285. {
  286. // Extract R and G (both 4 bit).
  287. // (Leave a space on the end for the replication of bits
  288. ABColours[i][0] = (RawBits[i] >> (8 - 1)) & 0x1E;
  289. ABColours[i][1] = (RawBits[i] >> (4 - 1)) & 0x1E;
  290. // Replicate bits to truly expand to 5 bits
  291. ABColours[i][0] |= ABColours[i][0] >> 4;
  292. ABColours[i][1] |= ABColours[i][1] >> 4;
  293. // Grab the 3(+padding) or 4 bits of blue and add an extra padding bit
  294. ABColours[i][2] = (RawBits[i] & 0xF) << 1;
  295. // Expand from 3 to 5 bits if this is from colour A, or 4 to 5 bits if from
  296. // colour B
  297. if (i == 0)
  298. {
  299. ABColours[0][2] |= ABColours[0][2] >> 3;
  300. }
  301. else
  302. {
  303. ABColours[0][2] |= ABColours[0][2] >> 4;
  304. }
  305. // Set the alpha bits to be 3 + a zero on the end
  306. ABColours[i][3] = (RawBits[i] >> 11) & 0xE;
  307. }
  308. }
  309. }
  310. static void UnpackModulations(const AMTC_BLOCK_STRUCT* pBlock, const int Do2bitMode, int ModulationVals[8][16],
  311. int ModulationModes[8][16], int StartX, int StartY)
  312. {
  313. int BlockModMode;
  314. unsigned ModulationBits;
  315. int x, y;
  316. BlockModMode = pBlock->PackedData[1] & 1;
  317. ModulationBits = pBlock->PackedData[0];
  318. // If it's in an interpolated mode
  319. if (Do2bitMode && BlockModMode)
  320. {
  321. // Run through all the pixels in the block. Note we can now treat all the
  322. // "stored" values as if they have 2bits (even when they didn't!)
  323. for (y = 0; y < BLK_Y_SIZE; y++)
  324. {
  325. for (x = 0; x < BLK_X_2BPP; x++)
  326. {
  327. ModulationModes[y + StartY][x + StartX] = BlockModMode;
  328. // If this is a stored value...
  329. if (((x ^ y) & 1) == 0)
  330. {
  331. ModulationVals[y + StartY][x + StartX] = ModulationBits & 3;
  332. ModulationBits >>= 2;
  333. }
  334. }
  335. }
  336. }
  337. // Else if direct encoded 2bit mode - i.e. 1 mode bit per pixel
  338. else if (Do2bitMode)
  339. {
  340. for (y = 0; y < BLK_Y_SIZE; y++)
  341. {
  342. for (x = 0; x < BLK_X_2BPP; x++)
  343. {
  344. ModulationModes[y + StartY][x + StartX] = BlockModMode;
  345. // Double the bits so 0=> 00, and 1=>11
  346. if (ModulationBits & 1)
  347. {
  348. ModulationVals[y + StartY][x + StartX] = 0x3;
  349. }
  350. else
  351. {
  352. ModulationVals[y + StartY][x + StartX] = 0x0;
  353. }
  354. ModulationBits >>= 1;
  355. }
  356. }
  357. }
  358. // Else its the 4bpp mode so each value has 2 bits
  359. else
  360. {
  361. for (y = 0; y < BLK_Y_SIZE; y++)
  362. {
  363. for (x = 0; x < BLK_X_4BPP; x++)
  364. {
  365. ModulationModes[y + StartY][x + StartX] = BlockModMode;
  366. ModulationVals[y + StartY][x + StartX] = ModulationBits & 3;
  367. ModulationBits >>= 2;
  368. }
  369. }
  370. }
  371. }
  372. static void InterpolateColours(const int ColourP[4], const int ColourQ[4], const int ColourR[4], const int ColourS[4],
  373. const int Do2bitMode, const int x, const int y, int Result[4])
  374. {
  375. int u, v, uscale;
  376. int k;
  377. int tmp1, tmp2;
  378. int P[4], Q[4], R[4], S[4];
  379. // Copy the colours
  380. for (k = 0; k < 4; k++)
  381. {
  382. P[k] = ColourP[k];
  383. Q[k] = ColourQ[k];
  384. R[k] = ColourR[k];
  385. S[k] = ColourS[k];
  386. }
  387. // Put the x and y values into the right range
  388. v = (y & 0x3) | ((~y & 0x2) << 1);
  389. if (Do2bitMode)
  390. {
  391. u = (x & 0x7) | ((~x & 0x4) << 1);
  392. }
  393. else
  394. {
  395. u = (x & 0x3) | ((~x & 0x2) << 1);
  396. }
  397. // Get the u and v scale amounts
  398. v = v - BLK_Y_SIZE / 2;
  399. if (Do2bitMode)
  400. {
  401. u = u - BLK_X_2BPP / 2;
  402. uscale = 8;
  403. }
  404. else
  405. {
  406. u = u - BLK_X_4BPP / 2;
  407. uscale = 4;
  408. }
  409. for (k = 0; k < 4; k++)
  410. {
  411. tmp1 = P[k] * uscale + u * (Q[k] - P[k]);
  412. tmp2 = R[k] * uscale + u * (S[k] - R[k]);
  413. tmp1 = tmp1 * 4 + v * (tmp2 - tmp1);
  414. Result[k] = tmp1;
  415. }
  416. // Lop off the appropriate number of bits to get us to 8 bit precision
  417. if (Do2bitMode)
  418. {
  419. // Do RGB
  420. for (k = 0; k < 3; k++)
  421. {
  422. Result[k] >>= 2;
  423. }
  424. Result[3] >>= 1;
  425. }
  426. else
  427. {
  428. // Do RGB (A is ok)
  429. for (k = 0; k < 3; k++)
  430. {
  431. Result[k] >>= 1;
  432. }
  433. }
  434. // Convert from 5554 to 8888
  435. //
  436. // do RGB 5.3 => 8
  437. for (k = 0; k < 3; k++)
  438. {
  439. Result[k] += Result[k] >> 5;
  440. }
  441. Result[3] += Result[3] >> 4;
  442. }
  443. static void GetModulationValue(int x, int y, const int Do2bitMode, const int ModulationVals[8][16],
  444. const int ModulationModes[8][16], int* Mod, int* DoPT)
  445. {
  446. static const int RepVals0[4] = {0, 3, 5, 8};
  447. static const int RepVals1[4] = {0, 4, 4, 8};
  448. int ModVal;
  449. // Map X and Y into the local 2x2 block
  450. y = (y & 0x3) | ((~y & 0x2) << 1);
  451. if (Do2bitMode)
  452. {
  453. x = (x & 0x7) | ((~x & 0x4) << 1);
  454. }
  455. else
  456. {
  457. x = (x & 0x3) | ((~x & 0x2) << 1);
  458. }
  459. // Assume no PT for now
  460. *DoPT = 0;
  461. // Extract the modulation value. If a simple encoding
  462. if (ModulationModes[y][x] == 0)
  463. {
  464. ModVal = RepVals0[ModulationVals[y][x]];
  465. }
  466. else if (Do2bitMode)
  467. {
  468. // If this is a stored value
  469. if (((x ^ y) & 1) == 0)
  470. {
  471. ModVal = RepVals0[ModulationVals[y][x]];
  472. }
  473. // Else average from the neighbours
  474. //
  475. // If H&V interpolation...
  476. else if (ModulationModes[y][x] == 1)
  477. {
  478. ModVal = (RepVals0[ModulationVals[y - 1][x]] +
  479. RepVals0[ModulationVals[y + 1][x]] +
  480. RepVals0[ModulationVals[y][x - 1]] +
  481. RepVals0[ModulationVals[y][x + 1]] + 2) / 4;
  482. }
  483. // Else if H-Only
  484. else if (ModulationModes[y][x] == 2)
  485. {
  486. ModVal = (RepVals0[ModulationVals[y][x - 1]] +
  487. RepVals0[ModulationVals[y][x + 1]] + 1) / 2;
  488. }
  489. // Else it's V-Only
  490. else
  491. {
  492. ModVal = (RepVals0[ModulationVals[y - 1][x]] +
  493. RepVals0[ModulationVals[y + 1][x]] + 1) / 2;
  494. }
  495. }
  496. // Else it's 4BPP and PT encoding
  497. else
  498. {
  499. ModVal = RepVals1[ModulationVals[y][x]];
  500. *DoPT = ModulationVals[y][x] == PT_INDEX;
  501. }
  502. *Mod = ModVal;
  503. }
  504. static unsigned TwiddleUV(unsigned YSize, unsigned XSize, unsigned YPos, unsigned XPos)
  505. {
  506. unsigned Twiddled;
  507. unsigned MinDimension;
  508. unsigned MaxValue;
  509. unsigned SrcBitPos;
  510. unsigned DstBitPos;
  511. int ShiftCount;
  512. if (YSize < XSize)
  513. {
  514. MinDimension = YSize;
  515. MaxValue = XPos;
  516. }
  517. else
  518. {
  519. MinDimension = XSize;
  520. MaxValue = YPos;
  521. }
  522. // Step through all the bits in the "minimum" dimension
  523. SrcBitPos = 1;
  524. DstBitPos = 1;
  525. Twiddled = 0;
  526. ShiftCount = 0;
  527. while (SrcBitPos < MinDimension)
  528. {
  529. if (YPos & SrcBitPos)
  530. {
  531. Twiddled |= DstBitPos;
  532. }
  533. if (XPos & SrcBitPos)
  534. {
  535. Twiddled |= (DstBitPos << 1);
  536. }
  537. SrcBitPos <<= 1;
  538. DstBitPos <<= 2;
  539. ShiftCount += 1;
  540. }
  541. // Prepend any unused bits
  542. MaxValue >>= ShiftCount;
  543. Twiddled |= (MaxValue << (2 * ShiftCount));
  544. return Twiddled;
  545. }
  546. void DecompressImagePVRTC(unsigned char* rgba, const void* blocks, int width, int height, CompressedFormat format)
  547. {
  548. auto* pCompressedData = (AMTC_BLOCK_STRUCT*)blocks;
  549. int AssumeImageTiles = 1;
  550. int Do2bitMode = format == CF_PVRTC_RGB_2BPP || format == CF_PVRTC_RGBA_2BPP;
  551. int x, y;
  552. int i, j;
  553. int BlkX, BlkY;
  554. int BlkXp1, BlkYp1;
  555. int XBlockSize;
  556. int BlkXDim, BlkYDim;
  557. int StartX, StartY;
  558. int ModulationVals[8][16];
  559. int ModulationModes[8][16];
  560. int Mod, DoPT;
  561. unsigned uPosition;
  562. // Local neighbourhood of blocks
  563. AMTC_BLOCK_STRUCT* pBlocks[2][2];
  564. AMTC_BLOCK_STRUCT* pPrevious[2][2] = {{nullptr, nullptr},
  565. {nullptr, nullptr}};
  566. // Low precision colours extracted from the blocks
  567. struct
  568. {
  569. int Reps[2][4];
  570. } Colours5554[2][2];
  571. // Interpolated A and B colours for the pixel
  572. int ASig[4], BSig[4];
  573. int Result[4];
  574. if (Do2bitMode)
  575. {
  576. XBlockSize = BLK_X_2BPP;
  577. }
  578. else
  579. {
  580. XBlockSize = BLK_X_4BPP;
  581. }
  582. // For MBX don't allow the sizes to get too small
  583. BlkXDim = _MAX(2, width / XBlockSize);
  584. BlkYDim = _MAX(2, height / BLK_Y_SIZE);
  585. // Step through the pixels of the image decompressing each one in turn
  586. //
  587. // Note that this is a hideously inefficient way to do this!
  588. for (y = 0; y < height; y++)
  589. {
  590. for (x = 0; x < width; x++)
  591. {
  592. // Map this pixel to the top left neighbourhood of blocks
  593. BlkX = (x - XBlockSize / 2);
  594. BlkY = (y - BLK_Y_SIZE / 2);
  595. BlkX = LIMIT_COORD(BlkX, width, AssumeImageTiles);
  596. BlkY = LIMIT_COORD(BlkY, height, AssumeImageTiles);
  597. BlkX /= XBlockSize;
  598. BlkY /= BLK_Y_SIZE;
  599. // Compute the positions of the other 3 blocks
  600. BlkXp1 = LIMIT_COORD(BlkX + 1, BlkXDim, AssumeImageTiles);
  601. BlkYp1 = LIMIT_COORD(BlkY + 1, BlkYDim, AssumeImageTiles);
  602. // Map to block memory locations
  603. pBlocks[0][0] = pCompressedData + TwiddleUV((unsigned)BlkYDim, (unsigned)BlkXDim, (unsigned)BlkY, (unsigned)BlkX);
  604. pBlocks[0][1] = pCompressedData + TwiddleUV((unsigned)BlkYDim, (unsigned)BlkXDim, (unsigned)BlkY, (unsigned)BlkXp1);
  605. pBlocks[1][0] = pCompressedData + TwiddleUV((unsigned)BlkYDim, (unsigned)BlkXDim, (unsigned)BlkYp1, (unsigned)BlkX);
  606. pBlocks[1][1] = pCompressedData + TwiddleUV((unsigned)BlkYDim, (unsigned)BlkXDim, (unsigned)BlkYp1, (unsigned)BlkXp1);
  607. // Extract the colours and the modulation information IF the previous values
  608. // have changed.
  609. if (memcmp(pPrevious, pBlocks, 4 * sizeof(void*)) != 0)
  610. {
  611. StartY = 0;
  612. for (i = 0; i < 2; i++)
  613. {
  614. StartX = 0;
  615. for (j = 0; j < 2; j++)
  616. {
  617. Unpack5554Colour(pBlocks[i][j], Colours5554[i][j].Reps);
  618. UnpackModulations(pBlocks[i][j],
  619. Do2bitMode,
  620. ModulationVals,
  621. ModulationModes,
  622. StartX, StartY);
  623. StartX += XBlockSize;
  624. }
  625. StartY += BLK_Y_SIZE;
  626. }
  627. // Make a copy of the new pointers
  628. memcpy(pPrevious, pBlocks, 4 * sizeof(void*));
  629. }
  630. // Decompress the pixel. First compute the interpolated A and B signals
  631. InterpolateColours(Colours5554[0][0].Reps[0],
  632. Colours5554[0][1].Reps[0],
  633. Colours5554[1][0].Reps[0],
  634. Colours5554[1][1].Reps[0],
  635. Do2bitMode, x, y,
  636. ASig);
  637. InterpolateColours(Colours5554[0][0].Reps[1],
  638. Colours5554[0][1].Reps[1],
  639. Colours5554[1][0].Reps[1],
  640. Colours5554[1][1].Reps[1],
  641. Do2bitMode, x, y,
  642. BSig);
  643. GetModulationValue(x, y, Do2bitMode, (const int (*)[16])ModulationVals, (const int (*)[16])ModulationModes,
  644. &Mod, &DoPT);
  645. // Compute the modulated colour
  646. for (i = 0; i < 4; i++)
  647. {
  648. Result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]);
  649. Result[i] >>= 3;
  650. }
  651. if (DoPT)
  652. {
  653. Result[3] = 0;
  654. }
  655. // Store the result in the output image
  656. uPosition = (unsigned)((x + y * width) << 2);
  657. rgba[uPosition + 0] = (unsigned char)Result[0];
  658. rgba[uPosition + 1] = (unsigned char)Result[1];
  659. rgba[uPosition + 2] = (unsigned char)Result[2];
  660. rgba[uPosition + 3] = (unsigned char)Result[3];
  661. }
  662. }
  663. }
  664. void FlipBlockVertical(unsigned char* dest, const unsigned char* src, CompressedFormat format)
  665. {
  666. switch (format)
  667. {
  668. case CF_RGBA:
  669. for (unsigned i = 0; i < 4; ++i)
  670. dest[i] = src[i];
  671. break;
  672. case CF_DXT1:
  673. for (unsigned i = 0; i < 4; ++i)
  674. {
  675. dest[i] = src[i];
  676. dest[i + 4] = src[7 - i];
  677. }
  678. break;
  679. case CF_DXT3:
  680. for (unsigned i = 0; i < 8; i += 2)
  681. {
  682. dest[i] = src[6 - i];
  683. dest[i + 1] = src[6 - i + 1];
  684. }
  685. for (unsigned i = 0; i < 4; ++i)
  686. {
  687. dest[i + 8] = src[i + 8];
  688. dest[i + 12] = src[15 - i];
  689. }
  690. break;
  691. case CF_DXT5:
  692. dest[0] = src[0];
  693. dest[1] = src[1];
  694. {
  695. unsigned a1 = src[2] | ((unsigned)src[3] << 8) | ((unsigned)src[4] << 16);
  696. unsigned a2 = src[5] | ((unsigned)src[6] << 8) | ((unsigned)src[7] << 16);
  697. unsigned b1 = ((a1 & 0x000fff) << 12) | (a1 & 0xfff000) >> 12;
  698. unsigned b2 = ((a2 & 0x000fff) << 12) | (a2 & 0xfff000) >> 12;
  699. dest[2] = (unsigned char)(b2 & 0xff);
  700. dest[3] = (unsigned char)((b2 >> 8) & 0xff);
  701. dest[4] = (unsigned char)((b2 >> 16) & 0xff);
  702. dest[5] = (unsigned char)(b1 & 0xff);
  703. dest[6] = (unsigned char)((b1 >> 8) & 0xff);
  704. dest[7] = (unsigned char)((b1 >> 16) & 0xff);
  705. }
  706. for (unsigned i = 0; i < 4; ++i)
  707. {
  708. dest[i + 8] = src[i + 8];
  709. dest[i + 12] = src[15 - i];
  710. }
  711. break;
  712. default:
  713. // ETC1 & PVRTC not yet implemented
  714. break;
  715. }
  716. }
  717. static unsigned char FlipDXT1Horizontal(unsigned char src)
  718. {
  719. return (unsigned char)(((src & 0x3) << 6) | ((src & 0xc) << 2) | ((src & 0x30) >> 2) | ((src & 0xc0) >> 6));
  720. }
  721. static unsigned FlipDXT5AlphaHorizontal(unsigned src)
  722. {
  723. // Works on 2 lines at a time
  724. return ((src & 0x7) << 9) | ((src & 0x38) << 3) | ((src & 0x1c0) >> 3) | ((src & 0xe00) >> 9) |
  725. ((src & 0x7000) << 9) | ((src & 0x38000) << 3) | ((src & 0x1c0000) >> 3) | ((src & 0xe00000) >> 9);
  726. }
  727. void FlipBlockHorizontal(unsigned char* dest, const unsigned char* src, CompressedFormat format)
  728. {
  729. switch (format)
  730. {
  731. case CF_DXT1:
  732. for (unsigned i = 0; i < 4; ++i)
  733. {
  734. dest[i] = src[i];
  735. dest[i + 4] = FlipDXT1Horizontal(src[i + 4]);
  736. }
  737. break;
  738. case CF_DXT3:
  739. for (unsigned i = 0; i < 8; i += 2)
  740. {
  741. dest[i] = (unsigned char)(((src[i + 1] & 0xf0) >> 4) | ((src[i + 1] & 0xf) << 4));
  742. dest[i + 1] = (unsigned char)(((src[i] & 0xf0) >> 4) | ((src[i] & 0xf) << 4));
  743. }
  744. for (unsigned i = 0; i < 4; ++i)
  745. {
  746. dest[i + 8] = src[i + 8];
  747. dest[i + 12] = FlipDXT1Horizontal(src[i + 12]);
  748. }
  749. break;
  750. case CF_DXT5:
  751. dest[0] = src[0];
  752. dest[1] = src[1];
  753. {
  754. unsigned a1 = src[2] | ((unsigned)src[3] << 8) | ((unsigned)src[4] << 16);
  755. unsigned a2 = src[5] | ((unsigned)src[6] << 8) | ((unsigned)src[7] << 16);
  756. unsigned b1 = FlipDXT5AlphaHorizontal(a1);
  757. unsigned b2 = FlipDXT5AlphaHorizontal(a2);
  758. dest[2] = (unsigned char)(b1 & 0xff);
  759. dest[3] = (unsigned char)((b1 >> 8) & 0xff);
  760. dest[4] = (unsigned char)((b1 >> 16) & 0xff);
  761. dest[5] = (unsigned char)(b2 & 0xff);
  762. dest[6] = (unsigned char)((b2 >> 8) & 0xff);
  763. dest[7] = (unsigned char)((b2 >> 16) & 0xff);
  764. }
  765. for (unsigned i = 0; i < 4; ++i)
  766. {
  767. dest[i + 8] = src[i + 8];
  768. dest[i + 12] = FlipDXT1Horizontal(src[i + 12]);
  769. }
  770. break;
  771. default:
  772. // ETC1 & PVRTC not yet implemented
  773. break;
  774. }
  775. }
  776. static void ReadBigEndian4byteWord(uint32_t* pBlock, const unsigned char *s)
  777. {
  778. *pBlock = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
  779. }
  780. // Use ETCPACK to decompress ETC texture.
  781. void DecompressImageETC(unsigned char* dstImage, const void* blocks, int width, int height, bool hasAlpha)
  782. {
  783. // ETCPACK initialization.
  784. static const bool placeholder = []() { setupAlphaTable(); return true; }();
  785. const int channelCount = hasAlpha ? 4 : 3;
  786. unsigned char* src = (unsigned char*)blocks;
  787. unsigned int blockPart1, blockPart2;
  788. // ETCPACK write 4x4 blocks, so it needs padding.
  789. int w4 = ((width + 3) / 4);
  790. int h4 = ((height + 3) / 4);
  791. unsigned char buffer4x4[4 * 4 * 4];
  792. for (int y = 0; y < h4; ++y)
  793. {
  794. for (int x = 0; x < w4; ++x)
  795. {
  796. memset(&buffer4x4[0], 0xFF, 4 * 4 * 4);
  797. if (hasAlpha)
  798. {
  799. decompressBlockAlphaC(src, &buffer4x4[3], 4, 4, 0, 0, channelCount);
  800. src += 8;
  801. }
  802. ReadBigEndian4byteWord(&blockPart1, src);
  803. src += 4;
  804. ReadBigEndian4byteWord(&blockPart2, src);
  805. src += 4;
  806. decompressBlockETC2c(blockPart1, blockPart2, &buffer4x4[0], 4, 4, 0, 0, 4);
  807. int wbuf = Min(width - x * 4, 4);
  808. int hbuf = Min(height - y * 4, 4);
  809. for(int dy = 0; dy < hbuf; ++dy)
  810. {
  811. for (int dx = 0; dx < wbuf; ++dx)
  812. {
  813. int idst = ((y * 4 + dy) * width + x * 4 + dx) * 4;
  814. int ibuf = (dy * 4 + dx) * 4;
  815. dstImage[idst] = buffer4x4[ibuf];
  816. dstImage[idst + 1] = buffer4x4[ibuf + 1];
  817. dstImage[idst + 2] = buffer4x4[ibuf + 2];
  818. dstImage[idst + 3] = buffer4x4[ibuf + 3];
  819. }
  820. }
  821. }
  822. }
  823. }
  824. }