OSDN Git Service

add a new mode REFINE_LOOP
authorRudolf Polzer <divverent@xonotic.org>
Fri, 15 Jul 2011 09:49:43 +0000 (11:49 +0200)
committerRudolf Polzer <divverent@xonotic.org>
Fri, 15 Jul 2011 09:49:43 +0000 (11:49 +0200)
README.txt
s2tc_compressor.cpp
s2tc_compressor.h
s2tc_libtxc_dxtn.cpp

index 4b14e9e..9617d7f 100644 (file)
@@ -22,3 +22,6 @@ ALWAYS:       always run color refinement (i.e. replace the colors by possibly better
        colors by averaging the original colors for the encoded pixels)
 CHECK: always run color refinement, but only use its result if it is actually
        a closer match for the block
+LOOP:  always run color refinement, but only use its result if it is actually
+       a closer match for the block; after refining, reassign colors and refine
+       till no change for the better happened
index 53163f4..dedca69 100644 (file)
@@ -495,124 +495,102 @@ namespace
                        }
                }
 
-               int nc0 = 0, na0 = 0, sc0r = 0, sc0g = 0, sc0b = 0, sa0 = 0;
-               int nc1 = 0, na1 = 0, sc1r = 0, sc1g = 0, sc1b = 0, sa1 = 0;
+               bool refined;
+               do
+               {
+                       int nc0 = 0, na0 = 0, sc0r = 0, sc0g = 0, sc0b = 0, sa0 = 0;
+                       int nc1 = 0, na1 = 0, sc1r = 0, sc1g = 0, sc1b = 0, sa1 = 0;
+                       if(refine == REFINE_LOOP)
+                               refined = false;
 
-               memset(out, 0, (dxt == DXT1) ? 8 : 16);
-               for(x = 0; x < w; ++x)
-                       for(y = 0; y < h; ++y)
-                       {
-                               int pindex = (x+y*4);
-                               c[2].r = rgba[(x + y * iw) * 4 + 2];
-                               c[2].g = rgba[(x + y * iw) * 4 + 1];
-                               c[2].b = rgba[(x + y * iw) * 4 + 0];
-                               ca[2]  = rgba[(x + y * iw) * 4 + 3];
-                               switch(dxt)
+                       memset(out, 0, (dxt == DXT1) ? 8 : 16);
+                       for(x = 0; x < w; ++x)
+                               for(y = 0; y < h; ++y)
                                {
-                                       case DXT5:
-                                               {
-                                                       int da[4];
-                                                       int bitindex = pindex * 3;
-                                                       da[0] = alpha_dist(ca[0], ca[2]);
-                                                       da[1] = alpha_dist(ca[1], ca[2]);
-                                                       da[2] = alpha_dist(0, ca[2]);
-                                                       da[3] = alpha_dist(255, ca[2]);
-                                                       if(da[2] <= da[0] && da[2] <= da[1] && da[2] <= da[3])
-                                                       {
-                                                               // 6
-                                                               ++bitindex;
-                                                               out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
-                                                               ++bitindex;
-                                                               out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
-                                                       }
-                                                       else if(da[3] <= da[0] && da[3] <= da[1])
+                                       int pindex = (x+y*4);
+                                       c[2].r = rgba[(x + y * iw) * 4 + 2];
+                                       c[2].g = rgba[(x + y * iw) * 4 + 1];
+                                       c[2].b = rgba[(x + y * iw) * 4 + 0];
+                                       ca[2]  = rgba[(x + y * iw) * 4 + 3];
+                                       switch(dxt)
+                                       {
+                                               case DXT5:
                                                        {
-                                                               // 7
-                                                               out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
-                                                               ++bitindex;
-                                                               out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
-                                                               ++bitindex;
-                                                               out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                               int da[4];
+                                                               int bitindex = pindex * 3;
+                                                               da[0] = alpha_dist(ca[0], ca[2]);
+                                                               da[1] = alpha_dist(ca[1], ca[2]);
+                                                               da[2] = alpha_dist(0, ca[2]);
+                                                               da[3] = alpha_dist(255, ca[2]);
+                                                               if(da[2] <= da[0] && da[2] <= da[1] && da[2] <= da[3])
+                                                               {
+                                                                       // 6
+                                                                       ++bitindex;
+                                                                       out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                                       ++bitindex;
+                                                                       out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                               }
+                                                               else if(da[3] <= da[0] && da[3] <= da[1])
+                                                               {
+                                                                       // 7
+                                                                       out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                                       ++bitindex;
+                                                                       out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                                       ++bitindex;
+                                                                       out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                               }
+                                                               else if(da[0] <= da[1])
+                                                               {
+                                                                       // 0
+                                                                       if(refine != REFINE_NEVER)
+                                                                       {
+                                                                               ++na0;
+                                                                               sa0 += ca[2];
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       // 1
+                                                                       out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
+                                                                       if(refine != REFINE_NEVER)
+                                                                       {
+                                                                               ++na1;
+                                                                               sa1 += ca[2];
+                                                                       }
+                                                               }
                                                        }
-                                                       else if(da[0] <= da[1])
+                                                       if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
                                                        {
-                                                               // 0
+                                                               int bitindex = pindex * 2;
+                                                               out[bitindex / 8 + 12] |= (1 << (bitindex % 8));
                                                                if(refine != REFINE_NEVER)
                                                                {
-                                                                       ++na0;
-                                                                       sa0 += ca[2];
+                                                                       ++nc1;
+                                                                       sc1r += refine_component_encode<ColorDist>(c[2].r);
+                                                                       sc1g += refine_component_encode<ColorDist>(c[2].g);
+                                                                       sc1b += refine_component_encode<ColorDist>(c[2].b);
                                                                }
                                                        }
                                                        else
                                                        {
-                                                               // 1
-                                                               out[bitindex / 8 + 2] |= (1 << (bitindex % 8));
                                                                if(refine != REFINE_NEVER)
                                                                {
-                                                                       ++na1;
-                                                                       sa1 += ca[2];
+                                                                       ++nc0;
+                                                                       sc0r += refine_component_encode<ColorDist>(c[2].r);
+                                                                       sc0g += refine_component_encode<ColorDist>(c[2].g);
+                                                                       sc0b += refine_component_encode<ColorDist>(c[2].b);
                                                                }
                                                        }
-                                               }
-                                               if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
-                                               {
-                                                       int bitindex = pindex * 2;
-                                                       out[bitindex / 8 + 12] |= (1 << (bitindex % 8));
-                                                       if(refine != REFINE_NEVER)
-                                                       {
-                                                               ++nc1;
-                                                               sc1r += refine_component_encode<ColorDist>(c[2].r);
-                                                               sc1g += refine_component_encode<ColorDist>(c[2].g);
-                                                               sc1b += refine_component_encode<ColorDist>(c[2].b);
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       if(refine != REFINE_NEVER)
-                                                       {
-                                                               ++nc0;
-                                                               sc0r += refine_component_encode<ColorDist>(c[2].r);
-                                                               sc0g += refine_component_encode<ColorDist>(c[2].g);
-                                                               sc0b += refine_component_encode<ColorDist>(c[2].b);
-                                                       }
-                                               }
-                                               break;
-                                       case DXT3:
-                                               {
-                                                       int bitindex = pindex * 4;
-                                                       out[bitindex / 8 + 0] |= (ca[2] << (bitindex % 8));
-                                               }
-                                               if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
-                                               {
-                                                       int bitindex = pindex * 2;
-                                                       out[bitindex / 8 + 12] |= (1 << (bitindex % 8));
-                                                       if(refine != REFINE_NEVER)
-                                                       {
-                                                               ++nc1;
-                                                               sc1r += refine_component_encode<ColorDist>(c[2].r);
-                                                               sc1g += refine_component_encode<ColorDist>(c[2].g);
-                                                               sc1b += refine_component_encode<ColorDist>(c[2].b);
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       if(refine != REFINE_NEVER)
+                                                       break;
+                                               case DXT3:
                                                        {
-                                                               ++nc0;
-                                                               sc0r += refine_component_encode<ColorDist>(c[2].r);
-                                                               sc0g += refine_component_encode<ColorDist>(c[2].g);
-                                                               sc0b += refine_component_encode<ColorDist>(c[2].b);
+                                                               int bitindex = pindex * 4;
+                                                               out[bitindex / 8 + 0] |= (ca[2] << (bitindex % 8));
                                                        }
-                                               }
-                                               break;
-                                       case DXT1:
-                                               {
-                                                       int bitindex = pindex * 2;
-                                                       if(!ca[2])
-                                                               out[bitindex / 8 + 4] |= (3 << (bitindex % 8));
-                                                       else if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
+                                                       if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
                                                        {
-                                                               out[bitindex / 8 + 4] |= (1 << (bitindex % 8));
+                                                               int bitindex = pindex * 2;
+                                                               out[bitindex / 8 + 12] |= (1 << (bitindex % 8));
                                                                if(refine != REFINE_NEVER)
                                                                {
                                                                        ++nc1;
@@ -631,123 +609,150 @@ namespace
                                                                        sc0b += refine_component_encode<ColorDist>(c[2].b);
                                                                }
                                                        }
-                                               }
-                                               break;
+                                                       break;
+                                               case DXT1:
+                                                       {
+                                                               int bitindex = pindex * 2;
+                                                               if(!ca[2])
+                                                                       out[bitindex / 8 + 4] |= (3 << (bitindex % 8));
+                                                               else if(ColorDist(c[0], c[2]) > ColorDist(c[1], c[2]))
+                                                               {
+                                                                       out[bitindex / 8 + 4] |= (1 << (bitindex % 8));
+                                                                       if(refine != REFINE_NEVER)
+                                                                       {
+                                                                               ++nc1;
+                                                                               sc1r += refine_component_encode<ColorDist>(c[2].r);
+                                                                               sc1g += refine_component_encode<ColorDist>(c[2].g);
+                                                                               sc1b += refine_component_encode<ColorDist>(c[2].b);
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       if(refine != REFINE_NEVER)
+                                                                       {
+                                                                               ++nc0;
+                                                                               sc0r += refine_component_encode<ColorDist>(c[2].r);
+                                                                               sc0g += refine_component_encode<ColorDist>(c[2].g);
+                                                                               sc0b += refine_component_encode<ColorDist>(c[2].b);
+                                                                       }
+                                                               }
+                                                       }
+                                                       break;
+                                       }
                                }
-                       }
-               if(refine != REFINE_NEVER)
-               {
-                       // REFINEMENT: trick from libtxc_dxtn: reassign the colors to an average of the colors encoded with that value
-
-                       if(dxt == DXT5)
+                       if(refine != REFINE_NEVER)
                        {
-                               if(refine == REFINE_CHECK)
+                               // REFINEMENT: trick from libtxc_dxtn: reassign the colors to an average of the colors encoded with that value
+
+                               if(dxt == DXT5)
                                {
-                                       ca[2] = ca[0];
-                                       ca[3] = ca[1];
+                                       if(na0)
+                                               ca[0] = (2 * sa0 + na0) / (2 * na0);
+                                       if(na1)
+                                               ca[1] = (2 * sa1 + na1) / (2 * na1);
+                               }
+                               if(refine == REFINE_CHECK || refine == REFINE_LOOP)
+                               {
+                                       c[2] = c[0];
+                                       c[3] = c[1];
+                               }
+                               if(nc0)
+                               {
+                                       c[0].r = refine_component_decode<ColorDist>((2 * sc0r + nc0) / (2 * nc0));
+                                       c[0].g = refine_component_decode<ColorDist>((2 * sc0g + nc0) / (2 * nc0));
+                                       c[0].b = refine_component_decode<ColorDist>((2 * sc0b + nc0) / (2 * nc0));
+                               }
+                               if(nc1)
+                               {
+                                       c[1].r = refine_component_decode<ColorDist>((2 * sc1r + nc1) / (2 * nc1));
+                                       c[1].g = refine_component_decode<ColorDist>((2 * sc1g + nc1) / (2 * nc1));
+                                       c[1].b = refine_component_decode<ColorDist>((2 * sc1b + nc1) / (2 * nc1));
                                }
-                               if(na0)
-                                       ca[0] = (2 * sa0 + na0) / (2 * na0);
-                               if(na1)
-                                       ca[1] = (2 * sa1 + na1) / (2 * na1);
-                       }
-                       if(refine == REFINE_CHECK)
-                       {
-                               c[2] = c[0];
-                               c[3] = c[1];
-                       }
-                       if(nc0)
-                       {
-                               c[0].r = refine_component_decode<ColorDist>((2 * sc0r + nc0) / (2 * nc0));
-                               c[0].g = refine_component_decode<ColorDist>((2 * sc0g + nc0) / (2 * nc0));
-                               c[0].b = refine_component_decode<ColorDist>((2 * sc0b + nc0) / (2 * nc0));
-                       }
-                       if(nc1)
-                       {
-                               c[1].r = refine_component_decode<ColorDist>((2 * sc1r + nc1) / (2 * nc1));
-                               c[1].g = refine_component_decode<ColorDist>((2 * sc1g + nc1) / (2 * nc1));
-                               c[1].b = refine_component_decode<ColorDist>((2 * sc1b + nc1) / (2 * nc1));
-                       }
 
-                       if(refine == REFINE_CHECK)
-                       {
-                               int score_01 = 0;
-                               int score_23 = 0;
-                               for(x = 0; x < w; ++x)
-                                       for(y = 0; y < h; ++y)
-                                       {
-                                               int pindex = (x+y*4);
-                                               c[4].r = rgba[(x + y * iw) * 4 + 2];
-                                               c[4].g = rgba[(x + y * iw) * 4 + 1];
-                                               c[4].b = rgba[(x + y * iw) * 4 + 0];
-                                               ca[4]  = rgba[(x + y * iw) * 4 + 3];
-                                               if(dxt == DXT1 && !ca[4])
-                                                       continue;
-                                               int bitindex = pindex * 2;
-                                               if(out[bitindex / 8 + (dxt == DXT1 ? 4 : 12)] & (1 << (bitindex % 8)))
-                                               {
-                                                       // we picked an 1
-                                                       score_01 += ColorDist(c[1], c[4]);
-                                                       score_23 += ColorDist(c[3], c[4]);
-                                               }
-                                               else
+                               if(refine == REFINE_CHECK || refine == REFINE_LOOP)
+                               {
+                                       int score_01 = 0;
+                                       int score_23 = 0;
+                                       for(x = 0; x < w; ++x)
+                                               for(y = 0; y < h; ++y)
                                                {
-                                                       // we picked a 0
-                                                       score_01 += ColorDist(c[0], c[4]);
-                                                       score_23 += ColorDist(c[2], c[4]);
+                                                       int pindex = (x+y*4);
+                                                       c[4].r = rgba[(x + y * iw) * 4 + 2];
+                                                       c[4].g = rgba[(x + y * iw) * 4 + 1];
+                                                       c[4].b = rgba[(x + y * iw) * 4 + 0];
+                                                       ca[4]  = rgba[(x + y * iw) * 4 + 3];
+                                                       if(dxt == DXT1 && !ca[4])
+                                                               continue;
+                                                       int bitindex = pindex * 2;
+                                                       if(out[bitindex / 8 + (dxt == DXT1 ? 4 : 12)] & (1 << (bitindex % 8)))
+                                                       {
+                                                               // we picked an 1
+                                                               score_01 += ColorDist(c[1], c[4]);
+                                                               score_23 += ColorDist(c[3], c[4]);
+                                                       }
+                                                       else
+                                                       {
+                                                               // we picked a 0
+                                                               score_01 += ColorDist(c[0], c[4]);
+                                                               score_23 += ColorDist(c[2], c[4]);
+                                                       }
                                                }
+
+                                       if(score_23 <= score_01)
+                                       {
+                                               // refinement was BAD
+                                               c[0] = c[2];
+                                               c[1] = c[3];
                                        }
+                                       else if(refine == REFINE_LOOP)
+                                               refined = true;
 
-                               if(score_23 < score_01)
-                               {
-                                       // refinement was BAD
-                                       c[0] = c[2];
-                                       c[1] = c[3];
+                                       // alpha refinement is always good and doesn't
+                                       // need to be checked because alpha is linear
                                }
 
-                               // alpha refinement is always good and doesn't
-                               // need to be checked because alpha is linear
-                       }
-
-                       if(dxt == DXT5)
-                       {
-                               if(ca[1] < ca[0])
+                               if(dxt == DXT5)
                                {
-                                       ca[2] = ca[0];
-                                       ca[0] = ca[1];
-                                       ca[1] = ca[2];
-                                       // swap the alphas
-                                       for(int pindex = 0; pindex < 16; ++pindex)
+                                       if(ca[1] < ca[0])
                                        {
-                                               int bitindex_set = pindex * 3;
-                                               int bitindex_test = bitindex_set + 2;
-                                               if(!(out[bitindex_test / 8] & (1 << (bitindex_test % 8))))
-                                                       out[bitindex_set / 8] ^= (1 << (bitindex_set % 8));
+                                               ca[2] = ca[0];
+                                               ca[0] = ca[1];
+                                               ca[1] = ca[2];
+                                               // swap the alphas
+                                               for(int pindex = 0; pindex < 16; ++pindex)
+                                               {
+                                                       int bitindex_set = pindex * 3;
+                                                       int bitindex_test = bitindex_set + 2;
+                                                       if(!(out[bitindex_test / 8] & (1 << (bitindex_test % 8))))
+                                                               out[bitindex_set / 8] ^= (1 << (bitindex_set % 8));
+                                               }
                                        }
                                }
-                       }
-                       if(c[1] < c[0])
-                       {
-                               c[2] = c[0];
-                               c[0] = c[1];
-                               c[1] = c[2];
-                               // swap the colors
-                               if(dxt == DXT1)
+                               if(c[1] < c[0])
                                {
-                                       out[4] ^= 0x55 & ~(out[4] >> 1);
-                                       out[5] ^= 0x55 & ~(out[5] >> 1);
-                                       out[6] ^= 0x55 & ~(out[6] >> 1);
-                                       out[7] ^= 0x55 & ~(out[7] >> 1);
-                               }
-                               else
-                               {
-                                       out[12] ^= 0x55 & ~(out[12] >> 1);
-                                       out[13] ^= 0x55 & ~(out[13] >> 1);
-                                       out[14] ^= 0x55 & ~(out[14] >> 1);
-                                       out[15] ^= 0x55 & ~(out[15] >> 1);
+                                       c[2] = c[0];
+                                       c[0] = c[1];
+                                       c[1] = c[2];
+                                       // swap the colors
+                                       if(dxt == DXT1)
+                                       {
+                                               out[4] ^= 0x55 & ~(out[4] >> 1);
+                                               out[5] ^= 0x55 & ~(out[5] >> 1);
+                                               out[6] ^= 0x55 & ~(out[6] >> 1);
+                                               out[7] ^= 0x55 & ~(out[7] >> 1);
+                                       }
+                                       else
+                                       {
+                                               out[12] ^= 0x55 & ~(out[12] >> 1);
+                                               out[13] ^= 0x55 & ~(out[13] >> 1);
+                                               out[14] ^= 0x55 & ~(out[14] >> 1);
+                                               out[15] ^= 0x55 & ~(out[15] >> 1);
+                                       }
                                }
                        }
                }
+               while(refine == REFINE_LOOP && refined);
+
                switch(dxt)
                {
                        case DXT5:
@@ -780,6 +785,10 @@ namespace
                                // these color dist functions do not need the refinement check, as they always improve the situation
                                if(ColorDist != color_dist_avg && ColorDist != color_dist_wavg)
                                        return s2tc_encode_block<dxt, ColorDist, mode, REFINE_CHECK>;
+                       case REFINE_LOOP:
+                               // these color dist functions do not need the refinement check, as they always improve the situation
+                               if(ColorDist != color_dist_avg && ColorDist != color_dist_wavg)
+                                       return s2tc_encode_block<dxt, ColorDist, mode, REFINE_CHECK>;
                        default:
                        case REFINE_ALWAYS:
                                return s2tc_encode_block<dxt, ColorDist, mode, REFINE_ALWAYS>;
index a3ed750..23beb93 100644 (file)
@@ -19,7 +19,8 @@ enum RefinementMode
 {
        REFINE_NEVER,
        REFINE_ALWAYS,
-       REFINE_CHECK
+       REFINE_CHECK,
+       REFINE_LOOP
 };
 
 typedef enum
index 138a31e..f81229c 100644 (file)
@@ -191,6 +191,8 @@ void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
                                refine = REFINE_ALWAYS;
                        else if(!strcasecmp(v, "CHECK"))
                                refine = REFINE_CHECK;
+                       else if(!strcasecmp(v, "LOOP"))
+                               refine = REFINE_LOOP;
                        else
                                fprintf(stderr, "Invalid refinement mode: %s\n", v);
                }