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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

ViewVC Help
Powered by ViewVC 1.0.4