Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. //! Use DXT1 compression.
  2. var kDxt1 = 1 << 0
  3. //! Use DXT3 compression.
  4. var kDxt3 = 1 << 1
  5. //! Use DXT5 compression.
  6. var kDxt5 = 1 << 2
  7. //! Use a very slow but very high quality colour compressor.
  8. var kColourIterativeClusterFit = 1 << 8
  9. //! Use a slow but high quality colour compressor (the default).
  10. var kColourClusterFit = 1 << 3
  11. //! Use a fast but low quality colour compressor.
  12. var kColourRangeFit = 1 << 4
  13. //! Weight the colour by alpha during cluster fit (disabled by default).
  14. var kWeightColourByAlpha = 1 << 7
  15. var krgb565 = 1 << 5
  16. function Unpack565(packed0, packed1, colour, offset) {
  17. var value = packed0 | (packed1 << 8)
  18. var red = (value >> 11) & 0x1f
  19. var green = (value >> 5) & 0x3f
  20. var blue = value & 0x1f
  21. colour[offset + 0] = (red << 3) | (red >> 2)
  22. colour[offset + 1] = (green << 2) | (green >> 4)
  23. colour[offset + 2] = (blue << 3) | (blue >> 2)
  24. colour[offset + 3] = 255
  25. return value
  26. }
  27. function DecompressColour(rgba, block, nOffset, isDxt1) {
  28. var codes = new Uint8Array(16)
  29. var a = Unpack565(block[nOffset + 0], block[nOffset + 1], codes, 0)
  30. var b = Unpack565(block[nOffset + 2], block[nOffset + 3], codes, 4)
  31. for (var i = 0; i < 3; i++) {
  32. var c = codes[i]
  33. var d = codes[4 + i]
  34. if (isDxt1 && a <= b) {
  35. codes[8 + i] = (c + d) / 2
  36. codes[12 + i] = 0
  37. } else {
  38. codes[8 + i] = (2 * c + d) / 3
  39. codes[12 + i] = (c + 2 * d) / 3
  40. }
  41. }
  42. codes[8 + 3] = 255
  43. codes[12 + 3] = isDxt1 && a <= b ? 0 : 255
  44. var indices = new Uint8Array(16)
  45. for (var i = 0; i < 4; ++i) {
  46. var packed = block[nOffset + 4 + i]
  47. indices[4 * i + 0] = packed & 0x3
  48. indices[4 * i + 1] = (packed >> 2) & 0x3
  49. indices[4 * i + 2] = (packed >> 4) & 0x3
  50. indices[4 * i + 3] = (packed >> 6) & 0x3
  51. }
  52. for (var i = 0; i < 16; ++i) {
  53. var offset = 4 * indices[i]
  54. for (var j = 0; j < 4; ++j) rgba[4 * i + j] = codes[offset + j]
  55. }
  56. }
  57. function DecompressAlphaDxt3(rgba, block, nOffset) {
  58. // unpack the alpha values pairwise
  59. for (var i = 0; i < 8; ++i) {
  60. // quantise down to 4 bits
  61. var quant = bytes[nOffset + i]
  62. // unpack the values
  63. var lo = quant & 0x0f
  64. var hi = quant & 0xf0
  65. // convert back up to bytes
  66. rgba[8 * i + 3] = lo | (lo << 4)
  67. rgba[8 * i + 7] = hi | (hi >> 4)
  68. }
  69. }
  70. function DecompressAlphaDxt5(rgba, block, nOffset) {
  71. var alpha0 = block[nOffset + 0]
  72. var alpha1 = block[nOffset + 1]
  73. var codes = new Uint8Array(8)
  74. codes[0] = alpha0
  75. codes[1] = alpha1
  76. if (alpha0 <= alpha1) {
  77. // use 5-alpha codebook
  78. for (var i = 1; i < 5; ++i)
  79. codes[1 + i] = ((5 - i) * alpha0 + i * alpha1) / 5
  80. codes[6] = 0
  81. codes[7] = 255
  82. } else {
  83. // use 7-alpha codebook
  84. for (var i = 1; i < 7; ++i)
  85. codes[1 + i] = ((7 - i) * alpha0 + i * alpha1) / 7
  86. }
  87. var indices = new Uint8Array(16)
  88. var nOffset = nOffset + 2
  89. var nBegin = 0
  90. for (var i = 0; i < 2; ++i) {
  91. // grab 3 bytes
  92. var value = 0
  93. for (var j = 0; j < 3; ++j) {
  94. var byte = block[nOffset++]
  95. value |= byte << (8 * j)
  96. }
  97. // unpack 8 3-bit values from it
  98. for (var j = 0; j < 8; ++j) {
  99. var index = (value >> (3 * j)) & 0x7
  100. indices[nBegin++] = index
  101. }
  102. }
  103. for (var i = 0; i < 16; ++i) rgba[4 * i + 3] = codes[indices[i]]
  104. }
  105. function Decompress(rgba, block, nOffset, flags) {
  106. var nOffset2 = 0
  107. if ((flags & (kDxt3 | kDxt5)) != 0) nOffset2 = 8
  108. DecompressColour(rgba, block, nOffset + nOffset2, (flags & kDxt1) != 0)
  109. if ((flags & kDxt3) != 0) {
  110. DecompressAlphaDxt3(rgba, block, nOffset)
  111. } else if ((flags & kDxt5) != 0) {
  112. DecompressAlphaDxt5(rgba, block, nOffset)
  113. }
  114. }
  115. function DecompressImage565(rgb565, width, height, blocks) {
  116. var c = new Uint16Array(4)
  117. var dst = rgb565
  118. var m = 0
  119. var dstI = 0
  120. var i = 0
  121. var r0 = 0,
  122. g0 = 0,
  123. b0 = 0,
  124. r1 = 0,
  125. g1 = 0,
  126. b1 = 0
  127. var blockWidth = width / 4
  128. var blockHeight = height / 4
  129. for (var blockY = 0; blockY < blockHeight; blockY++) {
  130. for (var blockX = 0; blockX < blockWidth; blockX++) {
  131. i = 4 * ((blockHeight - blockY) * blockWidth + blockX)
  132. c[0] = blocks[i]
  133. c[1] = blocks[i + 1]
  134. r0 = c[0] & 0x1f
  135. g0 = c[0] & 0x7e0
  136. b0 = c[0] & 0xf800
  137. r1 = c[1] & 0x1f
  138. g1 = c[1] & 0x7e0
  139. b1 = c[1] & 0xf800
  140. // Interpolate between c0 and c1 to get c2 and c3. ~
  141. // Note that we approximate 1/3 as 3/8 and 2/3 as 5/8 for
  142. // speed. This also appears to be what the hardware DXT
  143. // decoder in many GPUs does :)
  144. c[2] =
  145. ((5 * r0 + 3 * r1) >> 3) |
  146. (((5 * g0 + 3 * g1) >> 3) & 0x7e0) |
  147. (((5 * b0 + 3 * b1) >> 3) & 0xf800)
  148. c[3] =
  149. ((5 * r1 + 3 * r0) >> 3) |
  150. (((5 * g1 + 3 * g0) >> 3) & 0x7e0) |
  151. (((5 * b1 + 3 * b0) >> 3) & 0xf800)
  152. m = blocks[i + 2]
  153. dstI = blockY * 4 * width + blockX * 4
  154. dst[dstI] = c[m & 0x3]
  155. dst[dstI + 1] = c[(m >> 2) & 0x3]
  156. dst[dstI + 2] = c[(m >> 4) & 0x3]
  157. dst[dstI + 3] = c[(m >> 6) & 0x3]
  158. dstI += width
  159. dst[dstI] = c[(m >> 8) & 0x3]
  160. dst[dstI + 1] = c[(m >> 10) & 0x3]
  161. dst[dstI + 2] = c[(m >> 12) & 0x3]
  162. dst[dstI + 3] = c[m >> 14]
  163. m = blocks[i + 3]
  164. dstI += width
  165. dst[dstI] = c[m & 0x3]
  166. dst[dstI + 1] = c[(m >> 2) & 0x3]
  167. dst[dstI + 2] = c[(m >> 4) & 0x3]
  168. dst[dstI + 3] = c[(m >> 6) & 0x3]
  169. dstI += width
  170. dst[dstI] = c[(m >> 8) & 0x3]
  171. dst[dstI + 1] = c[(m >> 10) & 0x3]
  172. dst[dstI + 2] = c[(m >> 12) & 0x3]
  173. dst[dstI + 3] = c[m >> 14]
  174. }
  175. }
  176. return dst
  177. }
  178. /*! @brief Decompresses an image in memory.
  179. @param rgba Storage for the decompressed pixels.
  180. @param width The width of the source image.
  181. @param height The height of the source image.
  182. @param blocks The compressed DXT blocks.
  183. @param flags Compression flags.
  184. The decompressed pixels will be written as a contiguous array of width*height
  185. 16 rgba values, with each component as 1 byte each. In memory this is:
  186. { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height
  187. The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
  188. however, DXT1 will be used by default if none is specified. All other flags
  189. are ignored.
  190. Internally this function calls squish::Decompress for each block.
  191. */
  192. function DecompressImage(rgba, width, height, blocks, flags) {
  193. var bytesPerBlock = (flags & kDxt1) != 0 ? 8 : 16
  194. var nOffset = 0
  195. for (var y = 0; y < height; y += 4) {
  196. for (var x = 0; x < width; x += 4) {
  197. var targetRgba = new Uint8Array(4 * 16)
  198. Decompress(targetRgba, blocks, nOffset, flags)
  199. var nOffsetTarget = 0
  200. for (var py = 0; py < 4; ++py) {
  201. for (var px = 0; px < 4; ++px) {
  202. var sx = x + px
  203. var sy = y + py
  204. if (sx < width && sy < height) {
  205. // flip Y
  206. var nBegin = 4 * (width * (height - sy) + sx)
  207. for (var i = 0; i < 4; ++i) {
  208. rgba[nBegin++] = targetRgba[nOffsetTarget++]
  209. }
  210. } else {
  211. nOffsetTarget += 4
  212. }
  213. }
  214. }
  215. // advance
  216. nOffset += bytesPerBlock
  217. }
  218. }
  219. }
  220. function DXTTextureDecode(options) {}
  221. DXTTextureDecode.decode = function(out, width, height, block, format) {
  222. if (out == null || block == null || height == 0 || width == 0) {
  223. return
  224. }
  225. var flags = 0
  226. //有alpha通道,转为RGBA,否则转为rgb565
  227. // S3MPixelFormat.BGR -> 11
  228. //S3MPixelFormat.LUMINANCE_ALPHA -> 5
  229. if (format > 11 || format === 5) {
  230. flags = kDxt5
  231. } else {
  232. flags = kDxt1 | krgb565
  233. }
  234. if (flags & kDxt1 && flags & krgb565) {
  235. DecompressImage565(out, width, height, block)
  236. } else {
  237. DecompressImage(out, width, height, block, flags)
  238. }
  239. }
  240. export default DXTTextureDecode