Pārlūkot izejas kodu

stb_dxt: Initialize tables at compile time

Also fix a "potentially uninitialized variable" warning.

This is a modified version of Alan's original PR that keeps the
table generator in the file (in case there's interest) and also
replaces the expand[] tables with math, since it's trivial.

Fixes issue #1117.
Alan Hickman 4 gadi atpakaļ
vecāks
revīzija
98623b9577
1 mainītis faili ar 191 papildinājumiem un 76 dzēšanām
  1. 191 76
      stb_dxt.h

+ 191 - 76
stb_dxt.h

@@ -29,6 +29,7 @@
 //   Kevin Schmidt (#defines for "freestanding" compilation)
 //   Kevin Schmidt (#defines for "freestanding" compilation)
 //   github:ppiastucki (BC4 support)
 //   github:ppiastucki (BC4 support)
 //   Ignacio Castano - improve DXT endpoint quantization
 //   Ignacio Castano - improve DXT endpoint quantization
+//   Alan Hickman - static table initialization
 //
 //
 // LICENSE
 // LICENSE
 //
 //
@@ -81,14 +82,10 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 
 
-#if !defined(STBD_ABS) || !defined(STBI_FABS)
+#if !defined(STBI_FABS)
 #include <math.h>
 #include <math.h>
 #endif
 #endif
 
 
-#ifndef STBD_ABS
-#define STBD_ABS(i)           abs(i)
-#endif
-
 #ifndef STBD_FABS
 #ifndef STBD_FABS
 #define STBD_FABS(x)          fabs(x)
 #define STBD_FABS(x)          fabs(x)
 #endif
 #endif
@@ -98,12 +95,112 @@ STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *sr
 #define STBD_MEMSET           memset
 #define STBD_MEMSET           memset
 #endif
 #endif
 
 
-static unsigned char stb__Expand5[32];
-static unsigned char stb__Expand6[64];
-static unsigned char stb__OMatch5[256][2];
-static unsigned char stb__OMatch6[256][2];
-static unsigned char stb__QuantRBTab[256+16];
-static unsigned char stb__QuantGTab[256+16];
+static const unsigned char stb__QuantRBTab[256 + 16] = {
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,   8,   8,
+     8,   8,   8,   8,   8,  16,  16,  16,  16,  16,  16,  16,  16,  24,  24,  24,
+    24,  24,  24,  24,  24,  33,  33,  33,  33,  33,  33,  33,  33,  33,  41,  41,
+    41,  41,  41,  41,  41,  41,  49,  49,  49,  49,  49,  49,  49,  49,  57,  57,
+    57,  57,  57,  57,  57,  57,  66,  66,  66,  66,  66,  66,  66,  66,  74,  74,
+    74,  74,  74,  74,  74,  74,  74,  82,  82,  82,  82,  82,  82,  82,  82,  90,
+    90,  90,  90,  90,  90,  90,  90,  99,  99,  99,  99,  99,  99,  99,  99, 107,
+   107, 107, 107, 107, 107, 107, 107, 107, 115, 115, 115, 115, 115, 115, 115, 115,
+   123, 123, 123, 123, 123, 123, 123, 123, 132, 132, 132, 132, 132, 132, 132, 132,
+   140, 140, 140, 140, 140, 140, 140, 140, 148, 148, 148, 148, 148, 148, 148, 148,
+   148, 156, 156, 156, 156, 156, 156, 156, 156, 165, 165, 165, 165, 165, 165, 165,
+   165, 173, 173, 173, 173, 173, 173, 173, 173, 181, 181, 181, 181, 181, 181, 181,
+   181, 181, 189, 189, 189, 189, 189, 189, 189, 189, 198, 198, 198, 198, 198, 198,
+   198, 198, 206, 206, 206, 206, 206, 206, 206, 206, 214, 214, 214, 214, 214, 214,
+   214, 214, 222, 222, 222, 222, 222, 222, 222, 222, 222, 231, 231, 231, 231, 231,
+   231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 247, 247, 247, 247, 247,
+   247, 247, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+};
+static const unsigned char stb__QuantGTab[256 + 16] = {
+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   4,   4,   4,   4,   8,
+     8,   8,   8,  12,  12,  12,  12,  16,  16,  16,  16,  20,  20,  20,  20,  24,
+    24,  24,  24,  28,  28,  28,  28,  32,  32,  32,  32,  36,  36,  36,  36,  40,
+    40,  40,  40,  44,  44,  44,  44,  48,  48,  48,  48,  52,  52,  52,  52,  56,
+    56,  56,  56,  60,  60,  60,  60,  65,  65,  65,  65,  69,  69,  69,  69,  73,
+    73,  73,  73,  77,  77,  77,  77,  81,  81,  81,  81,  85,  85,  85,  85,  85,
+    89,  89,  89,  89,  93,  93,  93,  93,  97,  97,  97,  97, 101, 101, 101, 101,
+   105, 105, 105, 105, 109, 109, 109, 109, 113, 113, 113, 113, 117, 117, 117, 117,
+   121, 121, 121, 121, 125, 125, 125, 125, 130, 130, 130, 130, 134, 134, 134, 134,
+   138, 138, 138, 138, 142, 142, 142, 142, 146, 146, 146, 146, 150, 150, 150, 150,
+   154, 154, 154, 154, 158, 158, 158, 158, 162, 162, 162, 162, 166, 166, 166, 166,
+   170, 170, 170, 170, 170, 174, 174, 174, 174, 178, 178, 178, 178, 182, 182, 182,
+   182, 186, 186, 186, 186, 190, 190, 190, 190, 195, 195, 195, 195, 199, 199, 199,
+   199, 203, 203, 203, 203, 207, 207, 207, 207, 211, 211, 211, 211, 215, 215, 215,
+   215, 219, 219, 219, 219, 223, 223, 223, 223, 227, 227, 227, 227, 231, 231, 231,
+   231, 235, 235, 235, 235, 239, 239, 239, 239, 243, 243, 243, 243, 247, 247, 247,
+   247, 251, 251, 251, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+};
+static const unsigned char stb__OMatch5[256][2] = {
+   {  0,  0 }, {  0,  0 }, {  0,  1 }, {  0,  1 }, {  1,  0 }, {  1,  0 }, {  1,  0 }, {  1,  1 },
+   {  1,  1 }, {  2,  0 }, {  2,  0 }, {  0,  4 }, {  2,  1 }, {  2,  1 }, {  2,  1 }, {  3,  0 },
+   {  3,  0 }, {  3,  0 }, {  3,  1 }, {  1,  5 }, {  3,  2 }, {  3,  2 }, {  4,  0 }, {  4,  0 },
+   {  4,  1 }, {  4,  1 }, {  4,  2 }, {  4,  2 }, {  4,  2 }, {  3,  5 }, {  5,  1 }, {  5,  1 },
+   {  5,  2 }, {  4,  4 }, {  5,  3 }, {  5,  3 }, {  5,  3 }, {  6,  2 }, {  6,  2 }, {  6,  2 },
+   {  6,  3 }, {  5,  5 }, {  6,  4 }, {  6,  4 }, {  4,  8 }, {  7,  3 }, {  7,  3 }, {  7,  3 },
+   {  7,  4 }, {  7,  4 }, {  7,  4 }, {  7,  5 }, {  5,  9 }, {  7,  6 }, {  7,  6 }, {  8,  4 },
+   {  8,  4 }, {  8,  5 }, {  8,  5 }, {  8,  6 }, {  8,  6 }, {  8,  6 }, {  7,  9 }, {  9,  5 },
+   {  9,  5 }, {  9,  6 }, {  8,  8 }, {  9,  7 }, {  9,  7 }, {  9,  7 }, { 10,  6 }, { 10,  6 },
+   { 10,  6 }, { 10,  7 }, {  9,  9 }, { 10,  8 }, { 10,  8 }, {  8, 12 }, { 11,  7 }, { 11,  7 },
+   { 11,  7 }, { 11,  8 }, { 11,  8 }, { 11,  8 }, { 11,  9 }, {  9, 13 }, { 11, 10 }, { 11, 10 },
+   { 12,  8 }, { 12,  8 }, { 12,  9 }, { 12,  9 }, { 12, 10 }, { 12, 10 }, { 12, 10 }, { 11, 13 },
+   { 13,  9 }, { 13,  9 }, { 13, 10 }, { 12, 12 }, { 13, 11 }, { 13, 11 }, { 13, 11 }, { 14, 10 },
+   { 14, 10 }, { 14, 10 }, { 14, 11 }, { 13, 13 }, { 14, 12 }, { 14, 12 }, { 12, 16 }, { 15, 11 },
+   { 15, 11 }, { 15, 11 }, { 15, 12 }, { 15, 12 }, { 15, 12 }, { 15, 13 }, { 13, 17 }, { 15, 14 },
+   { 15, 14 }, { 16, 12 }, { 16, 12 }, { 16, 13 }, { 16, 13 }, { 16, 14 }, { 16, 14 }, { 16, 14 },
+   { 15, 17 }, { 17, 13 }, { 17, 13 }, { 17, 14 }, { 16, 16 }, { 17, 15 }, { 17, 15 }, { 17, 15 },
+   { 18, 14 }, { 18, 14 }, { 18, 14 }, { 18, 15 }, { 17, 17 }, { 18, 16 }, { 18, 16 }, { 16, 20 },
+   { 19, 15 }, { 19, 15 }, { 19, 15 }, { 19, 16 }, { 19, 16 }, { 19, 16 }, { 19, 17 }, { 17, 21 },
+   { 19, 18 }, { 19, 18 }, { 20, 16 }, { 20, 16 }, { 20, 17 }, { 20, 17 }, { 20, 18 }, { 20, 18 },
+   { 20, 18 }, { 19, 21 }, { 21, 17 }, { 21, 17 }, { 21, 18 }, { 20, 20 }, { 21, 19 }, { 21, 19 },
+   { 21, 19 }, { 22, 18 }, { 22, 18 }, { 22, 18 }, { 22, 19 }, { 21, 21 }, { 22, 20 }, { 22, 20 },
+   { 20, 24 }, { 23, 19 }, { 23, 19 }, { 23, 19 }, { 23, 20 }, { 23, 20 }, { 23, 20 }, { 23, 21 },
+   { 21, 25 }, { 23, 22 }, { 23, 22 }, { 24, 20 }, { 24, 20 }, { 24, 21 }, { 24, 21 }, { 24, 22 },
+   { 24, 22 }, { 24, 22 }, { 23, 25 }, { 25, 21 }, { 25, 21 }, { 25, 22 }, { 24, 24 }, { 25, 23 },
+   { 25, 23 }, { 25, 23 }, { 26, 22 }, { 26, 22 }, { 26, 22 }, { 26, 23 }, { 25, 25 }, { 26, 24 },
+   { 26, 24 }, { 24, 28 }, { 27, 23 }, { 27, 23 }, { 27, 23 }, { 27, 24 }, { 27, 24 }, { 27, 24 },
+   { 27, 25 }, { 25, 29 }, { 27, 26 }, { 27, 26 }, { 28, 24 }, { 28, 24 }, { 28, 25 }, { 28, 25 },
+   { 28, 26 }, { 28, 26 }, { 28, 26 }, { 27, 29 }, { 29, 25 }, { 29, 25 }, { 29, 26 }, { 28, 28 },
+   { 29, 27 }, { 29, 27 }, { 29, 27 }, { 30, 26 }, { 30, 26 }, { 30, 26 }, { 30, 27 }, { 29, 29 },
+   { 30, 28 }, { 30, 28 }, { 30, 28 }, { 31, 27 }, { 31, 27 }, { 31, 27 }, { 31, 28 }, { 31, 28 },
+   { 31, 28 }, { 31, 29 }, { 31, 29 }, { 31, 30 }, { 31, 30 }, { 31, 30 }, { 31, 31 }, { 31, 31 },
+};
+static const unsigned char stb__OMatch6[256][2] = {
+   {  0,  0 }, {  0,  1 }, {  1,  0 }, {  1,  0 }, {  1,  1 }, {  2,  0 }, {  2,  1 }, {  3,  0 },
+   {  3,  0 }, {  3,  1 }, {  4,  0 }, {  4,  0 }, {  4,  1 }, {  5,  0 }, {  5,  1 }, {  6,  0 },
+   {  6,  0 }, {  6,  1 }, {  7,  0 }, {  7,  0 }, {  7,  1 }, {  8,  0 }, {  8,  1 }, {  8,  1 },
+   {  8,  2 }, {  9,  1 }, {  9,  2 }, {  9,  2 }, {  9,  3 }, { 10,  2 }, { 10,  3 }, { 10,  3 },
+   { 10,  4 }, { 11,  3 }, { 11,  4 }, { 11,  4 }, { 11,  5 }, { 12,  4 }, { 12,  5 }, { 12,  5 },
+   { 12,  6 }, { 13,  5 }, { 13,  6 }, {  8, 16 }, { 13,  7 }, { 14,  6 }, { 14,  7 }, {  9, 17 },
+   { 14,  8 }, { 15,  7 }, { 15,  8 }, { 11, 16 }, { 15,  9 }, { 15, 10 }, { 16,  8 }, { 16,  9 },
+   { 16, 10 }, { 15, 13 }, { 17,  9 }, { 17, 10 }, { 17, 11 }, { 15, 16 }, { 18, 10 }, { 18, 11 },
+   { 18, 12 }, { 16, 16 }, { 19, 11 }, { 19, 12 }, { 19, 13 }, { 17, 17 }, { 20, 12 }, { 20, 13 },
+   { 20, 14 }, { 19, 16 }, { 21, 13 }, { 21, 14 }, { 21, 15 }, { 20, 17 }, { 22, 14 }, { 22, 15 },
+   { 25, 10 }, { 22, 16 }, { 23, 15 }, { 23, 16 }, { 26, 11 }, { 23, 17 }, { 24, 16 }, { 24, 17 },
+   { 27, 12 }, { 24, 18 }, { 25, 17 }, { 25, 18 }, { 28, 13 }, { 25, 19 }, { 26, 18 }, { 26, 19 },
+   { 29, 14 }, { 26, 20 }, { 27, 19 }, { 27, 20 }, { 30, 15 }, { 27, 21 }, { 28, 20 }, { 28, 21 },
+   { 28, 21 }, { 28, 22 }, { 29, 21 }, { 29, 22 }, { 24, 32 }, { 29, 23 }, { 30, 22 }, { 30, 23 },
+   { 25, 33 }, { 30, 24 }, { 31, 23 }, { 31, 24 }, { 27, 32 }, { 31, 25 }, { 31, 26 }, { 32, 24 },
+   { 32, 25 }, { 32, 26 }, { 31, 29 }, { 33, 25 }, { 33, 26 }, { 33, 27 }, { 31, 32 }, { 34, 26 },
+   { 34, 27 }, { 34, 28 }, { 32, 32 }, { 35, 27 }, { 35, 28 }, { 35, 29 }, { 33, 33 }, { 36, 28 },
+   { 36, 29 }, { 36, 30 }, { 35, 32 }, { 37, 29 }, { 37, 30 }, { 37, 31 }, { 36, 33 }, { 38, 30 },
+   { 38, 31 }, { 41, 26 }, { 38, 32 }, { 39, 31 }, { 39, 32 }, { 42, 27 }, { 39, 33 }, { 40, 32 },
+   { 40, 33 }, { 43, 28 }, { 40, 34 }, { 41, 33 }, { 41, 34 }, { 44, 29 }, { 41, 35 }, { 42, 34 },
+   { 42, 35 }, { 45, 30 }, { 42, 36 }, { 43, 35 }, { 43, 36 }, { 46, 31 }, { 43, 37 }, { 44, 36 },
+   { 44, 37 }, { 44, 37 }, { 44, 38 }, { 45, 37 }, { 45, 38 }, { 40, 48 }, { 45, 39 }, { 46, 38 },
+   { 46, 39 }, { 41, 49 }, { 46, 40 }, { 47, 39 }, { 47, 40 }, { 43, 48 }, { 47, 41 }, { 47, 42 },
+   { 48, 40 }, { 48, 41 }, { 48, 42 }, { 47, 45 }, { 49, 41 }, { 49, 42 }, { 49, 43 }, { 47, 48 },
+   { 50, 42 }, { 50, 43 }, { 50, 44 }, { 48, 48 }, { 51, 43 }, { 51, 44 }, { 51, 45 }, { 49, 49 },
+   { 52, 44 }, { 52, 45 }, { 52, 46 }, { 51, 48 }, { 53, 45 }, { 53, 46 }, { 53, 47 }, { 52, 49 },
+   { 54, 46 }, { 54, 47 }, { 57, 42 }, { 54, 48 }, { 55, 47 }, { 55, 48 }, { 58, 43 }, { 55, 49 },
+   { 56, 48 }, { 56, 49 }, { 59, 44 }, { 56, 50 }, { 57, 49 }, { 57, 50 }, { 60, 45 }, { 57, 51 },
+   { 58, 50 }, { 58, 51 }, { 61, 46 }, { 58, 52 }, { 59, 51 }, { 59, 52 }, { 62, 47 }, { 59, 53 },
+   { 60, 52 }, { 60, 53 }, { 60, 53 }, { 60, 54 }, { 61, 53 }, { 61, 54 }, { 61, 54 }, { 61, 55 },
+   { 62, 54 }, { 62, 55 }, { 62, 55 }, { 62, 56 }, { 63, 55 }, { 63, 56 }, { 63, 56 }, { 63, 57 },
+   { 63, 58 }, { 63, 59 }, { 63, 59 }, { 63, 60 }, { 63, 61 }, { 63, 62 }, { 63, 62 }, { 63, 63 },
+};
 
 
 static int stb__Mul8Bit(int a, int b)
 static int stb__Mul8Bit(int a, int b)
 {
 {
@@ -117,9 +214,10 @@ static void stb__From16Bit(unsigned char *out, unsigned short v)
    int gv = (v & 0x07e0) >>  5;
    int gv = (v & 0x07e0) >>  5;
    int bv = (v & 0x001f) >>  0;
    int bv = (v & 0x001f) >>  0;
 
 
-   out[0] = stb__Expand5[rv];
-   out[1] = stb__Expand6[gv];
-   out[2] = stb__Expand5[bv];
+   // expand to 8 bits via bit replication
+   out[0] = (rv * 33) >> 2;
+   out[1] = (gv * 65) >> 4;
+   out[2] = (bv * 33) >> 2;
    out[3] = 0;
    out[3] = 0;
 }
 }
 
 
@@ -151,35 +249,6 @@ static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char
 
 
 /****************************************************************************/
 /****************************************************************************/
 
 
-// compute table to reproduce constant colors as accurately as possible
-static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size)
-{
-   int i,mn,mx;
-   for (i=0;i<256;i++) {
-      int bestErr = 256;
-      for (mn=0;mn<size;mn++) {
-         for (mx=0;mx<size;mx++) {
-            int mine = expand[mn];
-            int maxe = expand[mx];
-            int err = STBD_ABS(stb__Lerp13(maxe, mine) - i);
-
-            // DX10 spec says that interpolation must be within 3% of "correct" result,
-            // add this as error term. (normally we'd expect a random distribution of
-            // +-1.5% error, but nowhere in the spec does it say that the error has to be
-            // unbiased - better safe than sorry).
-            err += STBD_ABS(maxe - mine) * 3 / 100;
-
-            if(err < bestErr)
-            {
-               Table[i*2+0] = (unsigned char)mx;
-               Table[i*2+1] = (unsigned char)mn;
-               bestErr = err;
-            }
-         }
-      }
-   }
-}
-
 static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1)
 static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1)
 {
 {
    stb__From16Bit(color+ 0, c0);
    stb__From16Bit(color+ 0, c0);
@@ -198,7 +267,7 @@ static void stb__DitherBlock(unsigned char *dest, unsigned char *block)
   // process channels separately
   // process channels separately
   for (ch=0; ch<3; ++ch) {
   for (ch=0; ch<3; ++ch) {
       unsigned char *bp = block+ch, *dp = dest+ch;
       unsigned char *bp = block+ch, *dp = dest+ch;
-      unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8;
+      const unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8;
       STBD_MEMSET(err, 0, sizeof(err));
       STBD_MEMSET(err, 0, sizeof(err));
       for(y=0; y<4; ++y) {
       for(y=0; y<4; ++y) {
          dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
          dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
@@ -316,7 +385,7 @@ static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *c
 // The color optimization function. (Clever code, part 1)
 // The color optimization function. (Clever code, part 1)
 static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16)
 static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16)
 {
 {
-  int mind = 0x7fffffff,maxd = -0x7fffffff;
+  int mind,maxd;
   unsigned char *minp, *maxp;
   unsigned char *minp, *maxp;
   double magn;
   double magn;
   int v_r,v_g,v_b;
   int v_r,v_g,v_b;
@@ -398,8 +467,10 @@ static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax1
       v_b = (int) (vfb * magn);
       v_b = (int) (vfb * magn);
    }
    }
 
 
+   minp = maxp = block;
+   mind = maxd = block[0]*v_r + block[1]*v_g + block[2]*v_b;
    // Pick colors at extreme points
    // Pick colors at extreme points
-   for(i=0;i<16;i++)
+   for(i=1;i<16;i++)
    {
    {
       int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
       int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
 
 
@@ -418,12 +489,12 @@ static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax1
    *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]);
    *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]);
 }
 }
 
 
