stb_dxt.h 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. // stb_dxt.h - Real-Time DXT1/DXT5 compressor
  2. // Based on original by fabian "ryg" giesen v1.04
  3. // Custom version, modified by Yann Collet
  4. //
  5. /*
  6. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
  7. Redistribution and use in source and binary forms, with or without
  8. modification, are permitted provided that the following conditions are
  9. met:
  10. * Redistributions of source code must retain the above copyright
  11. notice, this list of conditions and the following disclaimer.
  12. * Redistributions in binary form must reproduce the above
  13. copyright notice, this list of conditions and the following disclaimer
  14. in the documentation and/or other materials provided with the
  15. distribution.
  16. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. You can contact the author at :
  28. - RygsDXTc source repository : http://code.google.com/p/rygsdxtc/
  29. */
  30. // use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation
  31. //
  32. // USAGE:
  33. // call stb_compress_dxt_block() for every block (you must pad)
  34. // source should be a 4x4 block of RGBA data in row-major order;
  35. // A is ignored if you specify alpha=0; you can turn on dithering
  36. // and "high quality" using mode.
  37. //
  38. // version history:
  39. // v1.06 - (cyan) implement Fabian Giesen's comments
  40. // v1.05 - (cyan) speed optimizations
  41. // v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec);
  42. // single color match fix (allow for inexact color interpolation);
  43. // optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps.
  44. // v1.03 - (stb) endianness support
  45. // v1.02 - (stb) fix alpha encoding bug
  46. // v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom
  47. // v1.00 - (stb) first release
  48. #ifndef STB_INCLUDE_STB_DXT_H
  49. #define STB_INCLUDE_STB_DXT_H
  50. //*******************************************************************
  51. // Enable custom Optimisations
  52. // Comment this define if you want to revert to ryg's original code
  53. #define NEW_OPTIMISATIONS
  54. //*******************************************************************
  55. // compression mode (bitflags)
  56. #define STB_DXT_NORMAL 0
  57. #define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like!
  58. #define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower.
  59. void rygCompress(unsigned char *dst, unsigned char *src, int w, int h, int isDxt5);
  60. // TODO remove these, not working properly..
  61. void rygCompressYCoCg(unsigned char *dst, unsigned char *src, int w, int h);
  62. void linearize(unsigned char * dst, const unsigned char * src, int n);
  63. void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode);
  64. #define STB_COMPRESS_DXT_BLOCK
  65. #ifdef STB_DXT_IMPLEMENTATION
  66. // configuration options for DXT encoder. set them in the project/makefile or just define
  67. // them at the top.
  68. // STB_DXT_USE_ROUNDING_BIAS
  69. // use a rounding bias during color interpolation. this is closer to what "ideal"
  70. // interpolation would do but doesn't match the S3TC/DX10 spec. old versions (pre-1.03)
  71. // implicitly had this turned on.
  72. //
  73. // in case you're targeting a specific type of hardware (e.g. console programmers):
  74. // NVidia and Intel GPUs (as of 2010) as well as DX9 ref use DXT decoders that are closer
  75. // to STB_DXT_USE_ROUNDING_BIAS. AMD/ATI, S3 and DX10 ref are closer to rounding with no bias.
  76. // you also see "(a*5 + b*3) / 8" on some old GPU designs.
  77. // #define STB_DXT_USE_ROUNDING_BIAS
  78. #include <stdlib.h>
  79. #include <math.h>
  80. #include <stddef.h>
  81. #include <string.h> // memset
  82. #include <assert.h>
  83. #include <iostream>
  84. #include <algorithm>
  85. static unsigned char stb__Expand5[32];
  86. static unsigned char stb__Expand6[64];
  87. static unsigned char stb__OMatch5[256][2];
  88. static unsigned char stb__OMatch6[256][2];
  89. static unsigned char stb__QuantRBTab[256+16];
  90. static unsigned char stb__QuantGTab[256+16];
  91. static int stb__Mul8Bit(int a, int b)
  92. {
  93. int t = a*b + 128;
  94. return (t + (t >> 8)) >> 8;
  95. }
  96. static void stb__From16Bit(unsigned char *out, unsigned short v)
  97. {
  98. int rv = (v & 0xf800) >> 11;
  99. int gv = (v & 0x07e0) >> 5;
  100. int bv = (v & 0x001f) >> 0;
  101. out[0] = stb__Expand5[rv];
  102. out[1] = stb__Expand6[gv];
  103. out[2] = stb__Expand5[bv];
  104. out[3] = 0;
  105. }
  106. static unsigned short stb__As16Bit(int r, int g, int b)
  107. {
  108. return (stb__Mul8Bit(r,31) << 11) + (stb__Mul8Bit(g,63) << 5) + stb__Mul8Bit(b,31);
  109. }
  110. // linear interpolation at 1/3 point between a and b, using desired rounding type
  111. static int stb__Lerp13(int a, int b)
  112. {
  113. #ifdef STB_DXT_USE_ROUNDING_BIAS
  114. // with rounding bias
  115. return a + stb__Mul8Bit(b-a, 0x55);
  116. #else
  117. // without rounding bias
  118. // replace "/ 3" by "* 0xaaab) >> 17" if your compiler sucks or you really need every ounce of speed.
  119. return (2*a + b) / 3;
  120. #endif
  121. }
  122. // lerp RGB color
  123. static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char *p2)
  124. {
  125. out[0] = stb__Lerp13(p1[0], p2[0]);
  126. out[1] = stb__Lerp13(p1[1], p2[1]);
  127. out[2] = stb__Lerp13(p1[2], p2[2]);
  128. }
  129. /****************************************************************************/
  130. // compute table to reproduce constant colors as accurately as possible
  131. static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size)
  132. {
  133. int i,mn,mx;
  134. for (i=0;i<256;i++) {
  135. int bestErr = 256;
  136. for (mn=0;mn<size;mn++) {
  137. for (mx=0;mx<size;mx++) {
  138. int mine = expand[mn];
  139. int maxe = expand[mx];
  140. int err = abs(stb__Lerp13(maxe, mine) - i);
  141. // DX10 spec says that interpolation must be within 3% of "correct" result,
  142. // add this as error term. (normally we'd expect a random distribution of
  143. // +-1.5% error, but nowhere in the spec does it say that the error has to be
  144. // unbiased - better safe than sorry).
  145. err += abs(maxe - mine) * 3 / 100;
  146. if(err < bestErr)
  147. {
  148. Table[i*2+0] = mx;
  149. Table[i*2+1] = mn;
  150. bestErr = err;
  151. }
  152. }
  153. }
  154. }
  155. }
  156. static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1)
  157. {
  158. stb__From16Bit(color+ 0, c0);
  159. stb__From16Bit(color+ 4, c1);
  160. stb__Lerp13RGB(color+ 8, color+0, color+4);
  161. stb__Lerp13RGB(color+12, color+4, color+0);
  162. }
  163. // Block dithering function. Simply dithers a block to 565 RGB.
  164. // (Floyd-Steinberg)
  165. static void stb__DitherBlock(unsigned char *dest, unsigned char *block)
  166. {
  167. int err[8],*ep1 = err,*ep2 = err+4, *et;
  168. int ch,y;
  169. // process channels seperately
  170. for (ch=0; ch<3; ++ch) {
  171. unsigned char *bp = block+ch, *dp = dest+ch;
  172. unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8;
  173. memset(err, 0, sizeof(err));
  174. for(y=0; y<4; ++y) {
  175. dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
  176. ep1[0] = bp[ 0] - dp[ 0];
  177. dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)];
  178. ep1[1] = bp[ 4] - dp[ 4];
  179. dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)];
  180. ep1[2] = bp[ 8] - dp[ 8];
  181. dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)];
  182. ep1[3] = bp[12] - dp[12];
  183. bp += 16;
  184. dp += 16;
  185. et = ep1, ep1 = ep2, ep2 = et; // swap
  186. }
  187. }
  188. }
  189. // The color matching function
  190. static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color,int dither)
  191. {
  192. unsigned int mask = 0;
  193. int dirr = color[0*4+0] - color[1*4+0];
  194. int dirg = color[0*4+1] - color[1*4+1];
  195. int dirb = color[0*4+2] - color[1*4+2];
  196. int dots[16];
  197. int stops[4];
  198. int i;
  199. int c0Point, halfPoint, c3Point;
  200. for(i=0;i<16;i++)
  201. dots[i] = block[i*4+0]*dirr + block[i*4+1]*dirg + block[i*4+2]*dirb;
  202. for(i=0;i<4;i++)
  203. stops[i] = color[i*4+0]*dirr + color[i*4+1]*dirg + color[i*4+2]*dirb;
  204. // think of the colors as arranged on a line; project point onto that line, then choose
  205. // next color out of available ones. we compute the crossover points for "best color in top
  206. // half"/"best in bottom half" and then the same inside that subinterval.
  207. //
  208. // relying on this 1d approximation isn't always optimal in terms of euclidean distance,
  209. // but it's very close and a lot faster.
  210. // http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html
  211. c0Point = (stops[1] + stops[3]) >> 1;
  212. halfPoint = (stops[3] + stops[2]) >> 1;
  213. c3Point = (stops[2] + stops[0]) >> 1;
  214. if(!dither)
  215. {
  216. // the version without dithering is straightforward
  217. #ifdef NEW_OPTIMISATIONS
  218. const int indexMap[8] = { 0 << 30,2 << 30,0 << 30,2 << 30,3 << 30,3 << 30,1 << 30,1 << 30 };
  219. for(int i=0;i<16;i++)
  220. {
  221. int dot = dots[i];
  222. mask >>= 2;
  223. int bits =((dot < halfPoint) ? 4 : 0)
  224. | ((dot < c0Point) ? 2 : 0)
  225. | ((dot < c3Point) ? 1 : 0);
  226. mask |= indexMap[bits];
  227. }
  228. #else
  229. for (i=15;i>=0;i--) {
  230. int dot = dots[i];
  231. mask <<= 2;
  232. if(dot < halfPoint)
  233. mask |= (dot < c0Point) ? 1 : 3;
  234. else
  235. mask |= (dot < c3Point) ? 2 : 0;
  236. }
  237. #endif
  238. } else {
  239. // with floyd-steinberg dithering
  240. int err[8],*ep1 = err,*ep2 = err+4;
  241. int *dp = dots, y;
  242. c0Point <<= 4;
  243. halfPoint <<= 4;
  244. c3Point <<= 4;
  245. for(i=0;i<8;i++)
  246. err[i] = 0;
  247. for(y=0;y<4;y++)
  248. {
  249. int dot,lmask,step;
  250. dot = (dp[0] << 4) + (3*ep2[1] + 5*ep2[0]);
  251. if(dot < halfPoint)
  252. step = (dot < c0Point) ? 1 : 3;
  253. else
  254. step = (dot < c3Point) ? 2 : 0;
  255. ep1[0] = dp[0] - stops[step];
  256. lmask = step;
  257. dot = (dp[1] << 4) + (7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]);
  258. if(dot < halfPoint)
  259. step = (dot < c0Point) ? 1 : 3;
  260. else
  261. step = (dot < c3Point) ? 2 : 0;
  262. ep1[1] = dp[1] - stops[step];
  263. lmask |= step<<2;
  264. dot = (dp[2] << 4) + (7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]);
  265. if(dot < halfPoint)
  266. step = (dot < c0Point) ? 1 : 3;
  267. else
  268. step = (dot < c3Point) ? 2 : 0;
  269. ep1[2] = dp[2] - stops[step];
  270. lmask |= step<<4;
  271. dot = (dp[3] << 4) + (7*ep1[2] + 5*ep2[3] + ep2[2]);
  272. if(dot < halfPoint)
  273. step = (dot < c0Point) ? 1 : 3;
  274. else
  275. step = (dot < c3Point) ? 2 : 0;
  276. ep1[3] = dp[3] - stops[step];
  277. lmask |= step<<6;
  278. dp += 4;
  279. mask |= lmask << (y*8);
  280. { int *et = ep1; ep1 = ep2; ep2 = et; } // swap
  281. }
  282. }
  283. return mask;
  284. }
  285. // The color optimization function. (Clever code, part 1)
  286. static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16)
  287. {
  288. unsigned char *minp, *maxp;
  289. double magn;
  290. int v_r,v_g,v_b;
  291. static const int nIterPower = 4;
  292. float covf[6],vfr,vfg,vfb;
  293. // determine color distribution
  294. int cov[6];
  295. int mu[3],min[3],max[3];
  296. int ch,i,iter;
  297. for(ch=0;ch<3;ch++)
  298. {
  299. const unsigned char *bp = ((const unsigned char *) block) + ch;
  300. int muv,minv,maxv;
  301. #ifdef NEW_OPTIMISATIONS
  302. # define MIN(a,b) (int)a + (((int)b-a) & (((int)b-a) >> 31))
  303. # define MAX(a,b) (int)a + (((int)b-a) & (((int)a-b) >> 31))
  304. # define RANGE(a,b,n) int min##n = MIN(a,b); int max##n = a+b - min##n; muv += a+b;
  305. # define MINMAX(a,b,n) int min##n = MIN(min##a, min##b); int max##n = MAX(max##a, max##b);
  306. muv = 0;
  307. RANGE(bp[0], bp[4], 1);
  308. RANGE(bp[8], bp[12], 2);
  309. RANGE(bp[16], bp[20], 3);
  310. RANGE(bp[24], bp[28], 4);
  311. RANGE(bp[32], bp[36], 5);
  312. RANGE(bp[40], bp[44], 6);
  313. RANGE(bp[48], bp[52], 7);
  314. RANGE(bp[56], bp[60], 8);
  315. MINMAX(1,2,9);
  316. MINMAX(3,4,10);
  317. MINMAX(5,6,11);
  318. MINMAX(7,8,12);
  319. MINMAX(9,10,13);
  320. MINMAX(11,12,14);
  321. minv = MIN(min13,min14);
  322. maxv = MAX(max13,max14);
  323. #else
  324. muv = minv = maxv = bp[0];
  325. for(i=4;i<64;i+=4)
  326. {
  327. muv += bp[i];
  328. if (bp[i] < minv) minv = bp[i];
  329. else if (bp[i] > maxv) maxv = bp[i];
  330. }
  331. #endif
  332. mu[ch] = (muv + 8) >> 4;
  333. min[ch] = minv;
  334. max[ch] = maxv;
  335. }
  336. // determine covariance matrix
  337. for (i=0;i<6;i++)
  338. cov[i] = 0;
  339. for (i=0;i<16;i++)
  340. {
  341. int r = block[i*4+0] - mu[0];
  342. int g = block[i*4+1] - mu[1];
  343. int b = block[i*4+2] - mu[2];
  344. cov[0] += r*r;
  345. cov[1] += r*g;
  346. cov[2] += r*b;
  347. cov[3] += g*g;
  348. cov[4] += g*b;
  349. cov[5] += b*b;
  350. }
  351. // convert covariance matrix to float, find principal axis via power iter
  352. for(i=0;i<6;i++)
  353. covf[i] = cov[i] / 255.0f;
  354. vfr = (float) (max[0] - min[0]);
  355. vfg = (float) (max[1] - min[1]);
  356. vfb = (float) (max[2] - min[2]);
  357. for(iter=0;iter<nIterPower;iter++)
  358. {
  359. float r = vfr*covf[0] + vfg*covf[1] + vfb*covf[2];
  360. float g = vfr*covf[1] + vfg*covf[3] + vfb*covf[4];
  361. float b = vfr*covf[2] + vfg*covf[4] + vfb*covf[5];
  362. vfr = r;
  363. vfg = g;
  364. vfb = b;
  365. }
  366. magn = fabs(vfr);
  367. if (fabs(vfg) > magn) magn = fabs(vfg);
  368. if (fabs(vfb) > magn) magn = fabs(vfb);
  369. if(magn < 4.0f)
  370. { // too small, default to luminance
  371. v_r = 299; // JPEG YCbCr luma coefs, scaled by 1000.
  372. v_g = 587;
  373. v_b = 114;
  374. } else {
  375. magn = 512.0 / magn;
  376. v_r = (int) (vfr * magn);
  377. v_g = (int) (vfg * magn);
  378. v_b = (int) (vfb * magn);
  379. }
  380. #ifdef NEW_OPTIMISATIONS
  381. // Pick colors at extreme points
  382. int mind, maxd;
  383. mind = maxd = block[0]*v_r + block[1]*v_g + block[2]*v_b;
  384. minp = maxp = block;
  385. for(i=1;i<16;i++)
  386. {
  387. int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
  388. if (dot < mind) {
  389. mind = dot;
  390. minp = block+i*4;
  391. continue;
  392. }
  393. if (dot > maxd) {
  394. maxd = dot;
  395. maxp = block+i*4;
  396. }
  397. }
  398. #else
  399. int mind = 0x7fffffff,maxd = -0x7fffffff;
  400. // Pick colors at extreme points
  401. for(i=0;i<16;i++)
  402. {
  403. int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
  404. if (dot < mind) {
  405. mind = dot;
  406. minp = block+i*4;
  407. }
  408. if (dot > maxd) {
  409. maxd = dot;
  410. maxp = block+i*4;
  411. }
  412. }
  413. #endif
  414. *pmax16 = stb__As16Bit(maxp[0],maxp[1],maxp[2]);
  415. *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]);
  416. }
  417. inline static int stb__sclamp(float y, int p0, int p1)
  418. {
  419. int x = (int) y;
  420. #ifdef NEW_OPTIMISATIONS
  421. x = x>p1 ? p1 : x;
  422. return x<p0 ? p0 : x;
  423. #else
  424. if (x < p0) return p0;
  425. if (x > p1) return p1;
  426. return x;
  427. #endif
  428. }
  429. // The refinement function. (Clever code, part 2)
  430. // Tries to optimize colors to suit block contents better.
  431. // (By solving a least squares system via normal equations+Cramer's rule)
  432. static int stb__RefineBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16, unsigned int mask)
  433. {
  434. static const int w1Tab[4] = { 3,0,2,1 };
  435. static const int prods[4] = { 0x090000,0x000900,0x040102,0x010402 };
  436. // ^some magic to save a lot of multiplies in the accumulating loop...
  437. // (precomputed products of weights for least squares system, accumulated inside one 32-bit register)
  438. float frb,fg;
  439. unsigned short oldMin, oldMax, min16, max16;
  440. int i, akku = 0, xx,xy,yy;
  441. int At1_r,At1_g,At1_b;
  442. int At2_r,At2_g,At2_b;
  443. unsigned int cm = mask;
  444. oldMin = *pmin16;
  445. oldMax = *pmax16;
  446. if((mask ^ (mask<<2)) < 4) // all pixels have the same index?
  447. {
  448. // yes, linear system would be singular; solve using optimal
  449. // single-color match on average color
  450. int r = 8, g = 8, b = 8;
  451. for (i=0;i<16;++i) {
  452. r += block[i*4+0];
  453. g += block[i*4+1];
  454. b += block[i*4+2];
  455. }
  456. r >>= 4; g >>= 4; b >>= 4;
  457. max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
  458. min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
  459. } else {
  460. At1_r = At1_g = At1_b = 0;
  461. At2_r = At2_g = At2_b = 0;
  462. for (i=0;i<16;++i,cm>>=2)
  463. {
  464. int step = cm&3;
  465. int w1 = w1Tab[step];
  466. int r = block[i*4+0];
  467. int g = block[i*4+1];
  468. int b = block[i*4+2];
  469. akku += prods[step];
  470. At1_r += w1*r;
  471. At1_g += w1*g;
  472. At1_b += w1*b;
  473. At2_r += r;
  474. At2_g += g;
  475. At2_b += b;
  476. }
  477. At2_r = 3*At2_r - At1_r;
  478. At2_g = 3*At2_g - At1_g;
  479. At2_b = 3*At2_b - At1_b;
  480. // extract solutions and decide solvability
  481. xx = akku >> 16;
  482. yy = (akku >> 8) & 0xff;
  483. xy = (akku >> 0) & 0xff;
  484. frb = 3.0f * 31.0f / 255.0f / (xx*yy - xy*xy);
  485. fg = frb * 63.0f / 31.0f;
  486. // solve.
  487. max16 = stb__sclamp((At1_r*yy - At2_r*xy)*frb+0.5f,0,31) << 11;
  488. max16 |= stb__sclamp((At1_g*yy - At2_g*xy)*fg +0.5f,0,63) << 5;
  489. max16 |= stb__sclamp((At1_b*yy - At2_b*xy)*frb+0.5f,0,31) << 0;
  490. min16 = stb__sclamp((At2_r*xx - At1_r*xy)*frb+0.5f,0,31) << 11;
  491. min16 |= stb__sclamp((At2_g*xx - At1_g*xy)*fg +0.5f,0,63) << 5;
  492. min16 |= stb__sclamp((At2_b*xx - At1_b*xy)*frb+0.5f,0,31) << 0;
  493. }
  494. *pmin16 = min16;
  495. *pmax16 = max16;
  496. return oldMin != min16 || oldMax != max16;
  497. }
  498. // Color block compression
  499. static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, int mode)
  500. {
  501. unsigned int mask;
  502. int i;
  503. int dither;
  504. int refinecount;
  505. unsigned short max16, min16;
  506. unsigned char dblock[16*4],color[4*4];
  507. dither = mode & STB_DXT_DITHER;
  508. refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1;
  509. // check if block is constant
  510. for (i=1;i<16;i++)
  511. if (((unsigned int *) block)[i] != ((unsigned int *) block)[0])
  512. break;
  513. if(i == 16)
  514. { // constant color
  515. int r = block[0], g = block[1], b = block[2];
  516. mask = 0xaaaaaaaa;
  517. max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
  518. min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
  519. } else
  520. {
  521. // first step: compute dithered version for PCA if desired
  522. if(dither)
  523. stb__DitherBlock(dblock,block);
  524. // second step: pca+map along principal axis
  525. stb__OptimizeColorsBlock(dither ? dblock : block,&max16,&min16);
  526. if (max16 != min16)
  527. {
  528. stb__EvalColors(color,max16,min16);
  529. mask = stb__MatchColorsBlock(block,color,dither);
  530. } else
  531. mask = 0;
  532. // third step: refine (multiple times if requested)
  533. for (i=0;i<refinecount;i++) {
  534. unsigned int lastmask = mask;
  535. if (stb__RefineBlock(dither ? dblock : block,&max16,&min16,mask))
  536. {
  537. if (max16 != min16)
  538. {
  539. stb__EvalColors(color,max16,min16);
  540. mask = stb__MatchColorsBlock(block,color,dither);
  541. } else
  542. {
  543. mask = 0;
  544. break;
  545. }
  546. }
  547. if(mask == lastmask)
  548. break;
  549. }
  550. }
  551. // write the color block
  552. if(max16 < min16)
  553. {
  554. unsigned short t = min16;
  555. min16 = max16;
  556. max16 = t;
  557. mask ^= 0x55555555;
  558. }
  559. dest[0] = (unsigned char) (max16);
  560. dest[1] = (unsigned char) (max16 >> 8);
  561. dest[2] = (unsigned char) (min16);
  562. dest[3] = (unsigned char) (min16 >> 8);
  563. dest[4] = (unsigned char) (mask);
  564. dest[5] = (unsigned char) (mask >> 8);
  565. dest[6] = (unsigned char) (mask >> 16);
  566. dest[7] = (unsigned char) (mask >> 24);
  567. }
  568. // Alpha block compression (this is easy for a change)
  569. static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src,int mode)
  570. {
  571. int i,dist,bias,dist4,dist2,bits,mask;
  572. // find min/max color
  573. int mn,mx;
  574. mn = mx = src[3];
  575. for (i=1;i<16;i++)
  576. {
  577. if (src[i*4+3] < mn) mn = src[i*4+3];
  578. else if (src[i*4+3] > mx) mx = src[i*4+3];
  579. }
  580. // encode them
  581. ((unsigned char *)dest)[0] = mx;
  582. ((unsigned char *)dest)[1] = mn;
  583. dest += 2;
  584. #ifdef NEW_OPTIMISATIONS
  585. // mono-alpha shortcut
  586. if (mn==mx)
  587. {
  588. *(unsigned short*)dest = 0;
  589. dest += 2;
  590. *(unsigned int*)dest = 0;
  591. return;
  592. }
  593. #endif
  594. // determine bias and emit color indices
  595. // given the choice of mx/mn, these indices are optimal:
  596. // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/
  597. dist = mx-mn;
  598. //printf("mn = %i; mx = %i; dist = %i\n", mn, mx, dist);
  599. dist4 = dist*4;
  600. dist2 = dist*2;
  601. bias = (dist < 8) ? (dist - 1) : (dist/2 + 2);
  602. bias -= mn * 7;
  603. bits = 0, mask=0;
  604. for (i=0;i<16;i++)
  605. {
  606. int a = src[i*4+3]*7 + bias;
  607. int ind,t;
  608. // select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max).
  609. t = (a >= dist4) ? -1 : 0; ind = t & 4; a -= dist4 & t;
  610. t = (a >= dist2) ? -1 : 0; ind += t & 2; a -= dist2 & t;
  611. ind += (a >= dist);
  612. // turn linear scale into DXT index (0/1 are extremal pts)
  613. ind = -ind & 7;
  614. ind ^= (2 > ind);
  615. // write index
  616. mask |= ind << bits;
  617. if((bits += 3) >= 8)
  618. {
  619. *dest++ = mask;
  620. mask >>= 8;
  621. bits -= 8;
  622. }
  623. }
  624. }
  625. static void stb__InitDXT()
  626. {
  627. int i;
  628. for(i=0;i<32;i++)
  629. stb__Expand5[i] = (i<<3)|(i>>2);
  630. for(i=0;i<64;i++)
  631. stb__Expand6[i] = (i<<2)|(i>>4);
  632. for(i=0;i<256+16;i++)
  633. {
  634. int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8;
  635. stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)];
  636. stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)];
  637. }
  638. stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32);
  639. stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64);
  640. }
  641. void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode)
  642. {
  643. static int init=1;
  644. if (init)
  645. {
  646. stb__InitDXT();
  647. init=0;
  648. }
  649. if (alpha)
  650. {
  651. stb__CompressAlphaBlock(dest,(unsigned char*) src,mode);
  652. dest += 8;
  653. }
  654. stb__CompressColorBlock(dest,(unsigned char*) src,mode);
  655. }
  656. int imin(int x, int y) { return (x < y) ? x : y; }
  657. static void extractBlock(const unsigned char *src, int x, int y,
  658. int w, int h, unsigned char *block)
  659. {
  660. int i, j;
  661. #ifdef NEW_OPTIMISATIONS
  662. if ((w-x >=4) && (h-y >=4))
  663. {
  664. // Full Square shortcut
  665. src += x*4;
  666. src += y*w*4;
  667. for (i=0; i < 4; ++i)
  668. {
  669. *(unsigned int*)block = *(unsigned int*) src; block += 4; src += 4;
  670. *(unsigned int*)block = *(unsigned int*) src; block += 4; src += 4;
  671. *(unsigned int*)block = *(unsigned int*) src; block += 4; src += 4;
  672. *(unsigned int*)block = *(unsigned int*) src; block += 4;
  673. src += (w*4) - 12;
  674. }
  675. return;
  676. }
  677. #endif
  678. int bw = imin(w - x, 4);
  679. int bh = imin(h - y, 4);
  680. int bx, by;
  681. const int rem[] =
  682. {
  683. 0, 0, 0, 0,
  684. 0, 1, 0, 1,
  685. 0, 1, 2, 0,
  686. 0, 1, 2, 3
  687. };
  688. for(i = 0; i < 4; ++i)
  689. {
  690. by = rem[(bh - 1) * 4 + i] + y;
  691. for(j = 0; j < 4; ++j)
  692. {
  693. bx = rem[(bw - 1) * 4 + j] + x;
  694. block[(i * 4 * 4) + (j * 4) + 0] =
  695. src[(by * (w * 4)) + (bx * 4) + 0];
  696. block[(i * 4 * 4) + (j * 4) + 1] =
  697. src[(by * (w * 4)) + (bx * 4) + 1];
  698. block[(i * 4 * 4) + (j * 4) + 2] =
  699. src[(by * (w * 4)) + (bx * 4) + 2];
  700. block[(i * 4 * 4) + (j * 4) + 3] =
  701. src[(by * (w * 4)) + (bx * 4) + 3];
  702. }
  703. }
  704. }
  705. // should be a pretty optimized 0-255 clamper
  706. inline static unsigned char clamp255(int n)
  707. {
  708. if(n > 255) n = 255;
  709. if(n < 0) n = 0;
  710. return n;
  711. }
  712. void rgbToYCoCgBlock(unsigned char * dst, const unsigned char * src)
  713. {
  714. // Calculate Co and Cg extents
  715. int extents = 0;
  716. int n = 0;
  717. int iY, iCo, iCg; //, r, g, b;
  718. int blockCo[16];
  719. int blockCg[16];
  720. int i;
  721. const unsigned char *px = src;
  722. for(i=0;i<n;i++)
  723. {
  724. iCo = (px[0]<<1) - (px[2]<<1);
  725. iCg = (px[1]<<1) - px[0] - px[2];
  726. if(-iCo > extents) extents = -iCo;
  727. if(iCo > extents) extents = iCo;
  728. if(-iCg > extents) extents = -iCg;
  729. if(iCg > extents) extents = iCg;
  730. blockCo[n] = iCo;
  731. blockCg[n++] = iCg;
  732. px += 4;
  733. }
  734. // Co = -510..510
  735. // Cg = -510..510
  736. float scaleFactor = 1.0f;
  737. if(extents > 127)
  738. scaleFactor = (float)extents * 4.0f / 510.0f;
  739. // Convert to quantized scalefactor
  740. unsigned char scaleFactorQuantized = (unsigned char)(ceil((scaleFactor - 1.0f) * 31.0f / 3.0f));
  741. // Unquantize
  742. scaleFactor = 1.0f + (float)(scaleFactorQuantized / 31.0f) * 3.0f;
  743. unsigned char bVal = (unsigned char)((scaleFactorQuantized << 3) | (scaleFactorQuantized >> 2));
  744. unsigned char *outPx = dst;
  745. n = 0;
  746. px = src;
  747. /*
  748. for(i=0;i<16;i++)
  749. {
  750. // Calculate components
  751. iY = (px[0] + (px[1]<<1) + px[2] + 2) / 4;
  752. iCo = ((blockCo[n] / scaleFactor) + 128);
  753. iCg = ((blockCg[n] / scaleFactor) + 128);
  754. if(iCo < 0) iCo = 0; else if(iCo > 255) iCo = 255;
  755. if(iCg < 0) iCg = 0; else if(iCg > 255) iCg = 255;
  756. if(iY < 0) iY = 0; else if(iY > 255) iY = 255;
  757. px += 4;
  758. outPx[0] = (unsigned char)iCo;
  759. outPx[1] = (unsigned char)iCg;
  760. outPx[2] = bVal;
  761. outPx[3] = (unsigned char)iY;
  762. outPx += 4;
  763. }*/
  764. for(i=0;i<16;i++)
  765. {
  766. // Calculate components
  767. int r = px[0];
  768. int g = (px[1] + 1) >> 1;
  769. int b = px[2];
  770. int tmp = (2 + r + b) >> 2;
  771. // Co
  772. iCo = clamp255(128 + ((r - b + 1) >> 1));
  773. // Y
  774. iY = clamp255(g + tmp);
  775. // Cg
  776. iCg = clamp255(128 + g - tmp);
  777. px += 4;
  778. outPx[0] = (unsigned char)iCo;
  779. outPx[1] = (unsigned char)iCg;
  780. outPx[2] = bVal;
  781. outPx[3] = (unsigned char)iY;
  782. outPx += 4;
  783. }
  784. }
  785. void rygCompress(unsigned char *dst, unsigned char *src, int w, int h, int isDxt5)
  786. {
  787. unsigned char block[64];
  788. int x, y;
  789. for(y = 0; y < h; y += 4)
  790. {
  791. for(x = 0; x < w; x += 4)
  792. {
  793. extractBlock(src, x, y, w, h, block);
  794. stb_compress_dxt_block(dst, block, isDxt5, 10);
  795. dst += isDxt5 ? 16 : 8;
  796. }
  797. }
  798. }
  799. void rygCompressYCoCg(unsigned char *dst, unsigned char *src, int w, int h)
  800. {
  801. unsigned char block[64];
  802. unsigned char ycocgblock[64];
  803. int x, y;
  804. for(y = 0; y < h; y += 4)
  805. {
  806. for(x = 0; x < w; x += 4)
  807. {
  808. extractBlock(src, x, y, w, h, block);
  809. rgbToYCoCgBlock(ycocgblock,block);
  810. stb_compress_dxt_block(dst, ycocgblock, 1, 10);
  811. dst += 16;
  812. }
  813. }
  814. }
  815. static void stbgl__compress(unsigned char *p, unsigned char *rgba, int w, int h, int isDxt5)
  816. {
  817. int i,j,y,y2;
  818. int alpha = isDxt5;
  819. for (j=0; j < w; j += 4) {
  820. int x=4;
  821. for (i=0; i < h; i += 4) {
  822. unsigned char block[16*4];
  823. if (i+3 >= w) x = w-i;
  824. for (y=0; y < 4; ++y) {
  825. if (j+y >= h) break;
  826. memcpy(block+y*16, rgba + w*4*(j+y) + i*4, x*4);
  827. }
  828. if (x < 4) {
  829. switch (x) {
  830. case 0: assert(0);
  831. case 1:
  832. for (y2=0; y2 < y; ++y2) {
  833. memcpy(block+y2*16+1*4, block+y2*16+0*4, 4);
  834. memcpy(block+y2*16+2*4, block+y2*16+0*4, 8);
  835. }
  836. break;
  837. case 2:
  838. for (y2=0; y2 < y; ++y2)
  839. memcpy(block+y2*16+2*4, block+y2*16+0*4, 8);
  840. break;
  841. case 3:
  842. for (y2=0; y2 < y; ++y2)
  843. memcpy(block+y2*16+3*4, block+y2*16+1*4, 4);
  844. break;
  845. }
  846. }
  847. y2 = 0;
  848. for(; y<4; ++y,++y2)
  849. memcpy(block+y*16, block+y2*16, 4*4);
  850. stb_compress_dxt_block(p, block, alpha, 10);
  851. p += alpha ? 16 : 8;
  852. }
  853. }
  854. // assert(p <= end);
  855. }
  856. static inline unsigned char linearize(unsigned char inByte)
  857. {
  858. float srgbVal = ((float)inByte) / 255.0f;
  859. float linearVal;
  860. if(srgbVal < 0.04045)
  861. linearVal = srgbVal / 12.92f;
  862. else
  863. linearVal = pow((srgbVal + 0.055f) / 1.055f, 2.4f);
  864. return (unsigned char)(floor(sqrt(linearVal)* 255.0 + 0.5));
  865. }
  866. void linearize(unsigned char * dst, const unsigned char * src, int n)
  867. {
  868. n*=4;
  869. for(int i = 0; i < n; i++)
  870. dst[i] = linearize(src[i]);
  871. }
  872. #endif // STB_DXT_IMPLEMENTATION
  873. #endif // STB_INCLUDE_STB_DXT_H