[gimp-dds] / tags / release-2.0.4 / dxt.c Repository:
ViewVC logotype

View of /tags/release-2.0.4/dxt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 106 - (download) (as text) (annotate)
Thu May 8 01:29:25 2008 UTC (18 months, 2 weeks ago) by cocidius
File size: 35157 byte(s)
Release 2.0.4 tag
    1 /*
    2    DDS GIMP plugin
    3 
    4    Copyright (C) 2004-2008 Shawn Kirst <skirst@insightbb.com>,
    5    with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
    6 
    7    This program is free software; you can redistribute it and/or
    8    modify it under the terms of the GNU General Public
    9    License as published by the Free Software Foundation; either
   10    version 2 of the License, or (at your option) any later version.
   11 
   12    This program is distributed in the hope that it will be useful,
   13    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15    General Public License for more details.
   16 
   17    You should have received a copy of the GNU General Public License
   18    along with this program; see the file COPYING.  If not, write to
   19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   20    Boston, MA 02111-1307, USA.
   21 */
   22 
   23 /*
   24  * Parts of this code have been generously released in the public domain
   25  * by Fabian 'ryg' Giesen.  The original code can be found (at the time
   26  * of writing) here:  http://mollyrocket.com/forums/viewtopic.php?t=392
   27  *
   28  * For more information about this code, see the README.dxt file that
   29  * came with the source.
   30  */
   31 
   32 #include <stdlib.h>
   33 #include <string.h>
   34 #include <math.h>
   35 #include <glib.h>
   36 
   37 #include "dds.h"
   38 #include "endian.h"
   39 #include "mipmap.h"
   40 #include "imath.h"
   41 
   42 #include "dxt_tables.h"
   43 
   44 #ifndef MIN
   45 #define MIN(a, b)  ((a) < (b) ? (a) : (b))
   46 #endif
   47 #ifndef MAX
   48 #define MAX(a, b)  ((a) > (b) ? (a) : (b))
   49 #endif
   50 
   51 /* extract 4x4 BGRA block */
   52 static void extract_block(const unsigned char *src, int w,
   53                           unsigned char *block)
   54 {
   55    int i;
   56    for(i = 0; i < 4; ++i)
   57    {
   58       memcpy(&block[i * 4 * 4], src, 4 * 4);
   59       src += w * 4;
   60    }
   61 }
   62 
   63 /* pack BGR8 to RGB565 */
   64 static inline unsigned short pack_rgb565(const unsigned char *c)
   65 {
   66    return(((c[2] >> 3) << 11) | ((c[1] >> 2) << 5) | (c[0] >> 3));
   67 }
   68 
   69 /* unpack RGB565 to BGR */
   70 static void unpack_rgb565(unsigned char *dst, unsigned short v)
   71 {
   72    int r = (v >> 11) & 0x1f;
   73    int g = (v >>  5) & 0x3f;
   74    int b = (v      ) & 0x1f;
   75 
   76    dst[0] = (b << 3) | (b >> 2);
   77    dst[1] = (g << 2) | (g >> 4);
   78    dst[2] = (r << 3) | (r >> 2);
   79 }
   80 
   81 static void lerp_rgb(unsigned char *dst, unsigned char *a, unsigned char *b, int f)
   82 {
   83    dst[0] = blerp(a[0], b[0], f);
   84    dst[1] = blerp(a[1], b[1], f);
   85    dst[2] = blerp(a[2], b[2], f);
   86 }
   87 
   88 static int color_distance(const unsigned char *c0,
   89                           const unsigned char *c1)
   90 {
   91    return(((c0[0] - c1[0]) * (c0[0] - c1[0])) +
   92           ((c0[1] - c1[1]) * (c0[1] - c1[1])) +
   93           ((c0[2] - c1[2]) * (c0[2] - c1[2])));
   94 }
   95 
   96 static int luminance(const unsigned char *c)
   97 {
   98    return((c[2] * 54 + c[1] * 182 + c[0] * 20) >> 8);
   99 }
  100 
  101 /* Block dithering function.  Simply dithers a block to 565 RGB.
  102  * (Floyd-Steinberg)
  103  */
  104 static void dither_block(unsigned char *dst, const unsigned char *block)
  105 {
  106    int err[8], *ep1 = err, *ep2 = err + 4, *tmp;
  107    int c, y;
  108    unsigned char *bp, *dp;
  109    const unsigned char *quant;
  110 
  111    /* process channels seperately */
  112    for(c = 0; c < 3; ++c)
  113    {
  114       bp = (unsigned char *)block;
  115       dp = dst;
  116       quant = (c == 1) ? quantG + 8 : quantRB + 8;
  117 
  118       bp += c;
  119       dp += c;
  120 
  121       memset(err, 0, sizeof(err));
  122 
  123       for(y = 0; y < 4; ++y)
  124       {
  125          /* pixel 0 */
  126          dp[ 0] = quant[bp[ 0] + ((3 * ep2[1] + 5 * ep2[0]) >> 4)];
  127          ep1[0] = bp[ 0] - dp[ 0];
  128 
  129          /* pixel 1 */
  130          dp[ 4] = quant[bp[ 4] + ((7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]) >> 4)];
  131          ep1[1] = bp[ 4] - dp[ 4];
  132 
  133          /* pixel 2 */
  134          dp[ 8] = quant[bp[ 8] + ((7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]) >> 4)];
  135          ep1[2] = bp[ 8] - dp[ 8];
  136 
  137          /* pixel 3 */
  138          dp[12] = quant[bp[12] + ((7 * ep1[2] + 5 * ep2[3] + ep2[2]) >> 4)];
  139          ep1[3] = bp[12] - dp[12];
  140 
  141          /* advance to next line */
  142          tmp = ep1;
  143          ep1 = ep2;
  144          ep2 = tmp;
  145 
  146          bp += 16;
  147          dp += 16;
  148       }
  149    }
  150 }
  151 
  152 /* Color matching function */
  153 static unsigned int match_colors_block(const unsigned char *block,
  154                                        unsigned char color[4][3],
  155                                        int dither)
  156 {
  157    unsigned int mask = 0;
  158    int dirb = color[0][0] - color[1][0];
  159    int dirg = color[0][1] - color[1][1];
  160    int dirr = color[0][2] - color[1][2];
  161    int dots[16], stops[4];
  162    int c0pt, halfpt, c3pt, dot;
  163    int i;
  164 
  165    for(i = 0; i < 16; ++i)
  166       dots[i] = block[4 * i] * dirb + block[4 * i + 1] * dirg + block[4 * i + 2] * dirr;
  167 
  168    for(i = 0; i < 4; ++i)
  169       stops[i] = color[i][0] * dirb + color[i][1] * dirg + color[i][2] * dirr;
  170 
  171    c0pt = (stops[1] + stops[3]) >> 1;
  172    halfpt = (stops[3] + stops[2]) >> 1;
  173    c3pt = (stops[2] + stops[0]) >> 1;
  174 
  175    if(!dither)
  176    {
  177       /* the version without dithering is straight-forward */
  178       for(i = 15; i >= 0; --i)
  179       {
  180          mask <<= 2;
  181          dot = dots[i];
  182 
  183          if(dot < halfpt)
  184             mask |= (dot < c0pt) ? 1 : 3;
  185          else
  186             mask |= (dot < c3pt) ? 2 : 0;
  187       }
  188    }
  189    else
  190    {
  191       /* with floyd-steinberg dithering (see above) */
  192       int err[8], *ep1 = err, *ep2 = err + 4, *tmp;
  193       int *dp = dots, y, lmask, step;
  194 
  195       c0pt <<= 4;
  196       halfpt <<= 4;
  197       c3pt <<= 4;
  198 
  199       memset(err, 0, sizeof(err));
  200 
  201       for(y = 0; y < 4; ++y)
  202       {
  203          /* pixel 0 */
  204          dot = (dp[0] << 4) + (3 * ep2[1] + 5 * ep2[0]);
  205          if(dot < halfpt)
  206             step = (dot < c0pt) ? 1 : 3;
  207          else
  208             step = (dot < c3pt) ? 2 : 0;
  209 
  210          ep1[0] = dp[0] - stops[step];
  211          lmask = step;
  212 
  213          /* pixel 1 */
  214          dot = (dp[1] << 4) + (7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]);
  215          if(dot < halfpt)
  216             step = (dot < c0pt) ? 1 : 3;
  217          else
  218             step = (dot < c3pt) ? 2 : 0;
  219 
  220          ep1[1] = dp[1] - stops[step];
  221          lmask |= step << 2;
  222 
  223          /* pixel 2 */
  224          dot = (dp[2] << 4) + (7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]);
  225          if(dot < halfpt)
  226             step = (dot < c0pt) ? 1 : 3;
  227          else
  228             step = (dot < c3pt) ? 2 : 0;
  229 
  230          ep1[2] = dp[2] - stops[step];
  231          lmask |= step << 4;
  232 
  233          /* pixel 3 */
  234          dot = (dp[3] << 4) + (7 * ep1[2] + 5 * ep2[3] + ep2[2]);
  235          if(dot < halfpt)
  236             step = (dot < c0pt) ? 1 : 3;
  237          else
  238             step = (dot < c3pt) ? 2 : 0;
  239 
  240          ep1[3] = dp[3] - stops[step];
  241          lmask |= step << 6;
  242 
  243          /* advance to next line */
  244          tmp = ep1;
  245          ep1 = ep2;
  246          ep2 = tmp;
  247 
  248          dp += 4;
  249          mask |= lmask << (y * 8);
  250       }
  251    }
  252 
  253    return(mask);
  254 }
  255 
  256 /* Special case color matching for DXT1 color blocks with non-opaque
  257  * alpha values.  Simple distance based color matching.  This is my
  258  * little hack, Fabian had no need for DXT1-alpha :)
  259  */
  260 static unsigned int match_colors_block_DXT1alpha(const unsigned char *block,
  261                                                  unsigned char color[4][3])
  262 {
  263    int i, d0, d1, d2, idx;
  264    unsigned int mask = 0;
  265 
  266    for(i = 15; i >= 0; --i)
  267    {
  268       mask <<= 2;
  269       d0 = color_distance(&block[4 * i], color[0]);
  270       d1 = color_distance(&block[4 * i], color[1]);
  271       d2 = color_distance(&block[4 * i], color[2]);
  272       if(block[4 * i + 3] < 128)
  273          idx = 3;
  274       else if(d0 < d1 && d0 < d2)
  275          idx = 0;
  276       else if(d1 < d2)
  277          idx = 1;
  278       else
  279          idx = 2;
  280       mask |= idx;
  281    }
  282 
  283    return(mask);
  284 }
  285 
  286 /* The color optimization function. (Clever code, part 1) */
  287 static void optimize_colors_block(const unsigned char *block,
  288                                   unsigned short *max16, unsigned short *min16)
  289 {
  290    static const int niterpow = 4;
  291 
  292    int mu[3], mn[3], mx[3];
  293    int i, c, r, g, b, dot, iter;
  294    int muv, mnv, mxv, mnd, mxd;
  295    int cov[6];
  296    unsigned char *bp, mnc[3], mxc[3];
  297    float covf[6], vfr, vfg, vfb, magn;
  298    float fr, fg, fb;
  299 
  300    /* determine color distribution */
  301    for(c = 0; c < 3; ++c)
  302    {
  303       bp = (unsigned char *)block + c;
  304 
  305       muv = mnv = mxv = bp[0];
  306       for(i = 4; i < 64; i += 4)
  307       {
  308          muv += bp[i];
  309          if(mnv > bp[i]) mnv = bp[i];
  310          if(mxv < bp[i]) mxv = bp[i];
  311       }
  312 
  313       mu[c] = (muv + 8) >> 4;
  314       mn[c] = mnv;
  315       mx[c] = mxv;
  316    }
  317 
  318    memset(cov, 0, sizeof(cov));
  319 
  320    /* determine covariance matrix */
  321    for(i = 0; i < 16; ++i)
  322    {
  323       b = block[4 * i + 0] - mu[0];
  324       g = block[4 * i + 1] - mu[1];
  325       r = block[4 * i + 2] - mu[2];
  326 
  327       cov[0] += r * r;
  328       cov[1] += r * g;
  329       cov[2] += r * b;
  330       cov[3] += g * g;
  331       cov[4] += g * b;
  332       cov[5] += b * b;
  333    }
  334 
  335    /* convert covariance matrix to float, find principal axis via power iter */
  336    for(i = 0; i < 6; ++i)
  337       covf[i] = cov[i] / 255.0f;
  338 
  339    vfb = mx[0] - mn[0];
  340    vfg = mx[1] - mn[1];
  341    vfr = mx[2] - mn[2];
  342 
  343    for(iter = 0; iter < niterpow; ++iter)
  344    {
  345       fr = vfr * covf[0] + vfg * covf[1] + vfb * covf[2];
  346       fg = vfr * covf[1] + vfg * covf[3] + vfb * covf[4];
  347       fb = vfr * covf[2] + vfg * covf[4] + vfb * covf[5];
  348 
  349       vfr = fr;
  350       vfg = fg;
  351       vfb = fb;
  352    }
  353 
  354    vfr = fabsf(vfr);
  355    vfg = fabsf(vfg);
  356    vfb = fabsf(vfb);
  357 
  358    magn = MAX(MAX(vfr, vfg), vfb);
  359 
  360    if(magn < 4.0) /* too small, default to luminance */
  361    {
  362       r = 148;
  363       g = 300;
  364       b = 58;
  365    }
  366    else
  367    {
  368       magn = 512.0f / magn;
  369       r = (int)(vfr * magn);
  370       g = (int)(vfg * magn);
  371       b = (int)(vfb * magn);
  372    }
  373 
  374    /* pick colors at extreme points */
  375    mnd =  0x7fffffff;
  376    mxd = -0x7fffffff;
  377 
  378    for(i = 0; i < 16; ++i)
  379    {
  380       dot = block[4 * i] * b + block[4 * i + 1] * g + block[4 * i + 2] * r;
  381 
  382       if(dot < mnd)
  383       {
  384          mnd = dot;
  385          memcpy(mnc, &block[4 * i], 3);
  386       }
  387       if(dot > mxd)
  388       {
  389          mxd = dot;
  390          memcpy(mxc, &block[4 * i], 3);
  391       }
  392    }
  393 
  394    /* reduce to 16-bit colors */
  395    *max16 = pack_rgb565(mxc);
  396    *min16 = pack_rgb565(mnc);
  397 }
  398 
  399 /* The refinement function (Clever code, part 2)
  400  * Tries to optimize colors to suit block contents better.
  401  * (By solving a least squares system via normal equations + Cramer's rule)
  402  */
  403 static int refine_block(const unsigned char *block,
  404                         unsigned short *max16, unsigned short *min16,
  405                         unsigned int mask)
  406 {
  407    static const int w1tab[4] = {3, 0, 2, 1};
  408    static const int prods[4] = {0x090000, 0x000900, 0x040102, 0x010402};
  409    /* ^ Some magic to save a lot of multiplies in the accumulating loop... */
  410 
  411    int akku = 0;
  412    int At1_r, At1_g, At1_b;
  413    int At2_r, At2_g, At2_b;
  414    unsigned int cm = mask;
  415    int i, step, w1, r, g, b;
  416    int xx, yy, xy;
  417    float frb, fg;
  418    unsigned short v, oldmin, oldmax;
  419    int s;
  420 
  421    oldmin = *min16;
  422    oldmax = *max16;
  423    if((mask ^ (mask << 2)) < 4) /* all pixels have the same index */
  424    {
  425       /* degenerate system, use optimal single-color match for average color */
  426       r = g = b = 8;
  427       for(i = 0; i < 16; ++i)
  428       {
  429          r += block[4 * i + 2];
  430          g += block[4 * i + 1];
  431          b += block[4 * i + 0];
  432       }
  433 
  434       r >>= 4;
  435       g >>= 4;
  436       b >>= 4;
  437 
  438       *max16 = (omatch5[r][0] << 11) | (omatch6[g][0] << 5) | omatch5[b][0];
  439       *min16 = (omatch5[r][1] << 11) | (omatch6[g][1] << 5) | omatch5[b][1];
  440       return(*min16 != oldmin || *max16 != oldmax);
  441    }
  442 
  443    At1_r = At1_g = At1_b = 0;
  444    At2_r = At2_g = At2_b = 0;
  445 
  446    for(i = 0; i < 16; ++i, cm >>= 2)
  447    {
  448       step = cm & 3;
  449       w1 = w1tab[step];
  450       r = block[4 * i + 2];
  451       g = block[4 * i + 1];
  452       b = block[4 * i + 0];
  453 
  454       akku  += prods[step];
  455       At1_r += w1 * r;
  456       At1_g += w1 * g;
  457       At1_b += w1 * b;
  458       At2_r += r;
  459       At2_g += g;
  460       At2_b += b;
  461    }
  462 
  463    At2_r = 3 * At2_r - At1_r;
  464    At2_g = 3 * At2_g - At1_g;
  465    At2_b = 3 * At2_b - At1_b;
  466 
  467    /* extract solutions and decide solvability */
  468    xx = akku >> 16;
  469    yy = (akku >> 8) & 0xff;
  470    xy = (akku >> 0) & 0xff;
  471 
  472    frb = 3.0f * 31.0f / 255.0f / (xx * yy - xy * xy);
  473    fg = frb * 63.0f / 31.0f;
  474 
  475    /* solve */
  476    s = (int)((At1_r * yy - At2_r * xy) * frb + 0.5f);
  477    if(s < 0) s = 0;
  478    if(s > 31) s = 31;
  479    v = s << 11;
  480    s = (int)((At1_g * yy - At2_g * xy) * fg + 0.5f);
  481    if(s < 0) s = 0;
  482    if(s > 63) s = 63;
  483    v |= s << 5;
  484    s = (int)((At1_b * yy - At2_b * xy) * frb + 0.5f);
  485    if(s < 0) s = 0;
  486    if(s > 31) s = 31;
  487    v |= s;
  488    *max16 = v;
  489 
  490    s = (int)((At2_r * xx - At1_r * xy) * frb + 0.5f);
  491    if(s < 0) s = 0;
  492    if(s > 31) s = 31;
  493    v = s << 11;
  494    s = (int)((At2_g * xx - At1_g * xy) * fg + 0.5f);
  495    if(s < 0) s = 0;
  496    if(s > 63) s = 63;
  497    v |= s << 5;
  498    s = (int)((At2_b * xx - At1_b * xy) * frb + 0.5f);
  499    if(s < 0) s = 0;
  500    if(s > 31) s = 31;
  501    v |= s;
  502    *min16 = v;
  503 
  504    return(oldmin != *min16 || oldmax != *max16);
  505 }
  506 
  507 /* Find min/max colors by distance */
  508 static void get_min_max_colors_distance(const unsigned char *block,
  509                                         unsigned short *max16,
  510                                         unsigned short *min16)
  511 {
  512    int i, j, dist, maxdist = -1;
  513    unsigned short c0 = 0, c1 = 0;
  514 
  515    for(i = 0; i < 64 - 4; i += 4)
  516    {
  517       for(j = i + 4; j < 64; j += 4)
  518       {
  519          dist = color_distance(&block[i], &block[j]);
  520          if(dist > maxdist)
  521          {
  522             maxdist = dist;
  523             c0 = pack_rgb565(block + i);
  524             c1 = pack_rgb565(block + j);
  525          }
  526       }
  527    }
  528 
  529    *max16 = MAX(c0, c1);
  530    *min16 = MIN(c0, c1);
  531 }
  532 
  533 /* Find min-max colors by luminance */
  534 static void get_min_max_colors_luminance(const unsigned char *block,
  535                                          unsigned short *max16,
  536                                          unsigned short *min16)
  537 {
  538    int i, lum, minlum = 0x7fffffff, maxlum = -0x7fffffff;
  539    unsigned char mn[3], mx[3];
  540 
  541    for(i = 0; i < 16; ++i)
  542    {
  543       lum = luminance(&block[4 * i]);
  544       if(lum > maxlum)
  545       {
  546          maxlum = lum;
  547          memcpy(mx, &block[4 * i], 3);
  548       }
  549       if(lum < minlum)
  550       {
  551          minlum = lum;
  552          memcpy(mn, &block[4 * i], 3);
  553       }
  554    }
  555 
  556    *max16 = pack_rgb565(mx);
  557    *min16 = pack_rgb565(mn);
  558 }
  559 
  560 #define INSET_SHIFT  4
  561 
  562 /* Find min-max colors using the inset bounding box method */
  563 static void get_min_max_colors_inset_bbox(const unsigned char *block,
  564                                           unsigned short *max16,
  565                                           unsigned short *min16)
  566 {
  567    int i;
  568    unsigned char inset[3], mx[3], mn[3];
  569 
  570    mn[0] = mn[1] = mn[2] = 255;
  571    mx[0] = mx[1] = mx[2] = 0;
  572 
  573    for(i = 0; i < 16; ++i)
  574    {
  575       if(block[4 * i + 0] < mn[0]) mn[0] = block[4 * i + 0];
  576       if(block[4 * i + 1] < mn[1]) mn[1] = block[4 * i + 1];
  577       if(block[4 * i + 2] < mn[2]) mn[2] = block[4 * i + 2];
  578       if(block[4 * i + 0] > mx[0]) mx[0] = block[4 * i + 0];
  579       if(block[4 * i + 1] > mx[1]) mx[1] = block[4 * i + 1];
  580       if(block[4 * i + 2] > mx[2]) mx[2] = block[4 * i + 2];
  581    }
  582 
  583    inset[0] = (mx[0] - mn[0]) >> INSET_SHIFT;
  584    inset[1] = (mx[1] - mn[1]) >> INSET_SHIFT;
  585    inset[2] = (mx[2] - mn[2]) >> INSET_SHIFT;
  586 
  587    mn[0] = (mn[0] + inset[0] <= 255) ? mn[0] + inset[0] : 255;
  588    mn[1] = (mn[1] + inset[1] <= 255) ? mn[1] + inset[1] : 255;
  589    mn[2] = (mn[2] + inset[2] <= 255) ? mn[2] + inset[2] : 255;
  590 
  591    mx[0] = (mx[0] >= inset[0]) ? mx[0] - inset[0] : 0;
  592    mx[1] = (mx[1] >= inset[1]) ? mx[1] - inset[1] : 0;
  593    mx[2] = (mx[2] >= inset[2]) ? mx[2] - inset[2] : 0;
  594 
  595    *min16 = pack_rgb565(mn);
  596    *max16 = pack_rgb565(mx);
  597 }
  598 
  599 static void get_min_max_YCoCg(const unsigned char *block,
  600                               unsigned char *mincolor, unsigned char *maxcolor)
  601 {
  602    int i;
  603 
  604    mincolor[2] = mincolor[1] = 255;
  605    maxcolor[2] = maxcolor[1] = 0;
  606 
  607    for(i = 0; i < 16; ++i)
  608    {
  609       if(block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2];
  610       if(block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1];
  611       if(block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2];
  612       if(block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1];
  613    }
  614 }
  615 
  616 static void scale_YCoCg(unsigned char *block,
  617                         unsigned char *mincolor, unsigned char *maxcolor)
  618 {
  619    const int s0 = 128 / 2 - 1;
  620    const int s1 = 128 / 4 - 1;
  621    int m0, m1, m2, m3;
  622    int mask0, mask1, scale;
  623    int i;
  624 
  625    m0 = abs(mincolor[2] - 128);
  626    m1 = abs(mincolor[1] - 128);
  627    m2 = abs(maxcolor[2] - 128);
  628    m3 = abs(maxcolor[1] - 128);
  629 
  630    if(m1 > m0) m0 = m1;
  631    if(m3 > m2) m2 = m3;
  632    if(m2 > m0) m0 = m2;
  633 
  634    mask0 = -(m0 <= s0);
  635    mask1 = -(m0 <= s1);
  636    scale = 1 + (1 & mask0) + (2 & mask1);
  637 
  638    mincolor[2] = (mincolor[2] - 128) * scale + 128;
  639    mincolor[1] = (mincolor[1] - 128) * scale + 128;
  640    mincolor[0] = (scale - 1) << 3;
  641 
  642    maxcolor[2] = (maxcolor[2] - 128) * scale + 128;
  643    maxcolor[1] = (maxcolor[1] - 128) * scale + 128;
  644    maxcolor[0] = (scale - 1) << 3;
  645 
  646    for(i = 0; i < 16; ++i)
  647    {
  648       block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128;
  649       block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128;
  650    }
  651 }
  652 
  653 static void inset_bbox_YCoCg(unsigned char *mincolor, unsigned char *maxcolor)
  654 {
  655    int inset[4], mini[4], maxi[4];
  656 
  657    inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1);
  658    inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1);
  659 
  660    mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT;
  661    mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT;
  662 
  663    maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT;
  664    maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT;
  665 
  666    mini[2] = (mini[2] >= 0) ? mini[2] : 0;
  667    mini[1] = (mini[1] >= 0) ? mini[1] : 0;
  668 
  669    maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255;
  670    maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255;
  671 
  672    mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5);
  673    mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6);
  674 
  675    maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5);
  676    maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6);
  677 }
  678 
  679 static void select_diagonal_YCoCg(const unsigned char *block,
  680                                   unsigned char *mincolor,
  681                                   unsigned char *maxcolor)
  682 {
  683    unsigned char mid0, mid1, side, mask, b0, b1, c0, c1;
  684    int i;
  685 
  686    mid0 = ((int)mincolor[2] + maxcolor[2] + 1) >> 1;
  687    mid1 = ((int)mincolor[1] + maxcolor[1] + 1) >> 1;
  688 
  689    side = 0;
  690    for(i = 0; i < 16; ++i)
  691    {
  692       b0 = block[i * 4 + 2] >= mid0;
  693       b1 = block[i * 4 + 1] >= mid1;
  694       side += (b0 ^ b1);
  695    }
  696 
  697    mask = -(side > 8);
  698    mask &= -(mincolor[2] != maxcolor[2]);
  699 
  700    c0 = mincolor[1];
  701    c1 = maxcolor[1];
  702 
  703    c0 ^= c1;
  704    mask &= c0;
  705    c1 ^= mask;
  706    c0 ^= c1;
  707 
  708    mincolor[1] = c0;
  709    maxcolor[1] = c1;
  710 }
  711 
  712 static void eval_colors(unsigned char color[4][3],
  713                         unsigned short c0, unsigned short c1)
  714 {
  715    unpack_rgb565(color[0], c0);
  716    unpack_rgb565(color[1], c1);
  717    if(c0 > c1)
  718    {
  719       lerp_rgb(color[2], color[0], color[1], 0x55);
  720       lerp_rgb(color[3], color[0], color[1], 0xaa);
  721    }
  722    else
  723    {
  724       color[2][0] = (color[0][0] + color[1][0]) >> 1;
  725       color[2][1] = (color[0][1] + color[1][1]) >> 1;
  726       color[2][2] = (color[0][2] + color[1][2]) >> 1;
  727 
  728       color[3][0] = color[3][1] = color[3][2] = 0;
  729    }
  730 }
  731 
  732 static void encode_color_block(unsigned char *dst,
  733                                const unsigned char *block,
  734                                int type, int dither, int dxt1_alpha)
  735 {
  736    unsigned char dblock[64], color[4][3];
  737    unsigned short min16, max16;
  738    unsigned int v, mn, mx, mask;
  739    int i, block_has_alpha = 0;
  740 
  741    /* find min/max colors, determine if alpha values present in block
  742     * (for DXT1-alpha)
  743     */
  744    mn = mx = GETL32(block);
  745    for(i = 0; i < 16; ++i)
  746    {
  747       block_has_alpha = block_has_alpha || (block[4 * i + 3] < 255);
  748       v = GETL32(&block[4 * i]);
  749       if(v > mx) mx = v;
  750       if(v < mn) mn = v;
  751    }
  752 
  753    if(mn != mx) /* block is not a solid color, continue with compression */
  754    {
  755       /* compute dithered block for PCA if desired */
  756       if(dither)
  757          dither_block(dblock, block);
  758 
  759       switch(type)
  760       {
  761          case DDS_COLOR_DISTANCE:
  762             get_min_max_colors_distance(dither ? dblock : block, &max16, &min16);
  763             break;
  764          case DDS_COLOR_LUMINANCE:
  765             get_min_max_colors_luminance(dither ? dblock : block, &max16, &min16);
  766             break;
  767          case DDS_COLOR_INSET_BBOX:
  768             get_min_max_colors_inset_bbox(dither ? dblock : block, &max16, &min16);
  769             break;
  770          default:
  771             /* pca + map along principal axis */
  772             optimize_colors_block(dither ? dblock : block, &max16, &min16);
  773             if(max16 != min16)
  774             {
  775                eval_colors(color, max16, min16);
  776                mask = match_colors_block(block, color, dither != 0);
  777             }
  778             else
  779                mask = 0;
  780 
  781             /* refine */
  782             refine_block(dither ? dblock : block, &max16, &min16, mask);
  783             break;
  784       }
  785 
  786       if(max16 != min16)
  787       {
  788          eval_colors(color, max16, min16);
  789          mask = match_colors_block(block, color, dither != 0);
  790       }
  791       else
  792          mask = 0;
  793    }
  794    else /* constant color */
  795    {
  796       mask = 0xaaaaaaaa;
  797       max16 = (omatch5[block[2]][0] << 11) |
  798               (omatch6[block[1]][0] <<  5) |
  799               (omatch5[block[0]][0]      );
  800       min16 = (omatch5[block[2]][1] << 11) |
  801               (omatch6[block[1]][1] <<  5) |
  802               (omatch5[block[0]][1]      );
  803    }
  804 
  805    /* HACK! for DXT1 blocks which have non-opaque pixels */
  806    if(dxt1_alpha && block_has_alpha)
  807    {
  808       if(max16 > min16)
  809       {
  810          max16 ^= min16; min16 ^= max16; max16 ^= min16;
  811       }
  812       eval_colors(color, max16, min16);
  813       mask = match_colors_block_DXT1alpha(block, color);
  814    }
  815 
  816    if(max16 < min16 && !(dxt1_alpha && block_has_alpha))
  817    {
  818       max16 ^= min16; min16 ^= max16; max16 ^= min16;
  819       mask ^= 0x55555555;
  820    }
  821 
  822    PUTL16(&dst[0], max16);
  823    PUTL16(&dst[2], min16);
  824    PUTL32(&dst[4], mask);
  825 }
  826 
  827 /* write DXT3 alpha block */
  828 static void encode_alpha_block_DXT3(unsigned char *dst,
  829                                     const unsigned char *block)
  830 {
  831    int i, a1, a2;
  832 
  833    block += 3;
  834 
  835    for(i = 0; i < 8; ++i)
  836    {
  837       a1 = block[8 * i + 0];
  838       a2 = block[8 * i + 4];
  839       *dst++ = ((a2 >> 4) << 4) | (a1 >> 4);
  840    }
  841 }
  842 
  843 /* Write DXT5 alpha block */
  844 static void encode_alpha_block_DXT5(unsigned char *dst,
  845                                     const unsigned char *block)
  846 {
  847    int i, v, mn, mx;
  848    int dist, bias, dist2, dist4, bits, mask;
  849    int a, idx, t;
  850 
  851    block += 3;
  852 
  853    /* find min/max alpha pair */
  854    mn = mx = block[0];
  855    for(i = 0; i < 16; ++i)
  856    {
  857       v = block[4 * i];
  858       if(v > mx) mx = v;
  859       if(v < mn) mn = v;
  860    }
  861 
  862    /* encode them */
  863    *dst++ = mx;
  864    *dst++ = mn;
  865 
  866    /* determine bias and emit indices */
  867    dist = mx - mn;
  868    bias = mn * 7 - (dist >> 1);
  869    dist4 = dist * 4;
  870    dist2 = dist * 2;
  871    bits = 0;
  872    mask = 0;
  873 
  874    for(i = 0; i < 16; ++i)
  875    {
  876       a = block[4 * i] * 7 - bias;
  877 
  878       /* select index (hooray for bit magic) */
  879       t = (dist4 - a) >> 31; idx =  t & 4; a -= dist4 & t;
  880       t = (dist2 - a) >> 31; idx += t & 2; a -= dist2 & t;
  881       t = (dist  - a) >> 31; idx += t & 1;
  882 
  883       idx = -idx & 7;
  884       idx ^= (2 > idx);
  885 
  886       /* write index */
  887       mask |= idx << bits;
  888       if((bits += 3) >= 8)
  889       {
  890          *dst++ = mask;
  891          mask >>= 8;
  892          bits -= 8;
  893       }
  894    }
  895 }
  896 
  897 static void compress_DXT1(unsigned char *dst, const unsigned char *src,
  898                           int w, int h, int type, int dither, int alpha)
  899 {
  900    unsigned char block[64];
  901    int x, y;
  902 
  903    for(y = 0; y < h; y += 4, src += w * 4 * 4)
  904    {
  905       for(x = 0; x < w; x += 4)
  906       {
  907          extract_block(src + x * 4, w, block);
  908          encode_color_block(dst, block, type, dither, alpha);
  909          dst += 8;
  910       }
  911    }
  912 }
  913 
  914 static void compress_DXT3(unsigned char *dst, const unsigned char *src,
  915                           int w, int h, int type, int dither)
  916 {
  917    unsigned char block[64];
  918    int x, y;
  919 
  920    for(y = 0; y < h; y += 4, src += w * 4 * 4)
  921    {
  922       for(x = 0; x < w; x += 4)
  923       {
  924          extract_block(src + x * 4, w, block);
  925          encode_alpha_block_DXT3(dst, block);
  926          encode_color_block(dst + 8, block, type, dither, 0);
  927          dst += 16;
  928       }
  929    }
  930 }
  931 
  932 static void compress_DXT5(unsigned char *dst, const unsigned char *src,
  933                           int w, int h, int type, int dither)
  934 {
  935    unsigned char block[64];
  936    int x, y;
  937 
  938    for(y = 0; y < h; y += 4, src += w * 4 * 4)
  939    {
  940       for(x = 0; x < w; x += 4)
  941       {
  942          extract_block(src + x * 4, w, block);
  943          encode_alpha_block_DXT5(dst, block);
  944          encode_color_block(dst + 8, block, type, dither, 0);
  945          dst += 16;
  946       }
  947    }
  948 }
  949 
  950 static void compress_BC4(unsigned char *dst, const unsigned char *src,
  951                          int w, int h)
  952 {
  953    unsigned char block[64];
  954    int x, y;
  955 
  956    for(y = 0; y < h; y += 4, src += w * 4 * 4)
  957    {
  958       for(x = 0; x < w; x += 4)
  959       {
  960          extract_block(src + x * 4, w, block);
  961          encode_alpha_block_DXT5(dst, block - 1);
  962          dst += 8;
  963       }
  964    }
  965 }
  966 
  967 static void compress_BC5(unsigned char *dst, const unsigned char *src,
  968                          int w, int h)
  969 {
  970    unsigned char block[64];
  971    int x, y;
  972 
  973    for(y = 0; y < h; y += 4, src += w * 4 * 4)
  974    {
  975       for(x = 0; x < w; x += 4)
  976       {
  977          extract_block(src + x * 4, w, block);
  978          encode_alpha_block_DXT5(dst, block - 2);
  979          encode_alpha_block_DXT5(dst + 8, block - 1);
  980          dst += 16;
  981       }
  982    }
  983 }
  984 
  985 static void compress_YCoCg(unsigned char *dst, const unsigned char *src,
  986                            int w, int h)
  987 {
  988    unsigned char block[64], colors[4][3];
  989    unsigned char *maxcolor, *mincolor;
  990    unsigned int mask;
  991    int c0, c1, d0, d1, d2, d3;
  992    int b0, b1, b2, b3, b4;
  993    int x0, x1, x2;
  994    int x, y, i;
  995 
  996    for(y = 0; y < h; y += 4, src += w * 4 * 4)
  997    {
  998       for(x = 0; x < w; x += 4)
  999       {
 1000          extract_block(src + x * 4, w, block);
 1001 
 1002          encode_alpha_block_DXT5(dst, block);
 1003 
 1004          maxcolor = &colors[0][0];
 1005          mincolor = &colors[1][0];
 1006 
 1007          get_min_max_YCoCg(block, mincolor, maxcolor);
 1008          scale_YCoCg(block, mincolor, maxcolor);
 1009          inset_bbox_YCoCg(mincolor, maxcolor);
 1010          select_diagonal_YCoCg(block, mincolor, maxcolor);
 1011 
 1012          lerp_rgb(&colors[2][0], maxcolor, mincolor, 0x55);
 1013          lerp_rgb(&colors[3][0], maxcolor, mincolor, 0xaa);
 1014 
 1015          mask = 0;
 1016 
 1017          for(i = 15; i >= 0; --i)
 1018          {
 1019             c0 = block[4 * i + 2];
 1020             c1 = block[4 * i + 1];
 1021 
 1022             d0 = abs(colors[0][2] - c0) + abs(colors[0][1] - c1);
 1023             d1 = abs(colors[1][2] - c0) + abs(colors[1][1] - c1);
 1024             d2 = abs(colors[2][2] - c0) + abs(colors[2][1] - c1);
 1025             d3 = abs(colors[3][2] - c0) + abs(colors[3][1] - c1);
 1026 
 1027             b0 = d0 > d3;
 1028             b1 = d1 > d2;
 1029             b2 = d0 > d2;
 1030             b3 = d1 > d3;
 1031             b4 = d2 > d3;
 1032 
 1033             x0 = b1 & b2;
 1034             x1 = b0 & b3;
 1035             x2 = b0 & b4;
 1036 
 1037             mask <<= 2;
 1038             mask |= (x1 | ((x0 | x1) << 1));
 1039          }
 1040 
 1041          PUTL16(&dst[ 8], pack_rgb565(maxcolor));
 1042          PUTL16(&dst[10], pack_rgb565(mincolor));
 1043          PUTL32(&dst[12], mask);
 1044 
 1045          dst += 16;
 1046       }
 1047    }
 1048 }
 1049 
 1050 int dxt_compress(unsigned char *dst, unsigned char *src, int format,
 1051                  unsigned int width, unsigned int height, int bpp,
 1052                  int mipmaps, int type, int dither, int filter)
 1053 {
 1054    int i, size, w, h;
 1055    unsigned int offset;
 1056    unsigned char *tmp;
 1057    int j;
 1058    unsigned char *tmp2, *s;
 1059    int dxt1_alpha = 0;
 1060 
 1061    if(!(IS_POT(width) && IS_POT(height)))
 1062       return(0);
 1063 
 1064    size = get_mipmapped_size(width, height, bpp, 0, mipmaps,
 1065                              DDS_COMPRESS_NONE);
 1066    tmp = g_malloc(size);
 1067    generate_mipmaps(tmp, src, width, height, bpp, 0, mipmaps, filter);
 1068 
 1069    if(bpp == 4 && format == DDS_COMPRESS_BC1)
 1070       dxt1_alpha = 1;
 1071 
 1072    if(bpp == 1)
 1073    {
 1074       /* grayscale promoted to BGRA */
 1075 
 1076       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
 1077                                 DDS_COMPRESS_NONE);
 1078       tmp2 = g_malloc(size);
 1079 
 1080       for(i = j = 0; j < size; ++i, j += 4)
 1081       {
 1082          tmp2[j + 0] = tmp[i];
 1083          tmp2[j + 1] = tmp[i];
 1084          tmp2[j + 2] = tmp[i];
 1085          tmp2[j + 3] = 255;
 1086       }
 1087 
 1088       g_free(tmp);
 1089       tmp = tmp2;
 1090       bpp = 4;
 1091    }
 1092    else if(bpp == 2)
 1093    {
 1094       /* gray-alpha promoted to BGRA */
 1095 
 1096       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
 1097                                 DDS_COMPRESS_NONE);
 1098       tmp2 = g_malloc(size);
 1099 
 1100       for(i = j = 0; j < size; i += 2, j += 4)
 1101       {
 1102          tmp2[j + 0] = tmp[i];
 1103          tmp2[j + 1] = tmp[i];
 1104          tmp2[j + 2] = tmp[i];
 1105          tmp2[j + 3] = tmp[i + 1];
 1106       }
 1107 
 1108       g_free(tmp);
 1109       tmp = tmp2;
 1110       bpp = 4;
 1111    }
 1112    else if(bpp == 3)
 1113    {
 1114       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
 1115                                 DDS_COMPRESS_NONE);
 1116       tmp2 = g_malloc(size);
 1117 
 1118       for(i = j = 0; j < size; i += 3, j += 4)
 1119       {
 1120          tmp2[j + 0] = tmp[i + 0];
 1121          tmp2[j + 1] = tmp[i + 1];
 1122          tmp2[j + 2] = tmp[i + 2];
 1123          tmp2[j + 3] = 255;
 1124       }
 1125 
 1126       g_free(tmp);
 1127       tmp = tmp2;
 1128       bpp = 4;
 1129    }
 1130 
 1131    offset = 0;
 1132    w = width;
 1133    h = height;
 1134    s = tmp;
 1135 
 1136    for(i = 0; i < mipmaps; ++i)
 1137    {
 1138       switch(format)
 1139       {
 1140          case DDS_COMPRESS_BC1:
 1141             compress_DXT1(dst + offset, s, w, h, type, dither, dxt1_alpha);
 1142             break;
 1143          case DDS_COMPRESS_BC2:
 1144             compress_DXT3(dst + offset, s, w, h, type, dither);
 1145             break;
 1146          case DDS_COMPRESS_BC3:
 1147             compress_DXT5(dst + offset, s, w, h, type, dither);
 1148             break;
 1149          case DDS_COMPRESS_BC4:
 1150             compress_BC4(dst + offset, s, w, h);
 1151             break;
 1152          case DDS_COMPRESS_BC5:
 1153             compress_BC5(dst + offset, s, w, h);
 1154             break;
 1155          case DDS_COMPRESS_YCOCGS:
 1156             compress_YCoCg(dst + offset, s, w, h);
 1157             break;
 1158          default:
 1159             compress_DXT5(dst + offset, s, w, h, type, dither);
 1160             break;
 1161       }
 1162       s += (w * h * bpp);
 1163       offset += get_mipmapped_size(w, h, 0, 0, 1, format);
 1164       if(w > 1) w >>= 1;
 1165       if(h > 1) h >>= 1;
 1166    }
 1167 
 1168    g_free(tmp);
 1169 
 1170    return(1);
 1171 }
 1172 
 1173 static void decode_color_block(unsigned char *dst, unsigned char *src,
 1174                                int w, int h, int rowbytes, int format)
 1175 {
 1176    int i, x, y;
 1177    unsigned int indexes, idx;
 1178    unsigned char *d;
 1179    unsigned char colors[4][3];
 1180    unsigned short c0, c1;
 1181 
 1182    c0 = GETL16(&src[0]);
 1183    c1 = GETL16(&src[2]);
 1184 
 1185    unpack_rgb565(colors[0], c0);
 1186    unpack_rgb565(colors[1], c1);
 1187 
 1188    if((c0 > c1) || (format == DDS_COMPRESS_BC3))
 1189    {
 1190       lerp_rgb(colors[2], colors[0], colors[1], 0x55);
 1191       lerp_rgb(colors[3], colors[0], colors[1], 0xaa);
 1192    }
 1193    else
 1194    {
 1195       for(i = 0; i < 3; ++i)
 1196       {
 1197          colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1;
 1198          colors[3][i] = 255;
 1199       }
 1200    }
 1201 
 1202    src += 4;
 1203    for(y = 0; y < h; ++y)
 1204    {
 1205       d = dst + (y * rowbytes);
 1206       indexes = src[y];
 1207       for(x = 0; x < w; ++x)
 1208       {
 1209          idx = indexes & 0x03;
 1210          d[0] = colors[idx][2];
 1211          d[1] = colors[idx][1];
 1212          d[2] = colors[idx][0];
 1213          if(format == DDS_COMPRESS_BC1)
 1214             d[3] = ((c0 <= c1) && idx == 3) ? 0 : 255;
 1215          indexes >>= 2;
 1216          d += 4;
 1217       }
 1218    }
 1219 }
 1220 
 1221 static void decode_alpha_block_DXT3(unsigned char *dst, unsigned char *src,
 1222                                     int w, int h, int rowbytes)
 1223 {
 1224    int x, y;
 1225    unsigned char *d;
 1226    unsigned int bits;
 1227 
 1228    for(y = 0; y < h; ++y)
 1229    {
 1230       d = dst + (y * rowbytes);
 1231       bits = GETL16(&src[2 * y]);
 1232       for(x = 0; x < w; ++x)
 1233       {
 1234          d[0] = (bits & 0x0f) * 17;
 1235          bits >>= 4;
 1236          d += 4;
 1237       }
 1238    }
 1239 }
 1240 
 1241 static void decode_alpha_block_DXT5(unsigned char *dst, unsigned char *src,
 1242                                     int w, int h, int bpp, int rowbytes)
 1243 {
 1244    int x, y, code;
 1245    unsigned char *d;
 1246    unsigned char a0 = src[0];
 1247    unsigned char a1 = src[1];
 1248    unsigned long long bits = GETL64(src) >> 16;
 1249 
 1250    for(y = 0; y < h; ++y)
 1251    {
 1252       d = dst + (y * rowbytes);
 1253       for(x = 0; x < w; ++x)
 1254       {
 1255          code = ((unsigned int)bits) & 0x07;
 1256          if(code == 0)
 1257             d[0] = a0;
 1258          else if(code == 1)
 1259             d[0] = a1;
 1260          else if(a0 > a1)
 1261             d[0] = ((8 - code) * a0 + (code - 1) * a1) / 7;
 1262          else if(code >= 6)
 1263             d[0] = (code == 6) ? 0 : 255;
 1264          else
 1265             d[0] = ((6 - code) * a0 + (code - 1) * a1) / 5;
 1266          bits >>= 3;
 1267          d += bpp;
 1268       }
 1269       if(w < 4) bits >>= (3 * (4 - w));
 1270    }
 1271 }
 1272 
 1273 int dxt_decompress(unsigned char *dst, unsigned char *src, int format,
 1274                    unsigned int size, unsigned int width, unsigned int height,
 1275                    int bpp)
 1276 {
 1277    unsigned char *d, *s;
 1278    unsigned int x, y, sx, sy;
 1279 
 1280    if(!(IS_POT(width) && IS_POT(height)))
 1281       return(0);
 1282 
 1283    sx = (width  < 4) ? width  : 4;
 1284    sy = (height < 4) ? height : 4;
 1285 
 1286    s = src;
 1287 
 1288    for(y = 0; y < height; y += 4)
 1289    {
 1290       for(x = 0; x < width; x += 4)
 1291       {
 1292          d = dst + (y * width + x) * bpp;
 1293          if(format == DDS_COMPRESS_BC1)
 1294          {
 1295             decode_color_block(d, s, sx, sy, width * bpp, format);
 1296             s += 8;
 1297          }
 1298          else if(format == DDS_COMPRESS_BC2)
 1299          {
 1300             decode_alpha_block_DXT3(d + 3, s, sx, sy, width * bpp);
 1301             s += 8;
 1302             decode_color_block(d, s, sx, sy, width * bpp, format);
 1303             s += 8;
 1304          }
 1305          else if(format == DDS_COMPRESS_BC3)
 1306          {
 1307             decode_alpha_block_DXT5(d + 3, s, sx, sy, bpp, width * bpp);
 1308             s += 8;
 1309             decode_color_block(d, s, sx, sy, width * bpp, format);
 1310             s += 8;
 1311          }
 1312          else if(format == DDS_COMPRESS_BC4)
 1313          {
 1314             decode_alpha_block_DXT5(d, s, sx, sy, bpp, width * bpp);
 1315             s += 8;
 1316          }
 1317          else if(format == DDS_COMPRESS_BC5)
 1318          {
 1319             decode_alpha_block_DXT5(d, s + 8, sx, sy, bpp, width * bpp);
 1320             decode_alpha_block_DXT5(d + 1, s, sx, sy, bpp, width * bpp);
 1321             s += 16;
 1322          }
 1323       }
 1324    }
 1325 
 1326    return(1);
 1327 }

ViewVC Help
Powered by ViewVC 1.0.4