-static const float midpoints5[32] = {
+static const float stb__midpoints5[32] = {
    0.015686f, 0.047059f, 0.078431f, 0.111765f, 0.145098f, 0.176471f, 0.207843f, 0.241176f, 0.274510f, 0.305882f, 0.337255f, 0.370588f, 0.403922f, 0.435294f, 0.466667f, 0.5f,
    0.015686f, 0.047059f, 0.078431f, 0.111765f, 0.145098f, 0.176471f, 0.207843f, 0.241176f, 0.274510f, 0.305882f, 0.337255f, 0.370588f, 0.403922f, 0.435294f, 0.466667f, 0.5f,
    0.533333f, 0.564706f, 0.596078f, 0.629412f, 0.662745f, 0.694118f, 0.725490f, 0.758824f, 0.792157f, 0.823529f, 0.854902f, 0.888235f, 0.921569f, 0.952941f, 0.984314f, 1.0f
    0.533333f, 0.564706f, 0.596078f, 0.629412f, 0.662745f, 0.694118f, 0.725490f, 0.758824f, 0.792157f, 0.823529f, 0.854902f, 0.888235f, 0.921569f, 0.952941f, 0.984314f, 1.0f
 };
 };
 
 
-static const float midpoints6[64] = {
+static const float stb__midpoints6[64] = {
    0.007843f, 0.023529f, 0.039216f, 0.054902f, 0.070588f, 0.086275f, 0.101961f, 0.117647f, 0.133333f, 0.149020f, 0.164706f, 0.180392f, 0.196078f, 0.211765f, 0.227451f, 0.245098f,
    0.007843f, 0.023529f, 0.039216f, 0.054902f, 0.070588f, 0.086275f, 0.101961f, 0.117647f, 0.133333f, 0.149020f, 0.164706f, 0.180392f, 0.196078f, 0.211765f, 0.227451f, 0.245098f,
    0.262745f, 0.278431f, 0.294118f, 0.309804f, 0.325490f, 0.341176f, 0.356863f, 0.372549f, 0.388235f, 0.403922f, 0.419608f, 0.435294f, 0.450980f, 0.466667f, 0.482353f, 0.500000f,
    0.262745f, 0.278431f, 0.294118f, 0.309804f, 0.325490f, 0.341176f, 0.356863f, 0.372549f, 0.388235f, 0.403922f, 0.419608f, 0.435294f, 0.450980f, 0.466667f, 0.482353f, 0.500000f,
    0.517647f, 0.533333f, 0.549020f, 0.564706f, 0.580392f, 0.596078f, 0.611765f, 0.627451f, 0.643137f, 0.658824f, 0.674510f, 0.690196f, 0.705882f, 0.721569f, 0.737255f, 0.754902f,
    0.517647f, 0.533333f, 0.549020f, 0.564706f, 0.580392f, 0.596078f, 0.611765f, 0.627451f, 0.643137f, 0.658824f, 0.674510f, 0.690196f, 0.705882f, 0.721569f, 0.737255f, 0.754902f,
@@ -435,7 +506,7 @@ static unsigned short stb__Quantize5(float x)
    unsigned short q;
    unsigned short q;
    x = x < 0 ? 0 : x > 1 ? 1 : x;  // saturate
    x = x < 0 ? 0 : x > 1 ? 1 : x;  // saturate
    q = (unsigned short)(x * 31);
    q = (unsigned short)(x * 31);
-   q += (x > midpoints5[q]);
+   q += (x > stb__midpoints5[q]);
    return q;
    return q;
 }
 }
 
 
@@ -444,7 +515,7 @@ static unsigned short stb__Quantize6(float x)
    unsigned short q;
    unsigned short q;
    x = x < 0 ? 0 : x > 1 ? 1 : x;  // saturate
    x = x < 0 ? 0 : x > 1 ? 1 : x;  // saturate
    q = (unsigned short)(x * 63);
    q = (unsigned short)(x * 63);
-   q += (x > midpoints6[q]);
+   q += (x > stb__midpoints6[q]);
    return q;
    return q;
 }
 }
 
 
@@ -654,35 +725,9 @@ static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int
    }
    }
 }
 }
 
 
-static void stb__InitDXT()
-{
-   int i;
-   for(i=0;i<32;i++)
-      stb__Expand5[i] = (unsigned char)((i<<3)|(i>>2));
-
-   for(i=0;i<64;i++)
-      stb__Expand6[i] = (unsigned char)((i<<2)|(i>>4));
-
-   for(i=0;i<256+16;i++)
-   {
-      int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8;
-      stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)];
-      stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)];
-   }
-
-   stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32);
-   stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64);
-}
-
 void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode)
 void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode)
 {
 {
    unsigned char data[16][4];
    unsigned char data[16][4];
-   static int init=1;
-   if (init) {
-      stb__InitDXT();
-      init=0;
-   }
-
    if (alpha) {
    if (alpha) {
       int i;
       int i;
       stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4);
       stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4);
@@ -710,6 +755,76 @@ void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src)
 }
 }
 #endif // STB_DXT_IMPLEMENTATION
 #endif // STB_DXT_IMPLEMENTATION
 
 
+// Compile with STB_DXT_IMPLEMENTATION and STB_DXT_GENERATE_TABLES
+// defined to generate the tables above.
+#ifdef STB_DXT_GENERATE_TABLES
+#include <stdio.h>
+
+int main()
+{
+   int i, j;
+   const char *quant_names[] = { "stb__QuantRBTab", "stb__QuantGTab" };
+   const char *omatch_names[] = { "stb__OMatch5", "stb__OMatch6" };
+   int dequant_mults[2] = { 33*4, 65 }; // .4 fixed-point dequant multipliers
+
+   // quant tables (for dither)
+   for (i=0; i < 2; ++i) {
+      int quant_mult = i ? 63 : 31;
+      printf("static const unsigned char %s[256 + 16] = {\n", quant_names[i]);
+      for (int j = 0; j < 256 + 16; ++j) {
+         int v = j - 8;
+         int q, dq;
+
+         v = (v < 0) ? 0 : (v > 255) ? 255 : v; // clamp
+         q = stb__Mul8Bit(v, quant_mult); // quantize
+         dq = (q * dequant_mults[i]) >> 4; // dequantize
+
+         if ((j % 16) == 0) printf("  "); // 2 spaces, third is done below
+         printf(" %3d,", dq);
+         if ((j % 16) == 15) printf("\n");
+      }
+      printf("};\n");
+   }
+
+   // optimal endpoint tables
+   for (i = 0; i < 2; ++i) {
+      int dequant = dequant_mults[i];
+      int size = i ? 64 : 32;
+      printf("static const unsigned char %s[256][2] = {\n", omatch_names[i]);
+      for (int j = 0; j < 256; ++j) {
+         int mn, mx;
+         int best_mn = 0, best_mx = 0;
+         int best_err = 256;
+         for (mn=0;mn<size;mn++) {
+            for (mx=0;mx<size;mx++) {
+               int mine = (mn * dequant) >> 4;
+               int maxe = (mx * dequant) >> 4;
+               int err = abs(stb__Lerp13(maxe, mine) - j);
+
+               // DX10 spec says that interpolation must be within 3% of "correct" result,
+               // add this as error term. Normally we'd expect a random distribution of
+               // +-1.5% error, but nowhere in the spec does it say that the error has to be
+               // unbiased - better safe than sorry.
+               err += abs(maxe - mine) * 3 / 100;
+
+               if(err < best_err) {
+                  best_mn = mn;
+                  best_mx = mx;
+                  best_err = err;
+               }
+            }
+         }
+         if ((j % 8) == 0) printf("  "); // 2 spaces, third is done below
+         printf(" { %2d, %2d },", best_mx, best_mn);
+         if ((j % 8) == 7) printf("\n");
+      }
+      printf("};\n");
+   }
+
+   return 0;
+}
+#endif
+
 /*
 /*
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 This software is available under 2 licenses -- choose whichever you prefer.
 This software is available under 2 licenses -- choose whichever you prefer.